Skip to content

CNI 与 Pod 网络

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

这块容易混淆,因为它同时涉及 Linux 网络、Kubernetes 资源对象和具体 CNI 实现。排查时把链路拆开:Pod 自己有没有 IP → 同节点 Pod 通不通 → 跨节点 Pod 通不通 → Service 通不通 → DNS 解析正不正常。逐一验证,不要混在一起。

K8s 网络模型的基本要求

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

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

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

Pod 到 Pod 的链路

同节点 Pod 通信:

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

这里的"路由或隧道"由 CNI 决定。Flannel 常见 VXLAN,Calico 可以用 IPIP、VXLAN 或 BGP,Cilium 用 eBPF 数据面。

排查时分清三件事:

验证对象看什么
Pod IPPod 是否拿到 IP,跨节点 Pod IP 是否互通
ServiceClusterIP 到 EndpointSlice 是否正常
DNS服务名是否能解析到正确 ClusterIP

Pod IP 不通和 Service 不通不是一回事。Pod IP 不通偏向 CNI、路由、隧道、防火墙;Pod IP 通但 Service 不通,问题在 kube-proxy、EndpointSlice、Service selector 或端口。

常见 CNI

插件特点场景
Flannel简单,主要解决跨节点通信实验、小集群
CalicoBGP/VXLAN/IPIP、NetworkPolicy 成熟传统机房和通用生产集群
CiliumeBPF 数据面、Hubble 可观测性、策略和 Gateway 能力强新集群,需要强网络观测和安全能力

传统机房里 Calico 很常见——它对 BGP、IPIP、VXLAN 这些模式都支持得比较成熟。新集群如果网络团队能一起维护,Cilium 值得评估,它把排查方式带到 eBPF、Hubble 和策略可视化体系里。

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 路由性能好,但依赖网络设备配合

隧道模式的好处是底层网络不用知道 Pod 网段——宿主机之间先包一层再发。代价是多一层封装,MTU 配不好时大包异常。BGP 模式把 Pod 网段直接告诉网络设备,更直接,但需要交换机或路由器配合。

MTU、防火墙和 conntrack

CNI 网络问题里,MTU 很容易被忽略。VXLAN、IPIP 封装会增加额外头部,原本 1500 的包封装后可能超过底层 MTU。表现通常是小包通、大包不通,或者 TCP 握手成功但传大响应时卡住。

防火墙除了 TCP 端口,还要看协议类型:

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

conntrack 表满时,Service 访问出现间歇失败:

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

接口突然超时、Service 访问随机失败、节点日志出现 nf_conntrack: table full 时,问题不在 Deployment YAML 上,要看节点连接跟踪和短连接数量。

跨节点不通排查

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 看不到底层网络问题。