Skip to content

fix: use per-endpoint hostname for health checks with auto-host-rewrite#8851

Closed
albsga4 wants to merge 6 commits into
envoyproxy:mainfrom
albsga4:fix/healthcheck-auto-host-rewrite
Closed

fix: use per-endpoint hostname for health checks with auto-host-rewrite#8851
albsga4 wants to merge 6 commits into
envoyproxy:mainfrom
albsga4:fix/healthcheck-auto-host-rewrite

Conversation

@albsga4

@albsga4 albsga4 commented Apr 24, 2026

Copy link
Copy Markdown

What type of PR is this?

fix: health check Host header for external backends with hostname.type: Backend

What this PR does / why we need it:

When hostname.type: Backend (auto-host-rewrite) is configured on an HTTPRoute, active health checks currently send the route hostname as the Host header instead of the backend endpoint FQDN. This causes health checks to fail for external backends that validate the Host header.

The root cause: SetHTTPHostIfAbsent(r.Hostname) in backendtrafficpolicy.go always sets the health check Host to the route hostname. The per-endpoint hostname fallback in getHealthCheckOverridesHostname (#8452) only triggers when HTTP.Host is empty — which it never is, because SetHTTPHostIfAbsent already filled it.

Fix:

Add HostFrom field (Endpoint | Route) to the ActiveHealthCheck IR struct. When the route has hostname.type: Backend configured and the user didn't explicitly set healthCheck.active.http.hostname:

  1. backendtrafficpolicy.go sets HostFrom = Endpoint on the health check
  2. SetHTTPHostIfAbsent still runs (cluster-level host is set, IR validation passes)
  3. getHealthCheckOverridesHostname checks HostFrom — when Endpoint, it returns the endpoint FQDN as per-endpoint HealthCheckConfig.Hostname
  4. Envoy's per-endpoint hostname overrides the cluster-level host for health checks
  5. If the user explicitly sets http.hostname, it takes precedence (HostFrom is not set)

Tested scenarios:

Config Cluster-level host Per-endpoint hc_hostname Result
FQDN backend + hostname.type: Backend route hostname (fallback) endpoint FQDN NEW — per-endpoint wins
FQDN backend, no auto-host-rewrite route hostname (none) Unchanged
FQDN backend + explicit http.hostname user's value (none) User's explicit value wins
Static URLRewrite hostname route hostname (none) Unchanged

All scenarios verified on a live cluster with multi-cell FQDN backends.

Changes:

  • internal/ir/xds.goHealthCheckHostFrom type + HostFrom field on ActiveHealthCheck + SetActiveHostFrom method
  • internal/gatewayapi/backendtrafficpolicy.go — set HostFrom = Endpoint when routeHasBackendHostRewrite && !hasExplicitHealthCheckHostname
  • internal/xds/translator/cluster.gogetHealthCheckOverridesHostname checks HostFrom
  • New test: backendtrafficpolicy-with-healthcheck-auto-host-rewrite exercising HostFrom with auto-host-rewrite
  • Includes health check testdata from fix: HealthCheck should respect endpoint hostname #8854
  • Deepcopy regenerated, release note added

Which issue(s) this PR fixes:

Fixes #8848

Release Notes: Yes

/cc @arkodg @zirain

When hostname.type: Backend (auto-host-rewrite) is configured on an
HTTPRoute, health checks now use the backend endpoint FQDN as the
Host header instead of the route hostname.

Add HostFrom field (Endpoint|Route) to ActiveHealthCheck IR. When the
route has auto-host-rewrite, HostFrom is set to Endpoint, and the xDS
translator sets per-endpoint HealthCheckConfig.Hostname to override
the cluster-level Host header.

Also auto-derives DestinationEndpoint.Hostname from FQDN.Hostname when
not explicitly set, so the endpoint always has a hostname available.

Routes without auto-host-rewrite are unchanged — they continue to use
the route hostname for health checks.

Fixes envoyproxy#8848

Signed-off-by: asalvador <[email protected]>
@albsga4 albsga4 requested a review from a team as a code owner April 24, 2026 17:46
@netlify

netlify Bot commented Apr 24, 2026

Copy link
Copy Markdown

Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit c5f55db
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/69ec187b27f2e50008e2632f
😎 Deploy Preview https://deploy-preview-8851--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.

@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: 7412be8124

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/xds/translator/cluster.go
albsga4 added 2 commits April 24, 2026 21:10
When the user explicitly sets healthCheck.active.http.hostname in the
BackendTrafficPolicy, it should take precedence over the per-endpoint
FQDN even when hostname.type: Backend is configured. Only set
HostFrom=Endpoint when the user didn't provide an explicit hostname.

Signed-off-by: asalvador <[email protected]>
@albsga4

albsga4 commented Apr 24, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@zirain

zirain commented Apr 25, 2026

Copy link
Copy Markdown
Member

looks good to me, can you include the testdata changes from #8854 and make CI happy?

@albsga4

albsga4 commented Apr 25, 2026

Copy link
Copy Markdown
Author

Thanks @zirain! Including testdata from #8854 in the next push.

Also found and fixing an issue: the initial commit auto-derived DestinationEndpoint.Hostname from FQDN.Hostname in route.go, which changed IR output for all FQDN backends and broke existing golden tests. Removing that — not needed since users with hostname.type: Backend already set endpoint.hostname explicitly.

Next push will have:

…ostFrom test

- Remove auto-derive of DestinationEndpoint.Hostname from FQDN in
  route.go (changed IR output for all FQDN backends unnecessarily)
- Include health check testdata from envoyproxy#8854 (by @zirain)
- Add backendtrafficpolicy-with-healthcheck-auto-host-rewrite test
  exercising HostFrom=Endpoint with hostname.type: Backend

Signed-off-by: asalvador <[email protected]>
// (auto-host-rewrite) configured, meaning the backend FQDN should be used as the
// Host header for both requests and health checks.
func routeHasBackendHostRewrite(r *ir.HTTPRoute) bool {
return r.URLRewrite != nil &&

@zirain zirain Apr 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

URLRewrite could happend per-route and per-backend, we need to handle both.

@albsga4 albsga4 Apr 25, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point. For this PR, routeHasBackendHostRewrite checks route-level URLRewrite since that's where hostname.type: Backend is set — the signal that health checks should use the per-endpoint FQDN.

Per-backend static URLRewrite (urlRewrite.hostname: example.com) sets a fixed Host for forwarding but doesn't change the health check Host, since health checks apply at the cluster level from the BTP.

@zirain

zirain commented Apr 25, 2026

Copy link
Copy Markdown
Member

@albsga4 I'm sorry, can you update the testdata from #8854, I add a new test case that host rewrite happen on route rule.

@codecov

codecov Bot commented Apr 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.47619% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.41%. Comparing base (cab6837) to head (c5f55db).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
internal/gatewayapi/backendtrafficpolicy.go 85.71% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8851      +/-   ##
==========================================
+ Coverage   74.39%   74.41%   +0.01%     
==========================================
  Files         246      246              
  Lines       39221    39240      +19     
==========================================
+ Hits        29180    29200      +20     
+ Misses       8017     8015       -2     
- Partials     2024     2025       +1     

☔ View full report in Codecov by Sentry.
📢 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.

socketAddress:
address: example2.com
portValue: 3001
hostname: example2.com

@zirain zirain Apr 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Corrent me if I'm wrong, rule-1 has a rule level host rewrite, should adopt endpoint host.

socketAddress:
address: example3.com
portValue: 3001
healthCheckConfig:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Corrent me if I'm wrong, for rule-0, host rewrite happend on backend level, example3 shouldn't has endpoint level healthCheckConfig.

@albsga4

albsga4 commented Apr 25, 2026

Copy link
Copy Markdown
Author

@zirain Thanks for the detailed review. To clarify the scope of this PR:

Case Health check Host Workaround?
No rewrite Route hostname Works as-is
Explicit http.hostname set User's value User controls it
Static urlRewrite.hostname: X (route or backend level) Route hostname Set http.hostname: X — target is known
hostname.type: Backend (auto-host-rewrite) Route hostname (wrong) No workaround — each endpoint has a different FQDN

This PR addresses the only case with no workaround: hostname.type: Backend where each endpoint has a different FQDN. A single static http.hostname can't cover multiple endpoints.

For static urlRewrite.hostname: X, the target is a known fixed value — the user can set http.hostname: X to match. Same for per-backend static URLRewrite.

Happy to expand to other rewrite cases in a follow-up if needed, but wanted to keep this PR focused on the gap that has no existing solution.

- path:
value: "/v2"
filters:
- type: ExtensionRef

@zirain zirain Apr 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I cannot recall, but can we use this filter in BackendRef only?

cc @arkodg

@zirain

zirain commented Apr 25, 2026

Copy link
Copy Markdown
Member

@albsga4 I rework #8854 to address all this issue, can you help to review it?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Health check Host header should use backend endpoint FQDN when auto-host-rewrite is configured

2 participants