You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Description:
During an upgrade from Envoy Gateway 1.9.0 to 1.9.1, we noticed a spike in TLS handshake errors. Root cause is the same class of bug as #9519 — pod readiness/liveness never checks whether SDS has actually delivered certificates — but via a different trigger: a brand-new pod's very first SDS fetch on cold start, racing a mass simultaneous pod restart, rather than #9519's stale delta-ADS re-subscription on a long-running proxy. Filing separately since the trigger and recovery profile are meaningfully different, but linking as clearly related.
Once the upgrade rollout had finished the TLS handshake errors went away.
Failure mechanism:
Trigger — routine version upgrade. We applied the Envoy Gateway 1.9.0 → 1.9.1 update to our cluster. This rolled all proxy pods to a new ReplicaSet.
Mass simultaneous cold start. All new pods started at once, each needing to fetch ~53 distinct SDS secrets (TLS certs for our configured Gateways/HTTPRoutes) from the envoy-gateway control plane simultaneously — i.e. ~477 concurrent initial SDS fetches hitting the control plane at once.
Readiness passes independent of SDS state. Per internal/xds/translator/listener_ready.go and internal/xds/filters/wellknown.go, the readiness listener uses the stock health_check HTTP filter with PassThroughMode: false — it answers purely from the Envoy process's own liveness flag, with no dependency on LDS/SDS convergence. So every pod passed Kubernetes readiness almost immediately, well before its 53 SDS secrets had loaded, and was added to the Service endpoints.
Real traffic hits listeners with SDS still outstanding. With the mass fetch contending against the control plane, a meaningful number of those initial fetches took long enough to hit the (correctly, per 1.9.1's fix) reverted 15s initial_fetch_timeout for SDS. Per GrpcSubscriptionImpl::onConfigUpdateFailed (Envoy core), a timed-out initial fetch still unblocks the init manager — so the listener becomes "active" without ever having received a valid cert for the affected filter chain. Live TLS handshakes against that pod failed until the pod's retry succeeded.
Install Envoy Gateway v1.9.1+ with a Gateway/HTTPRoute configuration referencing a non-trivial number of TLS secrets — we saw this reliably with ~50 per proxy pod; a handful may not create enough control-plane fetch contention to lose the race, so scale up if it doesn't reproduce at low secret counts.
Send steady TLS traffic to the Gateway's listener(s) so there's something to observe failing.
Trigger a rollout of all proxy pods at once so many pods request their initial SDS secrets from the control plane at the same moment.
While the rollout is in progress, in parallel:
Tail the new pods' logs for gRPC config: initial fetch timed out for type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret.
Poll each new pod's readiness endpoint (the port/path configured via bootstrap.EnvoyReadinessPort/EnvoyReadinessPath, exposed at the Kubernetes readiness probe) — it will report healthy immediately, before and during the SDS timeout warnings.
Send real TLS requests directly at each new pod's Service IP (bypassing any external LB retry/failover) as it becomes "Ready," to observe handshake failures independent of upstream retry logic masking the issue.
Logs:
Proxy log (representative — reconstructed from Envoy's source-level format at source/extensions/config_subscription/grpc/grpc_subscription_impl.cc:130 plus our aggregated log-count evidence; we have counts per pod via our log platform, not a saved verbatim capture of a single raw line):
[2026-08-28 14:08:2X.XXX][1][warning][config] [source/extensions/config_subscription/grpc/grpc_subscription_impl.cc:130] gRPC config: initial fetch timed out for type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret
This line repeated exactly 53 times in immediate succession per new pod — once per configured TLS secret — within the first couple of seconds after each pod's readiness probe had already started reporting healthy.
Description:
During an upgrade from Envoy Gateway 1.9.0 to 1.9.1, we noticed a spike in TLS handshake errors. Root cause is the same class of bug as #9519 — pod readiness/liveness never checks whether SDS has actually delivered certificates — but via a different trigger: a brand-new pod's very first SDS fetch on cold start, racing a mass simultaneous pod restart, rather than #9519's stale delta-ADS re-subscription on a long-running proxy. Filing separately since the trigger and recovery profile are meaningfully different, but linking as clearly related.
Once the upgrade rollout had finished the TLS handshake errors went away.
Failure mechanism:
internal/xds/translator/listener_ready.goandinternal/xds/filters/wellknown.go, the readiness listener uses the stockhealth_checkHTTP filter withPassThroughMode: false— it answers purely from the Envoy process's own liveness flag, with no dependency on LDS/SDS convergence. So every pod passed Kubernetes readiness almost immediately, well before its 53 SDS secrets had loaded, and was added to the Service endpoints.initial_fetch_timeoutfor SDS. PerGrpcSubscriptionImpl::onConfigUpdateFailed(Envoy core), a timed-out initial fetch still unblocks the init manager — so the listener becomes "active" without ever having received a valid cert for the affected filter chain. Live TLS handshakes against that pod failed until the pod's retry succeeded.Repro steps:
Environment:
Envoy Gateway 1.9.1
Logs:
Proxy log (representative — reconstructed from Envoy's source-level format at source/extensions/config_subscription/grpc/grpc_subscription_impl.cc:130 plus our aggregated log-count evidence; we have counts per pod via our log platform, not a saved verbatim capture of a single raw line):
This line repeated exactly 53 times in immediate succession per new pod — once per configured TLS secret — within the first couple of seconds after each pod's readiness probe had already started reporting healthy.