Skip to content

Gateway API: ListenerSet creation does not trigger TLS Secret synchronization #47622

Description

@vchrisb

What happened?

TLS Secrets referenced only by Gateway API ListenerSets are not synchronized into the configured cilium-secrets namespace when the Secret already exists before the ListenerSet is created.

The ListenerSets report Accepted=True, Programmed=True, and ResolvedRefs=True. Cilium also generates a CiliumEnvoyConfig containing the expected TLS filter chains and SDS secret names. However, the referenced cilium-sync-secret-* resources do not exist, so Envoy resets TLS connections during ClientHello.

Restarting the Cilium operator causes its initial Secret watch to reconcile the existing Secrets. All synchronized Secrets are then created immediately and HTTPS starts working without restarting Envoy.

Expected behavior

Creating or updating a ListenerSet should enqueue all TLS Secrets in spec.listeners[].tls.certificateRefs for synchronization, regardless of whether the Secret or ListenerSet was created first. A listener should also not report Programmed=True if its required SDS Secret is unavailable.

Reproduction

  1. Install the ListenerSet CRD before starting the Cilium operator.
  2. Enable Gateway API secret synchronization with gatewayAPI.secretsNamespace.sync=true.
  3. Create a Gateway that accepts ListenerSets.
  4. Create a valid kubernetes.io/tls Secret in an application namespace.
  5. Wait until the Secret exists.
  6. Create a ListenerSet in that namespace whose HTTPS listener references the existing Secret.
  7. Attach an HTTPRoute to the ListenerSet.
  8. Observe that the ListenerSet becomes Accepted, ResolvedRefs, and Programmed.
  9. Observe that the generated CiliumEnvoyConfig references a hashed Secret in cilium-secrets, but that Secret was not created.
  10. A TLS request resets during ClientHello.
  11. Restart the Cilium operator. The synchronized Secret is created and the same request succeeds.

This was reproduced with five ListenerSets/Secrets across multiple namespaces. The source Secrets were created several minutes before the ListenerSets. After one operator restart, all five synchronized Secrets appeared at the same timestamp and all HTTPS listeners became reachable.

Suspected cause

SecretSyncHandler.IsReferencedByGateway uses helpers.GetGatewaysForSecret, which accounts for ListenerSets through ListenerSetSecretIndex. Thus a source Secret event can discover its ListenerSet reference.

However, SecretSyncHandler.EnqueueTLSSecrets only accepts *gatewayv1.Gateway and walks gw.Spec.Listeners. The secret-sync registration watches Gateway reference objects, but does not appear to add ListenerSet as an additional watch that enqueues ListenerSet certificate references. Therefore creating the ListenerSet after the source Secret produces no secret-sync reconciliation event.

Relevant source:

The same relevant code appears unchanged on main at the time of filing.

Workaround

Restart the Cilium operator, or update the source TLS Secret after the ListenerSet exists, to trigger Secret reconciliation.

Environment

  • Cilium operator: quay.io/cilium/operator-generic:v1.20.0
  • Cilium commit reported by the running components: 450c5314
  • Kubernetes server: v1.36.2
  • ListenerSet storage API version: gateway.networking.k8s.io/v1
  • enable-gateway-api=true
  • enable-gateway-api-secrets-sync=true
  • gateway-api-secrets-namespace=cilium-secrets

Metadata

Metadata

Assignees

Labels

area/servicemeshGH issues or PRs regarding servicemeshfeature/k8s-gateway-apikind/bugThis is a bug in the Cilium logic.kind/community-reportThis was reported by a user in the Cilium community, eg via Slack.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions