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
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.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 | 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.
| 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-podson the GCE subnet is shared across nodes. See gke.md Prerequisites before runninginiton a second node.
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.