Skip to content

Gateway API + LB-IPAM: cilium-gateway Service LoadBalancer IP flaps (release/re-assign ~1/s), breaking BGP service advertisement (v1.5.2) #3307

Open

Description

@lfinmauritius

Summary

On Cozystack v1.5.2 with the Gateway API publishing path enabled (tenant.spec.gateway: true + platform gateway.enabled: true), the LB-IPAM assignment on the generated cilium-gateway-* Service flaps continuously: status.loadBalancer.ingress alternates between the assigned IP and empty every 1–2 seconds, indefinitely. Any consumer of the Service status is broken by this — in our case the Cilium BGP control plane (v2 CRDs) advertises and withdraws the /32 route ~2 times per second (our upstream FRR router logged 520 BGP UPDATE messages in under 4 minutes for a single prefix), making BGP-based LoadBalancer reachability unusable.

This looks like the "known-bad interaction between LB-IPAM and Gateway" mentioned as out-of-scope in #2586 — opening this issue since we could not find a dedicated tracking issue, and we have a fairly complete reproduction + diagnosis.

Environment

  • Cozystack v1.5.2 (variant isp-full), installed via cozy-installer Helm chart
  • Talos v1.13.0 (Cozystack nocloud image), Kubernetes v1.34.3
  • 3 combined control-plane+worker nodes (Proxmox VE, 8 vCPU / 32 GB each, 2 NICs: mgmt + external)
  • Cilium: Cozystack build cilium:v1.5.2 (Cilium 1.19.3), operator quay.io/cilium/operator-generic:v1.19.3 (also reproduced with operator v1.19.5)
  • Networking: default kubeovn-cilium variant (Kube-OVN primary CNI + Cilium chained, kube-proxy replacement, routing-mode=native)

Configuration

  • Tenant root: gateway: true → TenantGateway → Gateway tenant-root/cozystack (class cilium), certMode: existingSecret (wildcard secret)
  • Platform package: gateway.enabled: true, attachedNamespaces per docs → dashboard published via HTTPRoute (works)
  • CiliumLoadBalancerIPPool with a single /32 block; the generated Service tenant-root/cilium-gateway-cozystack gets that IP
  • Cilium BGP control plane enabled with CiliumBGPClusterConfig / CiliumBGPPeerConfig / CiliumBGPAdvertisement (advertisementType: Service, addresses: [LoadBalancerIP]), eBGP peering with an FRR router — sessions establish fine from all 3 nodes
  • externalTrafficPolicy of the gateway Service is Cluster (so not Gateway API and BGP control plane cilium/cilium#36804)

Observed behaviour

  1. Sampling the Service once per second shows the LB IP flapping (empty ↔ assigned, several transitions per 20 s window):
[1] ip=172.16.255.253
[2] ip=
[3] ip=172.16.255.253
[4] ip=
[5] ip=172.16.255.253
...
  1. cilium-operator logs show a tight reconcile loop (~1/s, continuous, no errors):
level=info msg="Reconciling Gateway" ... controller=gateway resource=tenant-root/cozystack
level=info msg="Successfully reconciled Gateway" ...
level=info msg="Reconciling GAMMA service" ... controller=gamma resource=tenant-root/cilium-gateway-cozystack
(repeats forever, ~40 "Reconciling Gateway" per minute)
  1. managedFields captured at the moment the status is empty show cilium-operator-lb-ipam is the only writer of status (owning an empty f:loadBalancer.f:ingress), i.e. LB-IPAM itself releases and re-assigns the IP on every Service update performed by the gateway/GAMMA reconcilers.

  2. The BGP speaker faithfully follows the Service status → advertise/withdraw storm. FRR peer stats: Updates Rcvd: 520 within a ~4 min session for one prefix. External reachability alternates between working / connection refused / no route to host.

  3. Notably, the datapath is unaffected: the BPF service entry for the VIP stays programmed the whole time; with a static route to a node IP, HTTPS requests to the VIP return 302/200 consistently while the status keeps flapping.

What we ruled out / tried

  • externalTrafficPolicy is Cluster (not the Gateway API and BGP control plane cilium/cilium#36804 case)
  • Restarting cilium agents: no change (datapath resync ok, flap continues)
  • Restarting cilium-operator: no change
  • Pinning the IP with lbipam.cilium.io/ips on the Service: annotation persists, flap continues
  • Adding spec.externalIPs to advertise via ExternalIP instead: the gateway controller's periodic re-apply removes the field within ~40 s (SSA prune), so no stable workaround on the Service object itself
  • Bumping only the operator to quay.io/cilium/operator-generic:v1.19.5: reconcile loop and flap unchanged
  • k8s client rate limit raised (k8sClientRateLimit: qps 100 / burst 200) and L2-announcement lease timers relaxed earlier in the investigation: unrelated to this loop

Expected behaviour

The cilium-gateway-* Service should keep its LB-IPAM address stably; gateway/GAMMA reconciliation should not cause LB-IPAM to release/re-assign the IP, so that BGP service advertisement (and anything else reading status.loadBalancer) is stable.

Questions

Workaround we settled on

Static route for the VIP /32 towards a node IP on the external network (datapath is stable), keeping the established BGP sessions in place for when the fix lands.

Activity

  1. lfinmauritius commented on Jul 15, 2026

    @lfinmauritius
    ContributorAuthor

    Follow-up with additional findings that narrow the bug down to LB-IPAM itself, independent of the Gateway API controllers:

    The flap reproduces with Gateway API fully disabled

    After rolling back platform publishing to ingress-nginx (gateway.enabled: false, tenant gateway: false, TenantGateway/Gateway deleted) and disabling the Cilium Gateway API controllers entirely (gatewayAPI.enabled: false → enable-gateway-api removed from cilium-config, gateway/GAMMA reconcilers no longer running, confirmed 0 reconcile log lines), the same release/re-assign cycle continued on the ingress-nginx LoadBalancer Service (tenant-root/root-ingress-controller): status.loadBalancer.ingress still alternated between the assigned IP and empty every 1–2 s at full cluster quiescence (measured 7 transitions over a 30 s window, no HR reconciliations in progress, no Service spec changes).

    So the gateway/GAMMA reconcile churn amplifies the issue (more Service update events → more cycles), but the release/re-assign behaviour is in LB-IPAM's own reconcile path on this build (Cozystack cilium:v1.5.2, Cilium 1.19.3). Also reproduced with quay.io/cilium/operator-generic:v1.19.5 (operator-only bump): no change.

    Side-effect worth noting: hours of this churn progressively corrupted the datapath — we captured return packets leaving with pod IPs instead of the reverse-NATed VIP (BPF conntrack inconsistencies), fixed transiently by restarting the cilium DaemonSet, but degrading again while the churn continued.

    Workaround that gives full stability on v1.5.2

    Remove LB-IPAM from the picture entirely:

    1. Pin the VIP on the Service spec: kubectl patch svc root-ingress-controller -n tenant-root --type merge -p '{"spec":{"externalIPs":["<VIP>"],"externalTrafficPolicy":"Cluster"}}'
    2. Delete the CiliumLoadBalancerIPPool (no pool → no allocation → nothing left to flap).
    3. BGP CiliumBGPAdvertisement with service.addresses: [LoadBalancerIP, ExternalIP] → the ExternalIP is advertised continuously.

    Result: BGP announcement stable (5/5 over 30 s vs 6/10 before), datapath steady at ~9 ms, no pod-IP leaks after a final agent restart. Note this pinning is only viable on the nginx Service — on the Gateway-generated Service the controller's periodic server-side apply prunes foreign fields (spec.externalIPs was removed within ~40 s), which is also what feeds LB-IPAM with a constant stream of update events.

    Happy to test a patched build — the environment reproduces the issue within minutes.

  2. added
    area/ciliumIssues or PRs related to Cilium (agent, operator, Gateway API, network policy, LB-IPAM)
    on Aug 19, 2026
  3. added
    kind/bugCategorizes issue or PR as related to a bug
    triage/acceptedIndicates an issue is ready to be actively worked on
    priority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next release
    and removed
    triage/needs-triageIndicates an issue needs triage by a maintainer
    on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area/ciliumIssues or PRs related to Cilium (agent, operator, Gateway API, network policy, LB-IPAM)kind/bugCategorizes issue or PR as related to a bugpriority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next releasetriage/acceptedIndicates an issue is ready to be actively worked on

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions