摘要
在 Kubernetes 主机上,Pod 网络接口(如示例中的 lxc4298e8476003@if282
)是通过 CNI 插件 在内核中创建的一对 veth(虚拟以太网)对设备,并将其中一端放入 Pod 的 网络命名空间(netns),另一端留在主机网络命名空间上。主机侧的 veth 接口通常以 lxc
或 veth
开头并附带 @ifxxx
后缀,表示它是与容器命名空间对端相连的虚拟设备。该机制利用 Linux 的网络命名空间和虚拟网络设备,配合桥接或路由,实现了容器与主机网络及集群内部和外部的互联通信。
Kubernetes CNI 网络模型
Kubernetes 本身不实现网络,而是通过 Container Network Interface (CNI) 规范和插件来完成网络配置。
- CNI 插件触发:当 Kubelet 在某节点上创建 Pod 时,会调用已配置的 CNI 插件(如 Flannel、Calico、Cilium 等)来执行
ADD
操作。 - 网络命名空间:CNI 插件为 Pod 创建或使用一个独立的 Linux 网络命名空间(netns),该空间拥有独立的网络栈和接口列表。
- veth 对连接:插件在主机和 Pod netns 之间创建一对虚拟以太网设备(veth pair),实现数据包的双向转发。
veth 对儿与网络命名空间
设备创建
-
使用
ip link add
命令或等价的 netlink 接口,CNI 插件创建一对 veth:ip link add lxcXXX type veth peer name tmpXXX
其中
lxcXXX
(或vethXXX
)是主机侧接口,tmpXXX
(或其他临时名)是容器(Pod)侧接口。
接口迁移
- 调用
netlink.LinkSetNsFd()
或ip link set tmpXXX netns <pid>
将容器侧接口迁移到 Pod 的网络命名空间中,使其只在该命名空间内可见。
命名与重命名
- 容器侧接口在进入命名空间后再被重命名(通常为
eth0
),以符合容器内部的网络习惯;主机侧则保持lxc…
前缀,并通过@ifXXX
指明它所连接的 peer 接口索引(if282
)。
link-netns
与接口观察
-
在
ip link
输出中,link-netns cni-<UUID>
或link-netnsid <N>
表示该接口的对端位于指定的网络命名空间。 -
例如:
283: lxc4298e8476003@if282: <…> link-netns cni-e71b6be0-f8a4-43dd-084a-55f5ad90f98b
表示接口
lxc4298e8476003
与索引为282
的对端相连,且对端位于网络命名空间cni-e71b6be0-f8a4-43dd-084a-55f5ad90f98b
中。 -
要查看容器侧接口,可使用:
ip netns exec cni-e71b6be0-f8a4-43dd-084a-55f5ad90f98b ip link
小结
- 网络命名空间(netns) 将容器与主机隔离,使得同一主机上不同 Pod 的网络环境互不干扰。
- veth 对 提供了容器与主机、容器与容器或节点间通信的桥梁。
- CNI 插件 统一执行接口创建、分配 IP、配置路由和策略的流程,实现 Kubernetes 网络的可插拔与扩展。
以上即为 Kubernetes 主机上网卡(veth/lxc接口)虚拟化的原理与实践说明。