fix: use per-endpoint hostname for health checks with auto-host-rewrite#8851
fix: use per-endpoint hostname for health checks with auto-host-rewrite#8851albsga4 wants to merge 6 commits into
Conversation
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]>
✅ Deploy Preview for cerulean-figolla-1f9435 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
💡 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".
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]>
Signed-off-by: asalvador <[email protected]>
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
|
looks good to me, can you include the testdata changes from #8854 and make CI happy? |
|
Thanks @zirain! Including testdata from #8854 in the next push. Also found and fixing an issue: the initial commit auto-derived 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 && |
There was a problem hiding this comment.
URLRewrite could happend per-route and per-backend, we need to handle both.
There was a problem hiding this comment.
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.
Codecov Report❌ Patch coverage is
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. 🚀 New features to boost your workflow:
|
Signed-off-by: asalvador <[email protected]>
Signed-off-by: asalvador <[email protected]>
| socketAddress: | ||
| address: example2.com | ||
| portValue: 3001 | ||
| hostname: example2.com |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
Corrent me if I'm wrong, for rule-0, host rewrite happend on backend level, example3 shouldn't has endpoint level healthCheckConfig.
|
@zirain Thanks for the detailed review. To clarify the scope of this PR:
This PR addresses the only case with no workaround: For static 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 |
There was a problem hiding this comment.
I cannot recall, but can we use this filter in BackendRef only?
cc @arkodg
What type of PR is this?
fix: health check Host header for external backends withhostname.type: BackendWhat 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)inbackendtrafficpolicy.goalways sets the health check Host to the route hostname. The per-endpoint hostname fallback ingetHealthCheckOverridesHostname(#8452) only triggers whenHTTP.Hostis empty — which it never is, becauseSetHTTPHostIfAbsentalready filled it.Fix:
Add
HostFromfield (Endpoint|Route) to theActiveHealthCheckIR struct. When the route hashostname.type: Backendconfigured and the user didn't explicitly sethealthCheck.active.http.hostname:backendtrafficpolicy.gosetsHostFrom = Endpointon the health checkSetHTTPHostIfAbsentstill runs (cluster-level host is set, IR validation passes)getHealthCheckOverridesHostnamechecksHostFrom— whenEndpoint, it returns the endpoint FQDN as per-endpointHealthCheckConfig.Hostnamehttp.hostname, it takes precedence (HostFrom is not set)Tested scenarios:
hostname.type: Backendhttp.hostnameAll scenarios verified on a live cluster with multi-cell FQDN backends.
Changes:
internal/ir/xds.go—HealthCheckHostFromtype +HostFromfield onActiveHealthCheck+SetActiveHostFrommethodinternal/gatewayapi/backendtrafficpolicy.go— setHostFrom = EndpointwhenrouteHasBackendHostRewrite && !hasExplicitHealthCheckHostnameinternal/xds/translator/cluster.go—getHealthCheckOverridesHostnamechecksHostFrombackendtrafficpolicy-with-healthcheck-auto-host-rewriteexercising HostFrom with auto-host-rewriteWhich issue(s) this PR fixes:
Fixes #8848
Release Notes: Yes
/cc @arkodg @zirain