Skip to content

fix: derive the protocol of active health checks from the backend - #9806

Draft
zhaohuabing wants to merge 1 commit into
envoyproxy:mainfrom
zhaohuabing:hc-protocol-version-api
Draft

fix: derive the protocol of active health checks from the backend#9806
zhaohuabing wants to merge 1 commit into
envoyproxy:mainfrom
zhaohuabing:hc-protocol-version-api

Conversation

@zhaohuabing

@zhaohuabing zhaohuabing commented Aug 20, 2026

Copy link
Copy Markdown
Member

Envoy Gateway doesn't configure the protocol used for active health checks, so Envoy falls back to its default and sends every health check request as HTTP/1.1. Health checks against a backend that speaks HTTP/2 on its health check endpoint fail, and all of its endpoints are marked unhealthy.

Envoy Gateway now derives the health check protocol from the backend protocol:

  • http_health_check.codec_client_type is set to HTTP2 for backends that use HTTP/2, and to HTTP1 otherwise.
  • For backends that use TLS, tls_options.alpn_protocols is set to the protocol matching the codec, h2 or http/1.1, so that the protocol negotiated during the health check handshake is the one Envoy uses to send the request. It's left unset when the backend TLS settings ask for an ALPN protocol that the codec can't speak, such as istio, since overriding the ALPN would break the handshake.
  • gRPC health checks are always sent over HTTP/2 by Envoy, so TLS backends get h2.

The new healthCheck.active.http.version field (Auto | HTTP1 | HTTP2, defaults to Auto) overrides the derived version, for backends that serve a different protocol on their health check endpoint than on the data path.

Note: since this PR introduces API changes, I'll raise a follow-up non-API change PR for v1.8/v1.9 only, and use the Auto default strategy.

@zhaohuabing
zhaohuabing requested a review from a team as a code owner August 20, 2026 06:58
@netlify

netlify Bot commented Aug 20, 2026

Copy link
Copy Markdown

Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit c07f0ba
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/6a86b2a779ed4d0008337866
😎 Deploy Preview https://deploy-preview-9806--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@zhaohuabing
zhaohuabing marked this pull request as draft August 20, 2026 06:59
@zhaohuabing
zhaohuabing force-pushed the hc-protocol-version-api branch from 34e59c0 to fb840dd Compare August 20, 2026 07:24
@zhaohuabing zhaohuabing changed the title api: add protocol version and TLS settings to active health check api: add protocol version to active HTTP health check Aug 20, 2026
@zhaohuabing zhaohuabing changed the title api: add protocol version to active HTTP health check api/fix: add protocol version to active HTTP health check Aug 20, 2026
@zhaohuabing
zhaohuabing force-pushed the hc-protocol-version-api branch from fb840dd to 3f0c5e2 Compare August 20, 2026 07:40
@zhaohuabing zhaohuabing changed the title api/fix: add protocol version to active HTTP health check fix: derive the protocol of active health checks from the backend Aug 20, 2026
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.47368% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.35%. Comparing base (2b40195) to head (c07f0ba).

Files with missing lines Patch % Lines
internal/xds/translator/cluster.go 88.57% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9806      +/-   ##
==========================================
+ Coverage   76.34%   76.35%   +0.01%     
==========================================
  Files         261      261              
  Lines       44440    44474      +34     
==========================================
+ Hits        33927    33960      +33     
- Misses       8269     8272       +3     
+ Partials     2244     2242       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Envoy sends HTTP health check requests with a codec that is fixed when the
health checker is created, and health check connections are created outside
of the connection pool, so they don't inherit the ALPN protocols that the
pool derives from the backend protocol settings. Envoy Gateway configures
neither, so health checks are sent as HTTP/1.1 and fail against a backend
that speaks HTTP/2 on its health check endpoint, marking all of its
endpoints unhealthy.

Derive both from the backend protocol: `codec_client_type` is set to HTTP2
for backends that use HTTP/2 and to HTTP1 otherwise, and for backends that
use TLS, `tls_options.alpn_protocols` is pinned to the protocol matching the
codec, so the protocol negotiated during the handshake is the one Envoy uses
to send the request. The ALPN isn't pinned when the backend TLS settings ask
for a protocol that the codec can't speak, such as `istio`, since overriding
it would break the handshake. gRPC health checks are always sent over
HTTP/2, so TLS backends get `h2`.

Add `healthCheck.active.http.version` to select the version explicitly, for
backends whose health check endpoint uses a different protocol than their
application endpoint.

Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
@zhaohuabing
zhaohuabing force-pushed the hc-protocol-version-api branch from 3f0c5e2 to c07f0ba Compare August 20, 2026 07:54
@zhaohuabing

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c07f0ba46d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +492 to +493
upstreamHTTP2 := requiresHTTP2Options && !forceHTTP1UpstreamProtocol
cluster.HealthChecks, err = buildXdsHealthCheck(args.healthCheck.Active, args.routeHostname, args.healthCheckLog, args.settings, upstreamHTTP2)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Honor useClientProtocol when deriving the health-check codec

When useClientProtocol is enabled on a route whose BackendRef indicates HTTP/2, requiresHTTP2Options remains true even though the protocol-options switch later gives useClientProtocol precedence. Consequently an HTTP/1 downstream request is forwarded upstream with HTTP/1 while the active health check is fixed to HTTP/2; an HTTP/1-only health endpoint then fails every probe and all endpoints are marked unhealthy. The Auto derivation needs to account for args.useClientProtocol rather than treating the BackendRef protocol as the effective fixed protocol.

Useful? React with 👍 / 👎.

//
// +kubebuilder:default=Auto
// +optional
Version *HTTPHealthCheckVersion `json:"version,omitempty" yaml:"version,omitempty"`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thoughts on Protocol ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants