cocoon-net

Architecture

cocoon-net gives each cocoon VM a VPC-routable IP directly – no overlay network, no iptables DNAT, no external DHCP server. It runs as a two-phase CLI: one-time cloud provisioning, then a long-lived daemon that serves DHCP and keeps host routes in sync with leases.

cocoon-net init          cocoon-net daemon
      |                        |
      v                        v
Cloud provisioning       Node setup (NICs up, bridge, sysctl, iptables, CNI conflist)
(alias IPs / ENIs)             |
      |                        v
      v                  DHCP server on cni0
pool.json  <----------        |
                               v
                         On lease: add /32 route
                         On release: del /32 route
  1. cocoon-net init – provisions cloud networking resources (GKE alias IPs or Volcengine secondary ENI IPs), configures the node, and persists the result to pool.json. adopt is the same step for a node provisioned by hand: it configures and persists; on GKE it calls no cloud API, on Volcengine it reads the ENI secondary IPs, the only addresses the VPC routes to the node.
  2. cocoon-net daemon – long-running service: re-applies node setup, then starts the embedded DHCP server that hands out pool IPs and manages dynamic host routes.

Package model

Package Responsibility
cmd/ Cobra commands: init, adopt, daemon, status, teardown
platform/ CloudPlatform interface with per-cloud implementations (platform/gke, platform/volcengine); auto-detection via instance metadata
pool/ pool.State – the allocation pool persisted to pool.json (atomic tmp+rename write)
node/ Secondary NIC bring-up, cni0 bridge, sysctl, iptables FORWARD + NAT, and the CNI conflist writer
dhcp/ The embedded DHCPv4 server: lease store, IP pool, dynamic route add/remove – see DHCP server
metrics/ Prometheus collectors: the lease grant counter and per-scrape pool gauges – see Configuration

platform.CloudPlatform is the seam between cloud-specific provisioning and everything else: ProvisionNetwork returns a NetworkResult (assigned IPs, primary/secondary NICs, platform-specific IDs) that pool.State persists verbatim, so node/ and dhcp/ never need to know which cloud they’re running on.

Supported platforms

Platform Mechanism Max IPs/node
GKE VPC alias IP ranges (gcloud) 253
Volcengine Dedicated subnet + secondary ENI IPs (ve CLI) 140 (7 ENIs x 20)

Platform-specific setup, prerequisites, and troubleshooting:

GKE multi-node: the secondary range cocoon-pods on the GCE subnet is shared across nodes. See gke.md Prerequisites before running init on a second node.

CNI integration

init, adopt, and daemon all write /etc/cni/net.d/30-cocoon-dhcp.conflist as part of node setup:

{
  "cniVersion": "1.0.0",
  "name": "cocoon-dhcp",
  "plugins": [{
    "type": "bridge",
    "bridge": "cni0",
    "mtu": 1460,
    "isGateway": false,
    "ipMasq": false,
    "portIsolation": true,
    "macspoofchk": true,
    "ipam": {}
  }]
}

portIsolation blocks same-node VM-to-VM traffic at L2 and macspoofchk pins each veth’s source MAC (see Traffic isolation). mtu is the primary NIC’s MTU read at setup (1460 on GCE, 1500 on Volcengine): the cni0 bridge is set to the same value, the veth inherits it from the conflist, cocoon syncs the TAP to the veth, and the hypervisor advertises the TAP MTU to the guest, so nothing cocoon-net produces can emit a frame the egress NIC cannot carry. A node whose MTU changes invalidates Firecracker fork and hibernate snapshots captured at the old value (cocoon rejects a clone whose target network MTU differs from the snapshot’s). The daemon restart that applies the new MTU only resizes the bridge and rewrites the conflist; a VM that is already running keeps the veth and TAP it was started with, so a snapshot taken from it still records the old MTU. Recreate the source VM after that restart, then capture the snapshot again. IPAM is intentionally empty – VMs obtain their IP from the embedded DHCP server, not from CNI. In a CocoonSet:

spec:
  agent:
    network: cocoon-dhcp
    os: windows

Cloud credentials each platform needs are covered in Configuration.