Skip to content

test: add PONv6 dual-stack podsubnet eBPF cluster and manifests - #4830

Open
Timothy J. Raymond (timraymond) wants to merge 3 commits into
masterfrom
users/traymond/ponv6-private-fork-cluster-target
Open

test: add PONv6 dual-stack podsubnet eBPF cluster and manifests#4830
Timothy J. Raymond (timraymond) wants to merge 3 commits into
masterfrom
users/traymond/ponv6-private-fork-cluster-target

Conversation

@timraymond

@timraymond Timothy J. Raymond (timraymond) commented Sep 2, 2026

Copy link
Copy Markdown
Member

Pod subnet on IPv6, the dual-stack pod subnet preview, is being validated against a private build of Cilium, and the half of that validation which belongs in this repository has been missing. A cluster of the exact preview shape is required: dual-stack pod and node subnets carved from static blocks, no kube-proxy, and no managed CNI, together with the Cilium manifests that are installed onto it. Until now that shape has had to be assembled by hand before each run, which makes a result difficult to trust and impossible to schedule.

Test infrastructure alone is added here. No product code path is touched, and nothing introduced by this change runs unless one of the new targets is invoked explicitly.

Masquerade is configured directly in the manifests rather than reconciled by the merger sidecar used elsewhere, because the delegated IPv6 prefix has to reach Cilium intact for a pod source address to survive a cross-node hop. Both properties are asserted by the deployment target once the DaemonSet has settled, so that a regression restoring the older shape is caught rather than validated by accident.

The NAT Gateway is created through the REST API rather than the CLI because StandardV2 and its IPv6 address list are not yet exposed by az network nat gateway. Its provisioning state is polled before the subnets are attached, since the attachment is rejected while creation is still in flight.

The end to end pipeline leg that consumes these targets lives in the private Cilium fork and is proposed there separately. That leg stands up the cluster target added here, so this change is its prerequisite and has to land first.

Copilot AI lite review requested due to automatic review settings September 2, 2026 20:53
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new NAT Gateway v2 target creates public IPs without the standard IP tagging used elsewhere in hack/aks/Makefile, which can cause operational tracking/cleanup issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds reproducible test infrastructure for validating the PONv6 dual-stack podsubnet preview against a private Cilium build by introducing a dedicated eBPF podsubnet dual-stack cluster shape (static pod/node subnets, no kube-proxy, no managed CNI) plus the exact Cilium manifests required to install onto it.

Changes:

  • Add new podsubnet-dualstack eBPF Cilium manifest sets for Cilium v1.17/v1.18/v1.19 (DaemonSet + required ConfigMaps).
  • Add AKS infra targets to create the required dual-stack VNet/subnets and a StandardV2 NAT Gateway via ARM REST polling.
  • Add a deployment target to apply the new manifests and assert the intended ip-masq configuration (no merger sidecar).
File summaries
File Description
test/integration/manifests/cilium/v1.19/ebpf/podsubnet-dualstack/static/cilium-config.yaml Cilium v1.19 ConfigMap enabling dual-stack/podsubnet settings and native routing CIDRs.
test/integration/manifests/cilium/v1.19/ebpf/podsubnet-dualstack/static/azure-dns-imds-ip-masq-agent-config.yaml ip-masq-agent ConfigMap used for Azure DNS/IMDS + link-local masquerade behavior.
test/integration/manifests/cilium/v1.19/ebpf/podsubnet-dualstack/static/allowed-ip6tables-patterns.yaml Allowed ip6tables patterns for azure-iptables-monitor validation in IPv6 scenarios.
test/integration/manifests/cilium/v1.19/ebpf/podsubnet-dualstack/cilium.yaml Cilium v1.19 DaemonSet manifest for the dual-stack podsubnet eBPF deployment.
test/integration/manifests/cilium/v1.18/ebpf/podsubnet-dualstack/static/cilium-config.yaml Cilium v1.18 dual-stack podsubnet ConfigMap.
test/integration/manifests/cilium/v1.18/ebpf/podsubnet-dualstack/static/azure-dns-imds-ip-masq-agent-config.yaml v1.18 ip-masq-agent ConfigMap for Azure DNS/IMDS and link-local masquerade.
test/integration/manifests/cilium/v1.18/ebpf/podsubnet-dualstack/static/allowed-ip6tables-patterns.yaml v1.18 allowed ip6tables patterns ConfigMap.
test/integration/manifests/cilium/v1.18/ebpf/podsubnet-dualstack/cilium.yaml Cilium v1.18 DaemonSet manifest for dual-stack podsubnet eBPF deployment.
test/integration/manifests/cilium/v1.17/ebpf/podsubnet-dualstack/static/cilium-config.yaml Cilium v1.17 dual-stack podsubnet ConfigMap.
test/integration/manifests/cilium/v1.17/ebpf/podsubnet-dualstack/static/azure-dns-imds-ip-masq-agent-config.yaml v1.17 ip-masq-agent ConfigMap for Azure DNS/IMDS and link-local masquerade.
test/integration/manifests/cilium/v1.17/ebpf/podsubnet-dualstack/static/allowed-ip6tables-patterns.yaml v1.17 allowed ip6tables patterns ConfigMap.
test/integration/manifests/cilium/v1.17/ebpf/podsubnet-dualstack/cilium.yaml Cilium v1.17 DaemonSet manifest for dual-stack podsubnet eBPF deployment.
hack/aks/Makefile Adds dual-stack VNet/subnet bring-up, NAT Gateway v2 creation via REST, and cluster bring-up target.
hack/aks/deploy.mk Adds a deploy target to install the new podsubnet-dualstack eBPF Cilium manifests and validate expected components.
Review details
  • Files reviewed: 14/14 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread hack/aks/Makefile Outdated
Validating pod subnet on IPv6 against a private Cilium fork requires a
cluster whose shape matches the preview exactly: pod and node addresses
drawn from static blocks in a dual-stack virtual network, kube-proxy
absent, and the CNI left unmanaged so that a fork build can be installed
over it. No existing target in this Makefile produces that combination,
so the shape has had to be assembled by hand before every run.

A target is now provided for it. Dual-stack node and pod subnets are
created, a StandardV2 NAT Gateway is provisioned and attached to both of
them so that egress is deterministic and available at all over IPv6, and
the cluster is then created with StaticBlock pod IP allocation, both IP
families, and neither a network plugin nor kube-proxy.

The gateway is created through the REST API rather than the CLI because
StandardV2 and its IPv6 address list are not yet exposed by az network
nat gateway, and its provisioning state is polled before the subnets are
attached, since the attachment is rejected while creation is still in
flight.
The cluster target added previously has nothing to install on it. Pod
subnet on IPv6 differs from the single-stack pod subnet configuration
chiefly in how masquerade is expressed: the delegated IPv6 prefix is
carried in the Cilium configuration directly rather than reconciled at
runtime by a merger sidecar, and the IPv6 iptables rules a node is
permitted to hold have to be enumerated rather than left open.

Manifests are therefore added for Cilium 1.17, 1.18 and 1.19 under a
podsubnet-dualstack directory, along with a deployment target that
renders and applies them.

Because the masquerade agent configuration is supplied as a static
ConfigMap and the merger sidecar is deliberately absent, two assertions
are made once the DaemonSet has settled: that the mounted ConfigMap is
the static one, and that no merger container has been introduced.
Without them a regression reinstating the merger would pass unnoticed
and the fork would be validated in a configuration nobody intends to
ship.
@timraymond
Timothy J. Raymond (timraymond) force-pushed the users/traymond/ponv6-private-fork-cluster-target branch from 221ea5f to 9bf30e3 Compare September 2, 2026 21:05
Comment on lines +3 to +16
ip-masq-agent: "nonMasqueradeCIDRs:\n- 0.0.0.0/1\n- 128.0.0.0/3\n- 160.0.0.0/5\n-
168.0.0.0/11\n- 168.32.0.0/12\n- 168.48.0.0/13\n- 168.56.0.0/14\n- 168.60.0.0/15\n-
168.62.0.0/16\n- 168.63.0.0/17\n- 168.63.128.0/24\n- 168.63.129.0/29\n- 168.63.129.8/30\n-
168.63.129.12/30\n- 168.63.129.17/32\n- 168.63.129.18/31\n- 168.63.129.20/30\n-
168.63.129.24/29\n- 168.63.129.32/27\n- 168.63.129.64/26\n- 168.63.129.128/25\n-
168.63.130.0/23\n- 168.63.132.0/22\n- 168.63.136.0/21\n- 168.63.144.0/20\n- 168.63.160.0/19\n-
168.63.192.0/18\n- 168.64.0.0/10\n- 168.128.0.0/9\n- 169.0.0.0/9\n- 169.128.0.0/10\n-
169.192.0.0/11\n- 169.224.0.0/12\n- 169.240.0.0/13\n- 169.248.0.0/14\n- 169.252.0.0/15\n-
169.254.0.0/17\n- 169.254.128.0/19\n- 169.254.160.0/21\n- 169.254.168.0/24\n-
169.254.169.0/25\n- 169.254.169.128/26\n- 169.254.169.192/27\n- 169.254.169.224/28\n-
169.254.169.240/29\n- 169.254.169.248/30\n- 169.254.169.252/31\n- 169.254.169.255/32\n-
169.254.170.0/23\n- 169.254.172.0/22\n- 169.254.176.0/20\n- 169.254.192.0/18\n-
169.255.0.0/16\n- 170.0.0.0/7\n- 172.0.0.0/6\n- 176.0.0.0/4\n- 192.0.0.0/3\n-
224.0.0.0/3\n \nmasqLinkLocal: true\nmasqLinkLocalIPv6: true\n"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

😵‍💫

The non-masquerade list in this ConfigMap is the exact complement of
Azure IMDS and Azure DNS, the only two destinations for which a pod
source address has to be replaced with the node address. Both are
reachable over IPv4 only, and no IPv6 entry was present, so the
ip-masq-agent IPv6 map was left empty and every IPv6 destination outside
the native routing CIDR was masqueraded to the node address.

::/0 is now listed, matching the change made to the resource provider
that renders this ConfigMap in production. Were the two to disagree, the
end to end run would validate a masquerade configuration that no cluster
actually receives.
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.

3 participants