[feat] Add IPv6 public backends for NodeBalancers#545
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #545 +/- ##
==========================================
+ Coverage 73.43% 73.62% +0.19%
==========================================
Files 19 19
Lines 2906 2927 +21
==========================================
+ Hits 2134 2155 +21
Misses 523 523
Partials 249 249 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds support for selecting public IPv6 addresses as NodeBalancer backend node targets (with global flag + per-Service annotation), including for VPC-backed NodeBalancers, and extends unit/e2e/docs/chart coverage around the new behavior.
Changes:
- Add
--enable-ipv6-for-nodebalancer-backendsandservice.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backendsto control IPv6 backend selection. - Update NodeBalancer reconciliation to build backend node addresses using IPv6-safe host:port formatting and preserve VPC config when IPv6 backends are enabled.
- Add Helm/docs and unit + Chainsaw e2e coverage for IPv6 backend behavior.
Reviewed changes
Copilot reviewed 14 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
main.go |
Registers new controller flag for IPv6 NodeBalancer backends. |
cloud/annotations/annotations.go |
Adds the per-service annotation constant for enabling IPv6 backends. |
cloud/linode/options/options.go |
Adds a global options field to enable IPv6 NodeBalancer backends. |
cloud/linode/loadbalancers.go |
Core logic: resolves IPv6-backend enablement, selects node backend IPs, preserves VPC config, and formats backend addresses safely for IPv6. |
cloud/linode/loadbalancers_test.go |
Adds unit tests for IPv6 backend selection, precedence rules, VPC preservation, and address formatting. |
deploy/chart/templates/daemonset.yaml |
Plumbs the new flag into the Helm chart DaemonSet args. |
deploy/chart/values.yaml |
Documents the new Helm value for enabling IPv6 NodeBalancer backends. |
docs/configuration/loadbalancer.md |
Documents frontend vs backend IPv6 behavior and operational requirements for IPv6 backends. |
docs/configuration/environment.md |
Documents the new controller flag and its behavior/requirements. |
docs/configuration/annotations.md |
Documents the new service annotation for IPv6 backends. |
e2e/test/lb-with-ipv6-backends/create-pods-services.yaml |
Adds an e2e workload + dual-stack Service annotated to enable IPv6 backends. |
e2e/test/lb-with-ipv6-backends/chainsaw-test.yaml |
Adds a Chainsaw scenario validating backend node addresses are IPv6 and traffic still reaches pods. |
devbox.json |
Pins clusterctl version in the devbox environment. |
devbox.lock |
Updates the devbox lockfile to reflect the pinned clusterctl version. |
Makefile |
Updates cluster-api related versions and ensures clusterctl is used via a configured path. |
.gitignore |
Ignores local generated cluster artifacts/kubeconfigs. |
What: - add the `service.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backends` annotation and the `--enable-ipv6-for-nodebalancer-backends` controller flag, including Helm values and docs - resolve the backend address family per service so the service annotation overrides the global default when needed - program NodeBalancer backends from `node.k8s.linode.com/public-ipv6` when IPv6 backends are enabled, format IPv6 backend addresses correctly, and omit IPv4 subnet IDs from IPv6 backend nodes - avoid applying VPC backend configuration during IPv6 backend creation while preserving the existing IPv4/VPC path for non-IPv6 services - fall back to the Service's current status when a fresh LoadBalancer status lookup fails during reconcile - add unit coverage for backend IP selection, annotation-vs-flag resolution, IPv6 address formatting, and the VPC/subnet behavior around IPv6 backends - add a dedicated Chainsaw test and CAPL workflow support for validating IPv6 public backends end to end in a dual-stack cluster - centralize CAPL manifest patching for image overrides, `LINODE_API_VERSION=v4beta`, VPC/subnet mutations, and subnet-specific test setup - document the feature, its dual-stack requirement, and its current limitation to node public IPv6 backends rather than VPC IPv6 backend addresses Why: - support NodeBalancer services that need IPv6 backend targets instead of the existing IPv4-only backend programming - make the backend selection logic explicit so IPv6 public backends do not inherit IPv4/VPC assumptions such as subnet IDs - validate the feature in CI and local CAPL flows using a dual-stack workload cluster that can actually serve IPv6 NodePort traffic - keep the rollout understandable for operators by documenting the opt-in controls, migration behavior, and failure mode when nodes do not expose public IPv6 addresses How: - factor backend-family handling into helpers for backend-state resolution, subnet lookup, backend node construction, backend address formatting, and node backend IP selection - read IPv6 backend addresses from the node public IPv6 annotation, return a clear reconcile error when a selected node lacks one, and continue using the existing private/VPC address path when IPv6 backends are disabled - create a dedicated IPv6 CAPL cluster path and `ipv6-backends` Chainsaw selector, run that test separately from the rest of e2e, and use a dual-stack service definition to exercise the public IPv6 backend datapath - patch generated CAPL manifests through `hack/patch-capl-manifest.sh` so the CCM image repo/tag, pull policy, beta API env var, VPC template values, and optional subnet override are applied consistently across regular, IPv6, and subnet test flows - route `clusterctl` usage through repo-managed tooling/devbox configuration and ignore generated local manifest and kubeconfig artifacts from dev workflows
There was a problem hiding this comment.
Pull request overview
Adds support for programming Linode NodeBalancer backend nodes using each Kubernetes node’s public IPv6 annotation, with an explicit global flag and per-service override, plus corresponding docs and e2e coverage.
Changes:
- Introduces
--enable-ipv6-for-nodebalancer-backendsand theservice.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backendsannotation to control backend address family selection. - Updates NodeBalancer reconciliation to build backend node addresses via an IPv6-safe host:port formatter and to omit VPC/subnet backend programming when IPv6 backends are selected.
- Adds CAPL manifest patch tooling and a dedicated Chainsaw e2e scenario to validate IPv6 backend programming and connectivity.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| main.go | Registers the new controller flag for IPv6 NodeBalancer backends. |
| cloud/linode/options/options.go | Adds a new global option to enable IPv6 NodeBalancer backends. |
| cloud/annotations/annotations.go | Adds the new service annotation constant for enabling IPv6 backends. |
| cloud/linode/loadbalancers.go | Implements IPv6 backend selection, backend IP resolution, and IPv6-safe backend address formatting. |
| cloud/linode/loadbalancers_test.go | Adds unit tests for backend-family selection, IPv6 backend IP parsing, and request shape expectations. |
| deploy/chart/templates/daemonset.yaml | Wires the Helm value into the new controller flag. |
| deploy/chart/values.yaml | Documents Helm configuration for IPv6 NodeBalancer backends. |
| docs/configuration/loadbalancer.md | Documents IPv6 backend behavior and recommended Service configuration. |
| docs/configuration/environment.md | Documents the new controller flag. |
| docs/configuration/annotations.md | Documents the new per-service annotation. |
| e2e/test/lb-with-ipv6-backends/* | Adds a new Chainsaw test scenario validating IPv6 backend programming and traffic. |
| hack/patch-capl-manifest.sh | Centralizes CAPL manifest patching for e2e workflows. |
| Makefile | Adds dual-stack CAPL cluster generation and a dedicated IPv6-backend e2e target; routes manifest generation through the patch script. |
| devbox.json | Adjusts devbox packages and adds convenience scripts for the new Makefile targets. |
| devbox.lock | Updates pinned clusterctl package metadata. |
| .gitignore | Ignores locally generated cluster manifest/kubeconfig artifacts. |
|
|
||
| .PHONY: e2e-test | ||
| e2e-test: | ||
| # Run ipv6 tests first and then the rest |
There was a problem hiding this comment.
In the e2e-test recipe, the comment line is indented with spaces instead of a tab. In Makefiles, every recipe line (including comments) must start with a tab, otherwise make fails with "missing separator" and the target won’t run. Convert the leading spaces on this line to a tab (or move the comment outside the recipe).
| # Run ipv6 tests first and then the rest | |
| # Run ipv6 tests first and then the rest |
Summary
node.k8s.linode.com/public-ipv6annotationBehavior
--enable-ipv6-for-nodebalancer-backendsas a global controller flagservice.beta.kubernetes.io/linode-loadbalancer-enable-ipv6-backendsas a per-service overrideCode Changes
cloud/annotations/annotations.gocloud/linode/options/options.goand register the flag inmain.gocloud/linode/loadbalancers.goto:deploy/chart/templates/daemonset.yamlanddeploy/chart/values.yamldocs/configuration/loadbalancer.md,docs/configuration/environment.md, anddocs/configuration/annotations.md.gitignoreCAPL And E2E Changes
hack/patch-capl-manifest.shto centralize generated manifest patching for:.image.repository/.image.tagimage.pullPolicy: AlwaysLINODE_API_VERSION=v4betarouteController.vpcNamestemplate valueSUBNET_NAMEinjection for subnet test flowsLinodeVPCobjects from the second subnet-test manifest when neededclusterctle2e/test/lb-with-ipv6-backends/LoadBalancerservice annotated withlinode-loadbalancer-enable-ipv6-backends: "true"Tests
Unit
cloud/linode/loadbalancers_test.gowith coverage for:node.k8s.linode.com/public-ipv6E2E
lb-with-ipv6-backendsChainsaw scenario for the public IPv6 backend path