Skip to content

CNI 与 Pod 网络

Kubernetes 只定义网络模型的要求——每个 Pod 有独立 IP、Pod 之间可以互通、Service 提供稳定入口。但 IP 从哪分、跨节点怎么转发、策略怎么拦截、隧道怎么封装——全部交给 CNI 插件。

网络问题的排查容易乱,因为它同时涉及 Linux 网络、K8s 资源对象和具体 CNI 实现。排查时把链路拆开,按顺序逐项验证,不要混在一起。

K8s 网络模型的基本要求

要求说明
每个 Pod 有独立 IPPod 内容器共享同一个 network namespace
Pod 之间可互通同节点和跨节点 Pod 都能直接访问 Pod IP
Node 能访问 Pod节点能访问本机和跨节点 Pod
Service 提供稳定入口Pod IP 变化后,Service 名称和 ClusterIP 不变

同一 Pod 内容器共享网络命名空间,localhost 互访。不同 Pod 即使在同一台节点上,也不在同一网络命名空间——访问必须走 Pod IP 或 Service。

Pod IP 是集群内地址。外部访问不走 Pod IP,而是走 LoadBalancer、Gateway、Ingress、NodePort 或云负载均衡。

Pod 到 Pod 的链路

同节点两个 Pod 通信:

跨节点多了一段节点间转发:

"路由或隧道"由 CNI 决定——Flannel 用 VXLAN,Calico 可选 IPIP/VXLAN/BGP,Cilium 用 eBPF 数据面。排查时先确认跨节点 Pod IP 是否互通,不通再看 CNI 的具体转发方式。

验证链路:

bash
# 在两个不同节点上各跑一个临时 Pod
kubectl get pods -A -o wide   # 记下 Pod IP 和所在节点

# 从一个 Pod ping 另一个 Pod 的 IP
kubectl exec -it <pod-a> -- ping <pod-b-ip>

跨节点 ping 不通时,先看节点路由有没有 Pod 网段,再看防火墙和 CNI 隧道状态。

三种网络对象要分清

验证对象做什么不通时看什么
Pod IPPod 之间直连CNI、路由、隧道、防火墙
Service ClusterIPService 到 Podkube-proxy、EndpointSlice、Service selector
DNSService 名到 ClusterIPCoreDNS、NetworkPolicy、Pod DNS 配置

Pod IP 通但 Service 不通——问题在 kube-proxy 和 Service 层。Service 通但域名不通——问题在 CoreDNS。

常见 CNI

插件实现方式适合场景
FlannelVXLAN 隧道实验、小集群,简单够用
CalicoBGP / IPIP / VXLAN,NetworkPolicy 成熟传统机房、通用生产集群
CiliumeBPF 数据面,Hubble 可观测性,策略和 Gateway 能力强新集群,需要强网络观测和安全能力

Calico 在传统机房常见——IPIP、VXLAN、BGP 都支持得成熟,不依赖特定网络设备。Cilium 把数据面做到 eBPF 里,用 Hubble 直接看流量路径和丢包点——排查方式从看 iptables 规则转向流量可视化。

Pod CIDR 和 Service CIDR

K8s 集群有两个网段必须在初始化时规划:

网段作用示例
Pod CIDR给 Pod 分配 IP10.244.0.0/16
Service CIDR给 ClusterIP 分配 IP10.96.0.0/12

这两个网段需要避开公司内网、VPN 网段、Docker 默认网段、云 VPC 网段。路由冲突的典型表现不是全部断开,而是部分地址路由异常——访问公司某个网段走了 Pod 路由,或者 VPN 连上后某些 Service 解析出来 IP 能通但端口不通。这类问题容易排查很久,因为现象不是"全断"而是"有时不通"。

Calico 三种模式

模式原理注意事项
IPIPPod 流量封装进 IPIP 包跨节点传输底层网络不感知 Pod 路由,注意 MTU
VXLANVXLAN 隧道封装跨节点流量云和跨三层网络常见,注意 UDP 4789 端口
BGP节点间或和交换机通过 BGP 分发 Pod 路由性能好,但依赖网络设备配合

隧道模式(IPIP、VXLAN)的好处:底层网络不用知道 Pod 网段——宿主机之间先包一层再发。代价是多一层封装,MTU 配不好时大包异常。BGP 模式把 Pod 网段直接通告给网络设备,延迟更低,但需要交换机或路由器支持 BGP 对等。

MTU、防火墙、conntrack

CNI 封装会增加额外头部。原本 1500 的包,VXLAN 封装后可能超过底层 MTU——表现是小包通、大包不通,或者 TCP 握手成功但传大响应时卡住。

防火墙除了 TCP 端口,还要放行 CNI 协议:

协议端口/类型
VXLANUDP 4789
IPIPIP 协议号 4
BGPTCP 179
kube-apiserverTCP 6443
NodePortTCP/UDP 30000-32767

conntrack 表满时 Service 访问出现间歇失败,和 Deployment、Service YAML 无关:

bash
sysctl net.netfilter.nf_conntrack_max
conntrack -S
dmesg | grep -i conntrack

nf_conntrack: table full 出现时,看节点上的短连接数量、nf_conntrack_max 大小和超时参数。这个现象在 Service 多的集群和高并发短连接场景容易出现。

跨节点不通排查

bash
kubectl get pods -A -o wide
kubectl get nodes -o wide

kubectl run net-test --rm -it --image=busybox:1.36 --restart=Never -- sh
# Pod 内
ping <other-pod-ip>
nc -vz <service-name> <port>
nslookup <service-name>.<namespace>.svc.cluster.local

节点上看路由和规则:

bash
ip route
iptables-save | grep -E 'CALI|CILIUM|FLANNEL|KUBE' | head -50
现象方向
新 Pod 没 IPCNI 插件异常、IP 池耗尽、kubelet 调 CNI 失败
同节点通、跨节点不通隧道、防火墙、路由、BGP、MTU
Pod IP 通、Service 不通kube-proxy、EndpointSlice、selector、端口
Service 通、域名不通CoreDNS、搜索域、NetworkPolicy
小包通、大包卡MTU、封装、中间设备
间歇性失败conntrack、节点压力、CNI Agent 重启

Cilium 集群用 Hubble 直接看流量路径和丢包点;Calico 集群更常看 IPPool、BGP 状态、felix 日志和节点路由。CNI 不同,排查入口也会变——只靠 kubectl describe pod 看不到底层网络问题。