Skip to content

feat(api): add healthCheckNodePort to EnvoyProxy service spec#8843

Open
electricjesus wants to merge 2 commits intoenvoyproxy:mainfrom
electricjesus:feat-service-hcnp
Open

feat(api): add healthCheckNodePort to EnvoyProxy service spec#8843
electricjesus wants to merge 2 commits intoenvoyproxy:mainfrom
electricjesus:feat-service-hcnp

Conversation

@electricjesus
Copy link
Copy Markdown

What type of PR is this?
feat (api)

What this PR does / why we need it:

Adds a new HealthCheckNodePort *int32 field to KubernetesServiceSpec, forwarded to corev1.ServiceSpec.HealthCheckNodePort in the generated Envoy Service. This lets users pin the health-check NodePort to a known value so it can be allowlisted in network policies or firewall rules — a common requirement when running Envoy Gateway with cloud or on-prem load balancers that probe nodes via NodePort (bare-metal, MetalLB, kube-vip, etc.).

Without this, Kubernetes auto-allocates healthCheckNodePort from the cluster NodePort range (default 30000–32767) whenever type: LoadBalancer + externalTrafficPolicy: Local. The allocated port is unpredictable across deployments and restarts, so operators end up either opening the entire NodePort range or resorting to the EnvoyService.Patch escape hatch. Setting allocateLoadBalancerNodePorts: false doesn't help, since it only controls the per-service-port NodePorts — not the health-check NodePort (k8s tracks those in separate allocators).

A CEL validation rule restricts the new field to type: LoadBalancer with externalTrafficPolicy: Local (or unset — the default is Local), matching Kubernetes' own validation rules. When the field is unset, behavior is unchanged.

Changes:

  • api/v1alpha1/shared_types.go: add field, CEL rule, range validation (1–65535)
  • internal/infrastructure/kubernetes/resource/resource.go: forward the field in ExpectedServiceSpec
  • Unit test covering the new mapping
  • Regenerated zz_generated.deepcopy.go, CRD manifests, helm-template fixtures, and API docs

Which issue(s) this PR fixes:
Fixes #8842

Release Notes: Yes

Allows specifying a fixed health-check NodePort on the Envoy Service
when type is LoadBalancer and externalTrafficPolicy is Local. Without
this, kube-apiserver auto-allocates the port from the cluster NodePort
range, making it hard to allowlist in network policies or firewall
rules.

A CEL validation rule restricts the field to type: LoadBalancer with
externalTrafficPolicy: Local, matching Kubernetes' own rules. When
unset, behavior is unchanged and Kubernetes continues to auto-allocate.

Fixes envoyproxy#8842

Signed-off-by: Seth Malaki <seth@tigera.io>
@electricjesus electricjesus requested a review from a team as a code owner April 24, 2026 09:29
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 24, 2026

Deploy Preview for cerulean-figolla-1f9435 ready!

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

Copy link
Copy Markdown

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

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: adb0e10cd6

ℹ️ 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".

// +kubebuilder:validation:XValidation:message="allocateLoadBalancerNodePorts can only be set for LoadBalancer type",rule="!has(self.allocateLoadBalancerNodePorts) || self.type == 'LoadBalancer'"
// +kubebuilder:validation:XValidation:message="loadBalancerSourceRanges can only be set for LoadBalancer type",rule="!has(self.loadBalancerSourceRanges) || self.type == 'LoadBalancer'"
// +kubebuilder:validation:XValidation:message="loadBalancerIP can only be set for LoadBalancer type",rule="!has(self.loadBalancerIP) || self.type == 'LoadBalancer'"
// +kubebuilder:validation:XValidation:message="healthCheckNodePort can only be set for LoadBalancer type with Local externalTrafficPolicy",rule="!has(self.healthCheckNodePort) || (self.type == 'LoadBalancer' && (!has(self.externalTrafficPolicy) || self.externalTrafficPolicy == 'Local'))"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mirror healthCheckNodePort checks in non-CEL validation

This adds a CEL rule for healthCheckNodePort, but the non-CEL validator (api/v1alpha1/validation/envoyproxy_validate.go in validateService) was not updated even though it is still used by internal/gatewayapi/translator.go and egctl paths. In those paths, an EnvoyProxy can pass validation and still produce a Service spec with healthCheckNodePort in unsupported combinations (for example after config merges), which Kubernetes then rejects during reconciliation. Please add equivalent checks in validateService so all validation paths enforce the same constraints.

Useful? React with 👍 / 👎.

Matches the pattern established for loadBalancerIP and
loadBalancerSourceRanges: a Go-level check in validateService to catch
invalid combinations in offline/CLI paths, unit tests for that check,
and CEL admission tests covering both the pass (LoadBalancer with
default or explicit Local externalTrafficPolicy) and fail (ClusterIP,
or LoadBalancer with Cluster externalTrafficPolicy) cases.

Signed-off-by: Seth Malaki <seth@tigera.io>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.42%. Comparing base (63c5b5b) to head (adb0e10).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8843      +/-   ##
==========================================
+ Coverage   74.39%   74.42%   +0.03%     
==========================================
  Files         246      246              
  Lines       39221    39223       +2     
==========================================
+ Hits        29177    29192      +15     
+ Misses       8017     8008       -9     
+ Partials     2027     2023       -4     

☔ 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.

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.

Allow setting healthCheckNodePort on EnvoyProxy service spec

1 participant