Network 模块设计
Network 模块位于 internal/netstack,负责为 Sandbox 创建并复用隔离的网络环境。CNI 管理 Sandbox 对外网络,Conch 管理 network namespace、guest tap 和两层网络之间的地址转换。
当前 Sandbox 数据面和网络策略仅支持 IPv4。VMM cold boot 会禁用 guest IPv6;CNI 返回 IPv6 地址、路由、网关或 DNS 时,Slot 创建失败并回滚。
1. 模块组成
| 组件 | 职责 |
|---|---|
Pool |
预创建、分配、回收和补充 Network Slot |
Slot |
保存 Slot ID、network namespace 路径、CNI IP、DNS 和 guest tap 地址 |
CNIManager |
加载 CNI 配置,执行 CNI ADD / DEL,获取 Sandbox 对外 IP 和 DNS |
netns |
创建并挂载独立的 network namespace |
guest_tap |
创建 tap0,启用 IPv4 转发并配置 SNAT / DNAT |
Pool 拥有 Slot 的状态变化;Sandbox 和 VMM 只读取 Slot 提供的 namespace 路径、tap 名称和 CNI IP。
Pool 初始化时会查找主机 0.0.0.0/0 IPv4 默认路由,并为 CNI bridge 配置主机转发规则。因此,运行 conchd 的主机必须存在类似 default via 192.168.1.1 dev eth0 的可用路由;否则网络池初始化失败,conchd 不会进入可用状态。
2. 网络结构
CNI bridge / host network
|
veth pair
|
network namespace: slot-N
├── eth0:CNI 分配的对外 IP
└── tap0:192.168.100.2/24
|
virtio-net
|
guest:192.168.100.21/24
每个 Slot 使用独立的 network namespace,因此可以复用相同的 guest 子网。Conch 在 namespace 内配置以下地址转换:
- guest 发出的流量以 CNI IP 作为源地址离开 namespace。
- 发往 CNI IP 的流量转发到 guest IP。
VMM 在 Slot 的 network namespace 中启动,并使用该 Slot 的 tap0。conch-init 通过初始化握手接收 guest IP、前缀长度、网关和 DNS,为第一个非 loopback 接口配置地址与默认路由,并更新 /etc/resolv.conf。
3. Network Slot
Network Slot 是一组可复用的网络资源,包括:
- Slot ID 和
/run/conch/netns/slot-Nnamespace。 - CNI 使用的
conch-slot-Ncontainer ID。 - CNI 创建的外层接口、分配的 IP 和返回的 DNS。
- Conch 创建的
tap0、IPv4 转发和 NAT 规则。
conchd 启动后并发填充 warm pool。创建 Sandbox 时,Pool.Get 取出一个 Slot 并绑定 Sandbox ID,同时触发后台补充;池为空时创建请求失败。Sandbox 删除后,Pool.Release 检查 namespace、CNI 接口和 tap 是否仍然存在:状态正常的 Slot 返回池中,状态异常的 Slot 被销毁并重新补充。
Slot 销毁时依次移除 tap 和 NAT、执行一次 CNI DEL、删除 network namespace,最后释放 Slot ID。CNI DEL 失败时保留 network namespace 和 Slot ID 并返回错误;启动 cache reconciliation 失败时保留 cache 并终止启动。
4. CNI 边界
Network 模块直接通过 libcni 加载一个默认 CNI 网络。ADD、DEL 与启动 cache reconciliation 共用同一个 libcni.CNIConfig,确保插件配置和 cache root 一致。CNI 负责 bridge/veth、IPAM、路由以及外层网络策略;Conch 通过 netlink 将 namespace 中的 loopback 接口置为 UP,不再调用 loopback CNI 插件。
CNI Result 是 guest DNS 的唯一来源。Conch 对 CNI 返回的 DNS 进行校验、去重并最多保留 3 个 IPv4 nameserver,然后通过初始化协议下发给 conch-init;Conch 不读取 Host resolv.conf。
Conch 固定从 /etc/conch/cni/net.d 加载专用 CNI 配置。外层接口名固定为内部实现值 eth0;libcni cache root 派生为 <server.state_dir>/cni,result cache 实际位于其 results 子目录。该路径不单独暴露为用户配置接口。
Conch 在加载 CNI 配置时将 host-local IPAM 的 dataDir 设为
<server.state_dir>/cni/networks,使 result cache 与 IPAM 租约都随持久状态根目录迁移。
5. 配置
network:
warm_pool_size: 250
cni:
plugin_bin_dirs:
- /usr/libexec/cni
warm_pool_size:空闲 Slot 的目标数量,默认 250,最大 4000。plugin_bin_dirs:CNI 插件二进制目录。
6. 状态与退出
Slot ID、Slot 与 Sandbox 的绑定关系以及 CNI IP 只保存在内存中,Network Slot 本身不写入 state store。conchd 重启后会创建新的 Pool,不恢复或接管旧 Slot。启动时会在 warm pool 预热前先清理仍挂载的旧 network namespace,再通过 libcni 枚举配置 cache root 中的 current-format attachment,并对已经失去 Slot 状态的 conch-slot-* attachment 执行 CNI DEL。随后清理旧 Sandbox 状态记录并释放对应的 snapshot view;旧 Sandbox 不会恢复。
正常退出时,conchd 会先删除所有 Sandbox,再关闭 containerd host。host 关闭 Pool 时会停止后台补充,并尽力销毁队列中的空闲 Slot。单个 Slot 清理失败只记录日志,不阻止其余关闭流程。