Appearance
CNI 与 Pod 网络
Kubernetes 只定义网络模型的要求——每个 Pod 有独立 IP、Pod 之间可以互通、Service 提供稳定入口。但 IP 从哪分、跨节点怎么转发、策略怎么拦截、隧道怎么封装——全部交给 CNI 插件。
网络问题的排查容易乱,因为它同时涉及 Linux 网络、K8s 资源对象和具体 CNI 实现。排查时把链路拆开,按顺序逐项验证,不要混在一起。
K8s 网络模型的基本要求
| 要求 | 说明 |
|---|---|
| 每个 Pod 有独立 IP | Pod 内容器共享同一个 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 IP | Pod 之间直连 | CNI、路由、隧道、防火墙 |
| Service ClusterIP | Service 到 Pod | kube-proxy、EndpointSlice、Service selector |
| DNS | Service 名到 ClusterIP | CoreDNS、NetworkPolicy、Pod DNS 配置 |
Pod IP 通但 Service 不通——问题在 kube-proxy 和 Service 层。Service 通但域名不通——问题在 CoreDNS。
常见 CNI
| 插件 | 实现方式 | 适合场景 |
|---|---|---|
| Flannel | VXLAN 隧道 | 实验、小集群,简单够用 |
| Calico | BGP / IPIP / VXLAN,NetworkPolicy 成熟 | 传统机房、通用生产集群 |
| Cilium | eBPF 数据面,Hubble 可观测性,策略和 Gateway 能力强 | 新集群,需要强网络观测和安全能力 |
Calico 在传统机房常见——IPIP、VXLAN、BGP 都支持得成熟,不依赖特定网络设备。Cilium 把数据面做到 eBPF 里,用 Hubble 直接看流量路径和丢包点——排查方式从看 iptables 规则转向流量可视化。
Pod CIDR 和 Service CIDR
K8s 集群有两个网段必须在初始化时规划:
| 网段 | 作用 | 示例 |
|---|---|---|
| Pod CIDR | 给 Pod 分配 IP | 10.244.0.0/16 |
| Service CIDR | 给 ClusterIP 分配 IP | 10.96.0.0/12 |
这两个网段需要避开公司内网、VPN 网段、Docker 默认网段、云 VPC 网段。路由冲突的典型表现不是全部断开,而是部分地址路由异常——访问公司某个网段走了 Pod 路由,或者 VPN 连上后某些 Service 解析出来 IP 能通但端口不通。这类问题容易排查很久,因为现象不是"全断"而是"有时不通"。
Calico 三种模式
| 模式 | 原理 | 注意事项 |
|---|---|---|
| IPIP | Pod 流量封装进 IPIP 包跨节点传输 | 底层网络不感知 Pod 路由,注意 MTU |
| VXLAN | VXLAN 隧道封装跨节点流量 | 云和跨三层网络常见,注意 UDP 4789 端口 |
| BGP | 节点间或和交换机通过 BGP 分发 Pod 路由 | 性能好,但依赖网络设备配合 |
隧道模式(IPIP、VXLAN)的好处:底层网络不用知道 Pod 网段——宿主机之间先包一层再发。代价是多一层封装,MTU 配不好时大包异常。BGP 模式把 Pod 网段直接通告给网络设备,延迟更低,但需要交换机或路由器支持 BGP 对等。
MTU、防火墙、conntrack
CNI 封装会增加额外头部。原本 1500 的包,VXLAN 封装后可能超过底层 MTU——表现是小包通、大包不通,或者 TCP 握手成功但传大响应时卡住。
防火墙除了 TCP 端口,还要放行 CNI 协议:
| 协议 | 端口/类型 |
|---|---|
| VXLAN | UDP 4789 |
| IPIP | IP 协议号 4 |
| BGP | TCP 179 |
| kube-apiserver | TCP 6443 |
| NodePort | TCP/UDP 30000-32767 |
conntrack 表满时 Service 访问出现间歇失败,和 Deployment、Service YAML 无关:
bash
sysctl net.netfilter.nf_conntrack_max
conntrack -S
dmesg | grep -i conntracknf_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 没 IP | CNI 插件异常、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 看不到底层网络问题。