perf(networking): Cilium ENI native routing as opt-in --cni=cilium datapath - #820
perf(networking): Cilium ENI native routing as opt-in --cni=cilium datapath#820rustyrazorblade wants to merge 1 commit into
Conversation
Code Coverage
|
|
Review: cilium-native-routing OpenSpec proposal This PR only adds OpenSpec artifacts (proposal/design/spec/tasks) - no code changes yet, consistent with the draft status. Overall the design is well-researched: I spot-checked the concrete claims against the current worktree (CiliumService.kt, EC2InstanceService.kt, ClusterState.kt, Up.kt, start-k3s-server.sh) and they all check out - the unquoted hubble.metrics.enabled={...} brace-expansion bug, the if (serverType == ServerType.Control) IMDS gating, ciliumEnabled: Boolean = false at ClusterState.kt:111, resolveCidr/startK3sOnAllNodes line references, and the --flannel-backend=none --disable-network-policy args in start-k3s-server.sh are all exactly as described. Bug: proposal.md contradicts itself (and design.md/tasks.md) on the default CniMode The Why section and What Changes bullet (line 16) are explicit that the default stays flannel: '--cni=flannel (the default) selects K3s built-in Flannel. The default-to-Cilium flip is deferred to #819.' This matches design.md Decision 1 ('Default stays flannel this patch (owner decision)') and tasks.md 1.2/1.3 (InitConfig.cni: CniMode = CniMode.Flannel, Init.cni: CniMode = CniMode.Flannel, default flannel). But the Impact section of proposal.md says the opposite in two places:
Since proposal.md is what gets carried forward into implementation (and archived into the spec), this is worth fixing before merge so whoever picks up tasks.md does not cross-reference the Impact section and flip the default by accident. Should be a one-line find/replace (CniMode.Cilium to CniMode.Flannel, default cilium to default flannel) on lines 30-31. Other notes (non-blocking):
No security, performance, or test-coverage concerns beyond the above - this is a docs-only PR and the actual code changes will need their own review once implemented per tasks.md. |
|
Reviewed the diff (Init/Up/CiliumService/EC2InstanceService + tests + openspec artifacts). Overall this is a well-scoped, well-tested change — the enum-based 1. This directly contradicts design.md Decision 1 ("default flannel... Default stays flannel this patch"), tasks.md 1.2/1.3, the new specs own scenario ("Default provision uses Flannel"), and the actual code ( 2. 3. Worth confirming before flipping the default (not a blocker for this opt-in patch) Minor/non-blocking: Nice fixes on the IMDS hop-limit generalization (EC2InstanceService.kt) — lifting it out of the Control-only guard is the right root-cause fix per the "configuration problems require configuration fixes" principle, and the new parameterized test (@EnumSource(ServerType::class)) covers all node types cleanly. |
|
Review of the Cilium ENI native routing change. Solid, well-scoped change. The default-stays-Flannel decision, the two bug fixes (Hubble brace-expansion, IMDS hop-limit on all node types), and the CIDR-threading approach (reading from Findings:
Nit: Nothing here blocks merging as a draft/opt-in change — finding 1 is the only one I would actually want fixed before this leaves draft, since it is a factual self-contradiction in the spec doc itself. |
Review: Cilium ENI native routing (opt-in
|
Review: Cilium ENI native routing (opt-in --cni=cilium)Overall this is a well-structured change: the CNI selection is modeled correctly as an enum (extensible, mutually exclusive by construction), the two blocking bugs described in the proposal (Hubble brace-expansion and IMDS hop-limit) are both genuinely fixed in the code, and keeping the default at Flannel is a sensible way to de-risk the rollout. Test coverage is strong - the new UpTest cases stub setupCluster to actually invoke onServerReady, which is the right way to exercise the install side effect rather than just asserting a mock was wired up. Issue openspec/changes/cilium-native-routing/proposal.md still claims the wrong default (Impact section): This says the new default is CniMode.Cilium, but the actual code, design.md, and every other part of this PR (including the dedicated commit "docs: fix proposal Impact bullet - --cni default is flannel not cilium") say the default is CniMode.Flannel. It looks like that fix commit corrected the root CLAUDE.md line but missed this second occurrence in proposal.md. Worth a follow-up since specs are meant to be the source of truth here and this one is currently self-contradictory. Nitpick (non-blocking) PicoCniModeConverter hand-matches "cilium"/"flannel" string literals rather than deriving from CniMode.entries(). The design doc frames the enum as extensible to future CNIs with no new flags, but as written a third CniMode value would need updates in both the enum and this converter's when block. Not a problem today - just something to keep in sync if a future CNI is added. What looks solid
No security, performance, or correctness concerns beyond the doc inconsistency above. Good test discipline throughout - tests exercise real decision points rather than mock-echo assertions. |
ReviewSolid piece of work — the OpenSpec docs are thorough (including the live-AWS-test corrections baked into the design doc), the Correctness
Previously this mismatch was harmless (the stored Docs
That contradicts Minor / nice-to-have
Nothing here blocks the shape of the design — the CIDR issue is scoped to a specific combination ( |
ReviewSolid, well-documented change. The openspec proposal/design/tasks docs are thorough, and the live-AWS-test-driven corrections baked into the design (named A few things worth a look before this comes out of draft: 1. Docs inconsistency: proposal.md still says the new default is Cilium
This contradicts 2. Security consideration: IMDS hop-limit 2 now applies to db/app (worker) nodes too
3. Weak assertion in one new UpTest casefun `up auto-resolves an unset VPC CIDR and installs Cilium with the selected block`() {
...
assertThat(cidrCaptor.firstValue).isNotBlank()
}Since 4. Minor test gap
5. Draft status / live validation still outstanding
Nothing here blocks the design — mostly documentation/test polish plus one security trade-off worth stating explicitly in the design doc. |
Review: Cilium ENI native routing (opt-in
|
Adds the CniMode enum-based flag surface ahead of the Cilium ENI native-routing work, which stays on #805/PR #820. This is plumbing only: Cilium still installs in the existing single-argument VXLAN-tunnel mode via CiliumService.install(controlHost) — unchanged. Only how the install-or-not decision gets computed changes, from a boolean field to InitConfig.cni == CniMode.Cilium. - CniMode enum in configuration/ClusterState.kt, replacing InitConfig.ciliumEnabled with InitConfig.cni (default Flannel) - PicoCniModeConverter for case-insensitive --cni parsing - Init.kt: --cni option replaces --cilium - Up.kt: reads workingState.initConfig?.cni == CniMode.Cilium instead of the old boolean
…DS hop-limit 2 to all node types (#858) * feat(packer): bake Cilium ENI networkd config into base AMI; apply IMDS hop-limit 2 to all node types Splits two safe, decoupled pieces out of the in-progress #805 Cilium ENI native-routing work so they can land independently while the rest of that PR is still being validated: - New packer/base/install/configure_cilium_eni_networkd.sh bakes systemd-networkd drop-ins into the base AMI so the OS leaves Cilium's runtime-attached secondary ENIs (ens6+) unmanaged, preventing a competing DHCP default route from multi-homing the host. Inert on Flannel. - EC2InstanceService now sets IMDSv2 hop-limit 2 for every node type, not just Control nodes, so the non-hostNetwork cilium-operator pod can reach IMDS regardless of which node it schedules on. Closes #857 * feat(cli): add --cni=<cilium|flannel> flag, replacing --cilium boolean Adds the CniMode enum-based flag surface ahead of the Cilium ENI native-routing work, which stays on #805/PR #820. This is plumbing only: Cilium still installs in the existing single-argument VXLAN-tunnel mode via CiliumService.install(controlHost) — unchanged. Only how the install-or-not decision gets computed changes, from a boolean field to InitConfig.cni == CniMode.Cilium. - CniMode enum in configuration/ClusterState.kt, replacing InitConfig.ciliumEnabled with InitConfig.cni (default Flannel) - PicoCniModeConverter for case-insensitive --cni parsing - Init.kt: --cni option replaces --cilium - Up.kt: reads workingState.initConfig?.cni == CniMode.Cilium instead of the old boolean
d34048d to
0471c94
Compare
Review: Cilium ENI native routing (opt-in
|
1a330de to
e0dc3fc
Compare
Review: Cilium ENI native routing (opt-in
|
Review: Cilium ENI native routing (opt-in
|
## Features - New `--cni=<cilium|flannel>` init flag (default `flannel`) selects the pod-network datapath. `--cni=cilium` installs Cilium 1.19.4 in ENI IPAM native-routing mode — pods get VPC-routable secondary IPs, so cross-AZ pod traffic is routed by the VPC with no encapsulation, replacing the previous VXLAN-tunnel install. ## Architecture - `CiliumService.install()` signature changed to `install(controlHost: Host, vpcCidr: String)`; `Up.installCilium()` now resolves the VPC CIDR from cluster state (`requireNotNull` guard) and threads it through for `ipv4NativeRoutingCIDR`. - Replaced the VXLAN `--set` flags (`tunnelProtocol=vxlan`, `routingMode=tunnel`) with the ENI native-routing set: `ipam.mode=eni`, `eni.enabled=true`, `routingMode=native`, `endpointRoutes.enabled=true`, `enableIPv4Masquerade=true`, `egressMasqueradeInterfaces=ens+`, `kubeProxyReplacement=false`, `bpf.hostLegacyRouting=true`, `ipv4NativeRoutingCIDR=<vpc-cidr>`. - Fixed two bugs found during live AWS testing: the Hubble metrics flag was unquoted and got brace-expanded by the remote shell into invalid tokens (now single-quoted); `kubeProxyReplacement` was previously unset, which silently enabled BPF host routing on the primary NIC and blackholed the node's own SSH/API-server traffic (cilium/cilium#46010) — now pinned `false` explicitly, with `bpf.masquerade` deliberately left unset. - `CniMode`'s KDoc and the `--cni` CLI help text updated to describe actual ENI native-routing behavior (previously written against VXLAN). - OpenSpec change `cilium-native-routing` (proposal/design/spec/tasks) records the design decisions and adds REQ-NET-007. - Test coverage: `CiliumServiceTest` asserts the ENI flag set and absence of VXLAN flags; `UpTest` covers the Cilium-install path and CIDR threading; `PicoCniModeConverterTest` covers the error contract.
e0dc3fc to
09f6bfa
Compare
Review: Cilium ENI native routing (opt-in
|
Closes #805
Draft — implementation in progress. The unit tier runs locally; the full suite runs in CI on each push.
Lands Cilium ENI IPAM native routing as an opt-in datapath, selected via
--cni=<cilium|flannel>(defaultflannel). Default-to-Cilium flip is tracked in #819.Scope update (post-rebase onto #858): the base-AMI packer script (
configure_cilium_eni_networkd.sh+base.pkr.hcl/docker-compose.yml/README.mdwiring), the IMDS hop-limit-2 fix applied to all node types (EC2InstanceService.kt), and the--cni=<cilium|flannel>enum flag itself (CniModeinClusterState.kt,PicoCniModeConverter,Init.kt/Up.ktwiring) landed separately via #858 and are no longer part of this diff.What remains here is just the actual, still-unvalidated Cilium install logic:
CiliumService.install()'s ENI native-routing flag set (ipam.mode=eni,routingMode=native,ipv4NativeRoutingCIDR,kubeProxyReplacement=falsepinning, iptables masquerade, the Hubble metrics brace-quoting fix)install(controlHost, vpcCidr)signatureUp.installCilium()'s VPC-CIDR threading into that callCiliumServiceTest.ktand theUp/Inittest coverage for the aboveopenspec/changes/cilium-native-routing/design docsLive cross-AZ validation (design doc task 6.2) is still outstanding — that's the risk this PR hasn't yet proven out.