概述
你有没有遇到过这种情况:
- Pod 在同一个集群,但不同节点上的 Pod 无法互相访问?
- Service 的 ClusterIP 能访问,但 Pod 的 IP 直接访问却超时?
- 换了 CNI 插件后,网络性能突然变差,延迟飙升?
- 想实现网络策略隔离,却发现策略完全不生效?
- 排查网络问题时,对着 iptables 规则一头雾水?
这些问题,很可能是因为你没有理解 Kubernetes 的核心网络机制------网络模型与 CNI 插件
什么是 Kubernetes 网络模型与 CNI
Kubernetes 网络模型是 K8s 为 Pod 和 Service 定义的网络通信规范 ,CNI 是 实现该规范的网络插件接口。
简单来说:
- Kubernetes 网络模型:规定了 Pod 之间、Pod 与 Service 之间该如何通信
- CNI:是让不同网络方案(如 Calico、Flannel)接入 K8s 的"通用插座"
它是 Kubernetes 实现跨节点 Pod 通信 与服务发现 的基础架构
为什么需要 Kubernetes 网络模型
在原生 Docker 环境中,容器网络是孤立的,每个容器有自己的网络命名空间。
如果没有统一的网络模型,K8s 集群会面临:
| 问题 | 后果 |
|---|---|
| Pod IP 不唯一 | 不同节点的 Pod 可能使用相同 IP,导致冲突 |
| 跨节点通信困难 | Pod 无法直接访问其他节点的 Pod,需复杂 NAT 转发 |
| Service 无法发现 | 无法通过统一入口访问动态变化的 Pod |
| 网络策略失效 | 无法控制 Pod 之间的流量访问权限 |
| 调试复杂 | 每个 CNI 插件的网络实现不同,排查问题无统一标准 |
没有统一网络模型的后果
假设你的集群结构如下:
Kubernetes 集群
├── 节点 1
│ └── Pod A: 10.244.1.2 (Flannel 分配)
├── 节点 2
│ └── Pod B: 10.244.2.3 (Flannel 分配)
└── 节点 3
└── Pod C: 192.168.1.5 (Calico 分配,与 Pod A/B 网段不同)
如果你混用不同 CNI 插件或不配置网络模型:
- Pod A 无法直接 ping 通 Pod B,因为网段不互通
- Pod C 的 IP 与 Pod A/B 冲突,导致路由混乱
- Service 无法正确转发流量到后端 Pod
- 结果:集群网络瘫痪,服务不可用
Kubernetes 网络模型的四大核心要求
Kubernetes 官方定义了网络模型必须满足的四个基本条件:
| 要求 | 说明 | 示例 |
|---|---|---|
| Pod IP 唯一且可达 | 每个 Pod 分配唯一 IP,所有 Pod 可直接通信(无需 NAT) | Pod A (10.244.1.2) 可直接访问 Pod B (10.244.2.3) |
| 节点与 Pod 互通 | 节点上的进程可直接访问 Pod,反之亦然 | 节点 1 可访问 Pod B,Pod A 可访问节点 2 的 kubelet |
| Service 虚拟 IP | Service 分配 ClusterIP,通过 iptables/IPVS 转发到后端 Pod | Service web-service (10.96.100.1) 转发到 Pod A/B/C |
| 网络策略支持 | 可通过 NetworkPolicy 控制 Pod 之间的流量 | 禁止 Pod A 访问 Pod C,仅允许访问 Pod B |
关键点:所有 Pod 必须在同一个扁平网络空间中,无需 NAT 即可直接通信
CNI 插件的核心作用
CNI 是 Container Network Interface 的缩写,它是 K8s 与网络插件之间的标准接口。
CNI 插件的职责:
- 为 Pod 分配 IP 地址
- 配置 Pod 的网络接口(veth pair)
- 设置路由规则,实现跨节点通信
- 实现网络策略(如 Calico 的 BGP 策略)
常见 CNI 插件对比:
| 插件 | 网络模式 | 适用场景 | 性能 | 功能 |
|---|---|---|---|---|
| Flannel | Overlay (VXLAN) | 简单集群,快速部署 | 🟡 中 | 基础连通性 |
| Calico | BGP/路由 | 生产环境,网络策略 | 🟢 高 | 网络策略、BGP 路由 |
| Cilium | eBPF | 高性能,安全策略 | 🟢 极高 | eBPF 加速、L7 策略 |
| Weave | Overlay (P2P) | 多集群互联 | 🟡 中 | 跨集群通信 |
| Macvlan | 物理网络直通 | 需要 Pod 与物理网络同网段 | 🟢 高 | 直通物理网络 |
主流 CNI 插件工作原理
Flannel:Overlay 网络(VXLAN 模式)
节点 1 (192.168.1.10)
├── Pod A: 10.244.1.2
│ └── 网络接口:eth0 (10.244.1.2)
│ └── 路由:10.244.0.0/16 via 10.244.1.1 (flannel.1)
└── Flannel 网桥:cni0
└── 封装:VXLAN (将 Pod A 的包封装到节点 IP)
节点 2 (192.168.1.20)
├── Pod B: 10.244.2.3
│ └── 网络接口:eth0 (10.244.2.3)
│ └── 路由:10.244.0.0/16 via 10.244.2.1 (flannel.1)
└── Flannel 网桥:cni0
└── 解封装:接收 VXLAN 包,转发到 Pod B
流程:Pod A → cni0 → flannel.1 (VXLAN 封装) → 节点 2 → flannel.1 (解封装) → cni0 → Pod B
Calico:BGP 路由模式
节点 1 (192.168.1.10)
├── Pod A: 10.244.1.2
│ └── 网络接口:eth0 (10.244.1.2)
│ └── 路由:10.244.2.0/24 via 192.168.1.20 (节点 2)
└── BGP 客户端:宣告 10.244.1.0/24 网段
节点 2 (192.168.1.20)
├── Pod B: 10.244.2.3
│ └── 网络接口:eth0 (10.244.2.3)
│ └── 路由:10.244.1.0/24 via 192.168.1.10 (节点 1)
└── BGP 客户端:宣告 10.244.2.0/24 网段
路由表同步:节点 1 和节点 2 通过 BGP 交换路由信息
流程:Pod A → eth0 → 路由表 (10.244.2.0/24 via 192.168.1.20) → 节点 2 → eth0 → Pod B
Cilium:eBPF 加速模式
节点 1 (192.168.1.10)
├── Pod A: 10.244.1.2
│ └── eBPF 程序:直接在内核层处理网络包
│ └── 绕过 iptables,通过 eBPF 映射转发
└── eBPF 映射:存储 Pod IP 与节点 IP 的对应关系
节点 2 (192.168.1.20)
├── Pod B: 10.244.2.3
│ └── eBPF 程序:接收包后直接转发到 Pod
└── eBPF 映射:同步节点 1 的 Pod 路由信息
流程:Pod A → eBPF 程序(内核层)→ 节点 2 → eBPF 程序 → Pod B(无 iptables 开销)
验证效果
你可以通过以下方式验证 CNI 插件是否生效:
查看 Pod 网络配置
bash
# 查看 Pod IP
kubectl get pods -o wide
# 进入 Pod 查看网络接口
kubectl exec -it pod-a -- ip addr
# 查看 Pod 路由表
kubectl exec -it pod-a -- ip route
测试跨节点通信
bash
# 在 Pod A 中 ping Pod B(不同节点)
kubectl exec -it pod-a -- ping 10.244.2.3
# 从节点 1 访问 Pod B
ping 10.244.2.3 # 需确保节点路由正确
检查 CNI 插件状态
bash
# 查看 CNI 插件 Pod
kubectl get pods -n kube-system | grep calico # 或 flannel/cilium
# 查看 CNI 配置
cat /etc/cni/net.d/10-calico.conflist # 或 10-flannel.conflist
调试网络策略
bash
# 创建 NetworkPolicy
kubectl apply -f network-policy.yaml
# 测试策略是否生效
kubectl exec -it pod-a -- curl pod-c:80 # 应被拒绝
最佳实践
| 建议 | 说明 |
|---|---|
| 生产环境选 Calico/Cilium | Flannel 功能简单,适合测试环境 |
| 启用 BGP 模式(Calico) | 比 VXLAN 性能更高,无封装开销 |
| 使用 eBPF(Cilium) | 适合高性能需求,支持 L7 网络策略 |
| 避免混用 CNI 插件 | 一个集群只能有一个 CNI 插件 |
| 配置网络策略 | 默认拒绝所有流量,按需开放 |
| 监控网络性能 | 使用 cilium monitor 或 calicoctl 查看流量 |
| 定期更新 CNI 插件 | 修复安全漏洞,提升性能 |
常见问题
| 陷阱 | 说明 | 解决方案 |
|---|---|---|
| Pod 跨节点无法通信 | CNI 插件未正确配置 BGP 或 VXLAN | 检查 CNI Pod 日志,确认路由同步 |
| 网络策略不生效 | CNI 插件不支持 NetworkPolicy | 选择 Calico/Cilium,避免 Flannel |
| IP 地址冲突 | Pod CIDR 与节点 CIDR 重叠 | 确保 podCIDR 与 serviceCIDR 不重叠 |
| 性能低下(Flannel VXLAN) | 封装/解封装消耗 CPU | 切换到 Calico BGP 或 Cilium eBPF |
| CNI 插件崩溃 | 节点资源不足或配置错误 | 检查 CNI Pod 的资源限制和日志 |
| Service 无法访问 Pod | kube-proxy 未正确配置 iptables | 检查 kube-proxy Pod 状态 |
| 节点与 Pod 无法互通 | 节点防火墙阻止 Pod CIDR | 开放节点间 Pod CIDR 的流量 |
总结
| 关键点 |
|---|
| Kubernetes 网络模型要求所有 Pod 在同一扁平网络中 |
| CNI 插件是实现该模型的具体方案,不同插件性能差异大 |
| Calico(BGP)和 Cilium(eBPF)是生产环境首选 |
| 正确配置 CNI 能避免网络隔离、性能低下等问题 |
Kubernetes 网络模型与 CNI 的关系:
┌─────────────────────────────────────────────────────────┐
│ Kubernetes 网络体系 │
├─────────────────┬─────────────────┬─────────────────────┤
│ 网络模型 │ CNI 插件 │ 具体实现 │
│ (规范) │ (接口) │ (方案) │
│ │ │ │
│ • Pod IP 唯一 │ • CNI 标准 │ • Calico (BGP) │
│ • 跨节点互通 │ • IPAM 插件 │ • Cilium (eBPF) │
│ • Service 转发 │ • 网络策略 │ • Flannel (VXLAN) │
└─────────────────┴─────────────────┴─────────────────────┘
一句话记住它:
Kubernetes 网络模型是"交通规则",CNI 插件是"修路公司",不同的公司修的路(网络方案)性能不同。