8.5 K8s 生产运维:CNI 网络插件对比与配置
预计阅读时间:19 分钟
📖 目录
6.2:Kubernetes 入门 创建 K8s 集群后,网络插件是第一个需要选择的组件。CNI(Container Network Interface)是 K8s 网络的标准接口,每种插件在性能、功能、复杂度上差异显著。本文对比主流 CNI 插件——Calico、Flannel、Cilium——并提供选型决策依据。
学习目标
- 理解 CNI 规范的四大核心能力(Pod 网络、跨节点通信、Service 抽象、网络策略)
- 能够对比 Flannel、Calico、Cilium 在性能、功能、适用场景上的差异
- 掌握至少一种 CNI 插件的安装、配置与验证流程
- 具备根据集群规模和需求选择合适 CNI 插件的决策能力
前置知识
- K8s 集群基础架构:Master/Worker 节点角色
- Linux 网络基础:网桥、路由表、VXLAN、iptables
- 已完成 kubeadm 集群初始化(了解 --pod-network-cidr 参数)
- Pod IP 分配原理与 CIDR 网段规划
CNI 概述
CNI 定义了容器网络的四个基本能力:
- Pod 网络:每个 Pod 拥有独立 IP
- 跨节点通信:Pod IP 在整个集群内可达
- Service 抽象:kube-proxy 实现的 ClusterIP 负载均衡
- 网络策略:通过 NetworkPolicy 对象控制 Pod 间流量
kubeadm init 后通过 --pod-network-cidr 指定网段,后续安装 CNI 插件。CNI 工作流程
# CNI 调用链路
1. kubelet 检测到新 Pod 需要网络
2. kubelet 调用 CNI 插件的 ADD 命令
3. CNI 插件为 Pod 创建网络命名空间、veth pair
4. CNI 插件配置 Pod IP 和路由
5. CNI 插件配置跨节点通信隧道
# 查看 CNI 配置
ls /etc/cni/net.d/
cat /etc/cni/net.d/10-calico.conflist
# 查看 Pod 的网络命名空间
ls /var/run/netns/
# 或通过 PID 获取
nsenter -t $(crictl inspect | jq -r '.info.pid') --net ip addr # K8s 节点运行时是 containerd,用 crictl 取 PID(docker inspect 仅适用于 docker 运行时)
CNI 的版本管理
插件版本与 Kubernetes 版本有对应关系,升级集群前应同步核对插件兼容性:
- Calico 每代版本标注支持的 K8s 版本范围(如 Calico 3.28 支持 K8s 1.27-1.30),升级 K8s 前先确认插件版本未超范围
- Cilium 与内核版本强相关:升级内核前先查 Cilium 的内核要求(cilium install --version 的 README 有兼容表)
- Flannel 升级频率低,但它的 etcd/k8s 客户端库会随大版本更新,长期不升级可能在新集群上无法工作
- 任何 CNI 的升级都建议先在测试集群验证,再按节点滚动(参考下文迁移流程)
Flannel
Flannel 是 K8s 最早的 CNI 插件之一,以简单著称。它只负责 Pod 网络的跨节点连通,不实现 NetworkPolicy。
| 特性 | VXLAN 模式 | host-gw 模式 |
|---|---|---|
| 封装 | UDP 封装(额外 50 字节头) | 无封装,直接路由 |
| 性能 | 约原生带宽的 85-90% | 接近原生(~97%) |
| 适用 | 跨子网、云环境 | 同一二层网络 |
| 配置 | 默认模式,零配置 | 需宿主机在同一子网 |
# 安装 Flannel
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
# 检查 flannel 运行状态
kubectl -n kube-flannel get pods
# 检查 VXLAN 接口
ip -d link show flannel.1
# 查看 Flannel 分配的子网
kubectl get configmap kube-flannel-cfg -n kube-flannel -o yaml
# 查看节点路由表
ip route | grep flannel
# 切换到 host-gw 模式(需修改 ConfigMap)
kubectl edit configmap kube-flannel-cfg -n kube-flannel
# 修改 Backend.Type 从 vxlan 改为 host-gw
适用场景:小型集群、开发环境、对性能不敏感、不需要网络策略隔离。
Calico
Calico 是目前最常用的 CNI 插件,功能最完整:Pod 网络 + NetworkPolicy + 安全策略。核心基于 BGP 路由实现跨节点通信,无需封装。
安装与模式选择
# 安装 Calico(默认 VXLAN 封装模式)
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml
# 或安装时指定 IPIP 封装
kubectl create -f https://docs.tigera.io/calico/latest/manifests/calico.yaml
# 检查 Calico 组件
kubectl -n calico-system get pods
# 查看节点 BGP 状态(需 calicoctl)
calicoctl node status
# 查看 IP 池配置
calicoctl ipam show
# 查看节点的 BGP 配置
calicoctl get node -o yaml | grep -A 10 bgp
| 模式 | 封装 | 性能 | 适用 |
|---|---|---|---|
| VXLAN | UDP 封装 | ~90% | 公有云、跨子网 |
| IPIP | IP over IP | ~90% | 跨子网,比 VXLAN 头小 |
| BGP(无封装) | 无 | ~97-99% | 同一二层网络 |
Calico NetworkPolicy 增强
# Calico 全局网络策略(不限于命名空间)
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: default-deny
spec:
selector: all()
types:
- Ingress
- Egress
# 基于 DNS 的 Egress 策略
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: allow-dns
spec:
selector: all()
types:
- Egress
egress:
- action: Allow
protocol: UDP
destination:
ports:
- 53
Calico 三种封装模式切换
# 查看当前封装模式
calicoctl get ippool -o yaml
# 切换到 BGP 模式(无封装,需节点在同一二层)
calicoctl get ippool default-ipv4-ippool -o yaml > ippool.yaml
# 修改 spec.vxlanEnabled: false, ipipMode: Never
calicoctl apply -f ippool.yaml
# 切换到 IPIP 模式
# 修改 spec.ipipMode: Always
calicoctl apply -f ippool.yaml
# 查看 BGP 对等体
calicoctl get bgpConfiguration -o yaml
calicoctl get bgpPeer -o yaml
适用场景:生产集群、需要精细网络策略、多租户隔离、混合云场景。
Cilium
Cilium 是基于 eBPF 的新一代 CNI 插件。它在 Linux 内核层面处理网络数据包,性能更高、可观测性更强,无需 kube-proxy。
安装
# 使用 Cilium CLI 安装(推荐)
cilium install --version 1.15
# Helm 安装
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --namespace kube-system \
--set kubeProxyReplacement=true \
--set l2announcements.enabled=true
# 验证安装
cilium status
cilium connectivity test
# 查看 eBPF 程序加载情况
cilium bpf list
# 启用 Hubble 可观测性
cilium hubble enable
cilium hubble port-forward &
hubble observe --namespace default
Cilium 核心特性
| 特性 | 说明 |
|---|---|
| eBPF 数据面 | 绕过 iptables,内核级高效转发 |
| kube-proxy 替代 | 直接基于 eBPF 实现 Service 负载均衡 |
| 网络策略(L3-L7) | 支持 HTTP/gRPC/Kafka 等应用层策略 |
| 可观测性(Hubble) | 实时流量可视化、服务依赖图 |
| 加密(WireGuard) | 节点间 Pod 流量加密 |
| ClusterMesh | 多集群网络互联 |
# Cilium 网络策略示例——允许特定 HTTP 路径
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-http-api
namespace: prod
spec:
endpointSelector:
matchLabels:
app: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/.*"
# 流量可视化
cilium hubble port-forward&
hubble observe --from-pod prod/frontend --to-pod prod/api
Cilium WireGuard 加密
# 启用节点间 WireGuard 加密
cilium install --wireguard
# 验证加密状态
cilium encrypt status
适用场景:需要最高性能、L7 可观测性、多集群互联、想摆脱 kube-proxy 的集群。硬件要求:Linux 内核 5.10+,推荐 5.15+。
选型决策树
是否需要 NetworkPolicy?
├── 否 → Flannel(最简方案)
└── 是 →
├── 需要 L7 策略 / eBPF 可观测性?
│ └── 是 → Cilium
└── 仅 L3/L4 策略,追求稳定 →
├── 已有 iptables 经验?
│ └── 是 → Calico
└── 希望现代化、高性能 →
└── Cilium
| Flannel | Calico | Cilium | |
|---|---|---|---|
| 复杂度 | 低 | 中 | 高 |
| NetworkPolicy | 不支持 | L3/L4 增强 | L3-L7 |
| 性能 | 中(VXLAN) | 高(BGP 无封装) | 最高(eBPF) |
| 可观测性 | 无 | 基础 | 丰富(Hubble) |
| kube-proxy 替代 | 否 | 部分 | 完整 |
| 内核要求 | 无特殊 | 无特殊 | 5.10+ |
| 社区 | 成熟,维护模式 | 活跃,Tigera 维护 | 非常活跃,CNCF |
CNI 规范详解
CNI 是一个被 CNCF 采纳的接口规范(github.com/containernetworking/cni),它约定了 kubelet(或容器运行时)如何调用网络插件。理解规范本身,才能看懂各插件差异的根源:
- 插件形态:每个插件是一个可执行文件,放在
/opt/cni/bin/(如 bridge、veth 等基础插件,以及 calico、cilium 等主插件) - 调用协议:kubelet 以 stdin 传入 JSON 配置(容器 ID、网络命名空间路径、网络配置),插件以 stdout 返回结果(IP、接口名、路由)
- 四个操作:ADD(创建网络)、DEL(删除网络)、CHECK(校验配置一致性)、VERSION(版本协商)
- conflist:
/etc/cni/net.d/下的 .conflist 文件描述"插件链"——例如 Calico 的列表里包含 loopback 插件 + calico 插件,按顺序执行 - 优先级:kubelet 按文件名排序(10-calico.conflist 优先于 99-loopback.conf),选取第一个加载
# 查看集群实际使用的 CNI 配置
cat /etc/cni/net.d/10-calico.conflist | jq '.plugins[].type'
# 常见输出:["calico"] 或 ["loopback","cilium-cni"]
# 手动调试:单独为容器创建网络(模拟 kubelet 调用)
cat <<EOF | sudo CNI_COMMAND=ADD CNI_CONTAINERID=test1 \
CNI_NETNS=/var/run/netns/testns CNI_IFNAME=eth0 \
CNI_PATH=/opt/cni/bin /opt/cni/bin/calico
{"cniVersion":"0.3.1","name":"k8s-pod-network","type":"calico",...}
EOF
各插件共同的职责链:创建 netns → 创建 veth pair(一端进容器,一端在宿主机)→ 分配 IP(IPAM)→ 写路由 → 配置跨节点通路。差异就出在"跨节点通路"这一步。
Flannel VXLAN 原理
Flannel 的默认后端是 VXLAN,理解它就能理解"封装开销"和"MTU 问题"的来源:
- 每个节点上 Flannel 守护进程(flanneld)通过 etcd/K8s API 获得集群子网划分(每个节点 /24),创建
flannel.1VTEP(VXLAN 隧道端点)接口 - Pod 流量从容器 eth0 → cni0 网桥 → 到达 flannel.1
- 目标 Pod 在别的节点时,本机路由表告诉内核走 flannel.1 发往目标节点 IP
- flannel.1 把原始 L2 帧封装进 UDP(VXLAN 头 8 字节 + UDP 头 8 字节 + IP 头 20 字节 + 外层以太网 14 字节 ≈ 50 字节),发给目标节点的 8472 端口
- 目标节点解封装,从本地 cni0 网桥送入目标 Pod
# 查看 VXLAN 隧道接口与路由
ip -d link show flannel.1
# 输出中的 "vxlan id 1 ... port 8472" 即隧道标识与对端端口
# 查看跨节点路由(10.244.0.0/24 是节点 1 的子网)
ip route | grep 10.244
# 10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
# 10.244.1.0/24 via 192.168.1.11 dev flannel.1 onlink
# 抓包验证封装(在源节点执行,观察目标 8472 端口的 UDP 包)
sudo tcpdump -i any -nn 'udp port 8472' -c 5
# 每个数据包比原始帧多约 50 字节 → 这就是 MTU 需要降到 1450 的原因
host-gw 模式则完全不同:不封装,直接在宿主机路由表写"Pod 子网 → 节点 IP"的路由(下一跳直连),性能接近裸机,但要求所有节点在同一二层网络(网关可直达)。
Calico BGP 原理
Calico 跨节点通信使用 BGP(边界网关协议)——没错,就是互联网骨干用的那个协议,Calico 把它搬进了数据中心网络:
- Node-to-Node Mesh:每个节点运行一个轻量 BGP 客户端(bird),与其他节点建立 BGP 会话,互相通告"我负责哪些 Pod 子网"
- 路由通告:例如节点 A 通告
10.244.0.0/24 via A,节点 B 收到后写进自己的路由表,Pod 包直接以节点 IP 为下一跳转发——零封装 - Full Mesh 上限:两两互连的会话数是 n(n-1)/2,超过 ~100 个节点时连接风暴不可控,必须引入路由反射器(Route Reflector),节点只与反射器建立会话
- 与物理网络融合:机房网络设备支持 BGP 时,Calico 节点可直接与交换机建立对等——Pod 网络对企业内网完全可见(混合云/物理机场景的关键能力)
# 查看 BGP 对等体与会话状态
calicoctl node status
# IPv4 BGP status
# +--------------+-----------+-------+------------+-------------+
# | PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
# +--------------+-----------+-------+------------+-------------+
# | 192.168.1.12 | node | up | 02:14:09 | Established |
# +--------------+-----------+-------+------------+-------------+
# 查看节点通告的路由(bird 视角)
sudo birdc show route 2>/dev/null | head -20
# 或从路由表验证:跨节点 Pod 网段下一跳是节点 IP
ip route | grep -E "^10\.244"
# 使用路由反射器后,节点只与反射器建会话
calicoctl get bgpPeer -o yaml | grep -A 5 "nodeRef\|peerIP"
Cilium eBPF 数据面
Cilium 与前两者最大的不同:不用 iptables、不用传统隧道,而是把处理逻辑编译成 eBPF 程序挂载到内核数据路径:
- TC 钩子:在每个 Pod 的 veth 接口上挂 eBPF 程序(tc ingress/egress),数据包进入内核网卡的那一刻就开始处理
- BPF Map:路由表、策略规则、端点状态都存内核态 BPF Map,查表在 eBPF 内完成,不经过用户态
- 绕过 iptables:Service 负载均衡由 eBPF 的
tail_call+ BPF Map 实现(kube-proxy 可以直接卸载),转发路径从"多链遍历"变成"一次查表" - XDP 加速:可选开启 XDP 模式,在驱动层(收包最早阶段)就完成过滤,转发性能进一步提升
- 加密与可观测:WireGuard 加密、Hubble 流量审计同样是 eBPF 程序,与转发路径共享同一套数据,所以 Hubble 能看到精确到连接的详情
# 查看 eBPF 程序挂载情况
cilium bpf prog list | head -30
# 查看 BPF Map(策略规则就存这里)
cilium bpf policy get
# 查看 Service 的 eBPF 实现
cilium bpf lb list | head -10
# 内核依赖:5.10+ 是硬门槛(CONFIG_BPF、CONFIG_BPF_EVENTS 等)
grep CONFIG_BPF /boot/config-$(uname -r)
# CONFIG_BPF=y
# CONFIG_BPF_JIT=y
# CONFIG_BPF_EVENTS=y
一句话总结三种数据面的演进:Flannel 在"用户态做决策 + 内核隧道转发",Calico 在"内核路由表 + 用户态 BGP 同步",Cilium 则"全部下沉到 eBPF 内核程序"。性能差距的根源在于数据包在内核里走的路程长短。
CNI 迁移与故障恢复
迁移场景
生产集群更换 CNI 属于高危操作(会重建所有 Pod 的网络命名空间),推荐流程:
# 1. 准备:确认新 CNI 与现有集群配置兼容(Pod CIDR、kube-proxy 模式)
# 2. 部署新 CNI 组件(先不接管网络)
kubectl apply -f new-cni.yaml
# 3. 逐个节点滚动切换:先打污点排空该节点
kubectl cordon node1 && kubectl drain node1 --ignore-daemonsets --delete-emptydir-data
# 4. 删除旧 CNI 配置,安装新 CNI conflist(指定优先级更高的文件名)
sudo rm /etc/cni/net.d/10-old-cni.conflist
sudo cp new-cni.conflist /etc/cni/net.d/11-new-cni.conflist
# 5. 重启节点上的容器运行时,驱逐的 Pod 会使用新 CNI 重建
sudo systemctl restart kubelet
# 6. 验证该节点 Pod 通信正常后,uncordon 并继续下一个节点
kubectl uncordon node1
故障恢复
- CNI 组件 Crash:先看
crictl ps确认插件容器状态;多数场景重启即可,Pod 网络不重建(veth 仍在) - 节点重启后 Pod 无 IP:检查 kubelet 是否重新调用了 ADD(
journalctl -u kubelet | grep CNI),常见原因是 conflist 丢失 - IP 泄漏:节点异常退出导致 IPAM 未释放 IP,用
calicoctl ipam show --show-blocks或等插件 GC(IPAM GC 周期) - 兜底方案:重要集群建议保留一份"网络故障恢复手册",含 CNI 二进制、conflist 备份与重启序列
最后一条建议特别提醒:把当前 CNI 的 conflist、镜像版本、安装命令存档(建议直接提交到 Git),一旦集群重建或灾备切换,能按文档 15 分钟内恢复网络——多数"CNI 事故"的根源其实是"没人记得当初怎么装的"。
Pod 网络通信路径对比
把三种插件放在"一个数据包从 Pod A 到跨节点 Pod B"的旅程中对比,数据面差异一目了然:
| 数据包路径 | Flannel VXLAN | Calico BGP | Cilium eBPF |
|---|---|---|---|
| 容器出口 | veth → cni0 网桥 | veth → cali- 接口直连 | veth → eBPF TC 程序(无网桥) |
| 跨节点封装 | VXLAN(+50B) | 无封装,纯路由 | 可选(覆盖模式)或无封装 |
| 路由决策 | 内核路由表(flannel.1 隧道) | 内核路由表(BGP 同步) | BPF Map 查表 |
| 策略检查 | 不支持 | iptables 链(Felix 渲染) | eBPF 程序内联检查 |
| 性能特征 | 封装开销 + 隧道转发 | 接近原生,iptables 遍历有少量开销 | 一次查表,最接近线速 |
# 实战验证三种路径(用 traceroute 观察数据包去向)
# Flannel 集群:包会经过隧道设备
kubectl exec <pod-a> -- traceroute -n <pod-b-ip>
# 第一跳通常是 10.244.x.1(cni0 网桥),随后走 flannel.1
# Calico 集群:直接路由,看不到隧道
kubectl exec <pod-a> -- traceroute -n <pod-b-ip>
# 直接显示对端 Pod 所在节点 IP(BGP 写入的路由)
# Cilium 集群:traceroute 可能显示"不通"——eBPF 转发不产生 TTL 变化的
# 传统逐跳行为,用 cilium monitor 观察更准确
cilium monitor --type trace --output json | head -5
MTU 问题的本质
封装模式下 MTU 必须减去封装头(VXLAN 约 50B、IPIP 约 20B),否则大包(如 1500 字节 HTTP 响应)被分片或丢弃。排查口诀:小包通、大包断,先查 MTU。
# 快速定位 MTU 问题
# 1. 测不同大小包的连通性
ping -M do -s 1472 -c 3 <pod-ip> # 1500-28=1472,成功则 MTU ≥ 1500
ping -M do -s 1400 -c 3 <pod-ip> # 缩小到 1400 再试
# 2. 两端都测:容器内和节点上分别执行
# 3. 对比容器 eth0 MTU 与物理网卡 MTU
kubectl exec <pod> -- ip link show eth0
ip link show eth0
# 预期:容器 MTU = 物理 MTU - 封装头(云环境常见物理 MTU 1420/1450)
选型案例分析
把决策树落到真实场景,三个案例覆盖最常见的选择困惑:
案例一:50 节点电商生产集群
需求:多租户隔离 + 精细网络策略 + 跨可用区部署(三层网络)。选型:Calico(VXLAN 封装,跨子网)。理由:策略成熟稳定、团队有 iptables 经验、无需内核升级;封装开销在业务可接受范围。进阶:上量后评估切换 Cilium 获得更好性能与可观测性,作为二期计划。
案例二:10 节点内部开发集群
需求:快速交付、无网络策略需求、机器配置低。选型:Flannel(host-gw)。理由:零配置、零维护、性能接近原生;安全隔离靠命名空间约定,不依赖网络层。注意:host-gw 要求节点同二层,云上多子网场景退回 VXLAN。
案例三:金融核心交易集群(低延迟)
需求:微秒级延迟、L7 审计、审计日志留痕。选型:Cilium(eBPF + Hubble)。理由:数据面延迟最低、Hubble 提供逐连接审计视图、内核 5.15+ 满足;eBPF 的确定性与无 iptables 遍历在峰值流量下表现稳定。成本:团队需要学习 eBPF 排障方法论,监控体系要配套升级。
| 场景 | 选型 | 决定性因素 |
|---|---|---|
| 中小集群、无策略需求 | Flannel | 最简维护 |
| 生产、需策略、有 iptables 经验 | Calico | 成熟稳定 |
| 低延迟 / L7 审计 / 多集群 | Cilium | 性能与可观测性 |
选型还有一个容易忽略的维度:团队能力与排障效率。CNI 出问题时,排障工具链的成熟度直接决定 MTTR——Calico 有 calicoctl/node diags、社区资料海量;Cilium 的 cilium connectivity test 能一键自检但要求团队理解 eBPF 概念;Flannel 问题通常简单直接(隧道状态、MTU)。选择团队"看得懂、修得快"的插件,比纸面性能参数更重要。
最后给一个务实的兜底建议:把"备选方案"也写进架构文档——如果当前插件出现无法短期解决的重大问题(如内核兼容性),集群是否有切换到另一插件的路径?这决定了你是否有退路,而不是被困在一个插件上。
常见错误
问题一:Pod IP 与宿主机网段冲突
现象:Pod 无法跨节点通信,或节点间路由异常。
原因:--pod-network-cidr 与节点所在网段重叠。
解决:规划 Pod CIDR 时避开已有网段(如 10.0.0.0/8 已被使用则用 172.20.0.0/16)。
# 检查节点网段
ip addr show | grep "inet "
# 确保 Pod CIDR 不与之重叠
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep pod-cluster-cidr
问题二:CNI 插件安装顺序错误
现象:kubeadm init 后节点一直 NotReady。
原因:CNI 插件必须在 kubeadm init 之后、节点 join 之前安装。
解决:确认安装顺序,使用 kubeadm join --skip-phases=preflight 跳过检查后安装 CNI。
问题三:Flannel VXLAN 封装导致 MTU 问题
现象:大包传输失败,但小包正常。
原因:VXLAN 封装增加 50 字节头,导致 MTU 超限。
解决:将 Flannel MTU 设为 1450(标准 MTU 1500 减去封装头),或在云环境中调整网络 MTU。
# 查看当前 MTU
ip link show flannel.1
# 修改 Flannel MTU(ConfigMap)
kubectl edit configmap kube-flannel-cfg -n kube-flannel
# 添加配置:data-backend-mtu: "1450"
问题四:Calico BGP 路由未同步
现象:节点间 Pod 通信间歇性中断。
原因:BGP 对等体未建立或路由未传播。
解决:检查 BGP 状态和路由表。
# 检查 BGP 对等体状态
calicoctl get bgpPeer -o wide
# 查看节点路由
ip route | grep bird
# 手动触发路由同步
calicoctl node diags
问题五:Cilium eBPF 程序加载失败
现象:Cilium Pod 启动失败,日志显示 eBPF 相关错误。
原因:内核版本过低或缺少 eBPF 相关内核模块。
解决:升级内核到 5.10+,确认内核配置启用 BPF。
# 检查内核版本
uname -r
# 检查 eBPF 支持
ls /sys/fs/bpf/
# 检查内核配置
grep CONFIG_BPF /boot/config-$(uname -r)
最佳实践
- 新集群首选 Cilium——eBPF 是 K8s 网络的未来方向
- 已有 Calico 集群无需迁移——Calico 成熟稳定
- 最小集群(<5 节点)Flannel 就够用——省心
- 多集群互联用 Cilium ClusterMesh 或 Calico Multi-cluster
- 安装前确认 Pod CIDR 不与企业网络冲突,kube-proxy 模式与 CNI 兼容
- 生产环境启用网络策略——即使当前不需要,也应预留能力
- 定期检查 CNI 健康状态——监控 Pod 路由表和封装隧道状态
练习题
练习一:CNI 对比测试
分别在三个测试集群安装 Flannel、Calico、Cilium,使用 iperf3 测试 Pod 间带宽,使用 ping 测试延迟,记录对比数据并分析差异原因。
练习二:Calico 模式切换
在现有 Calico 集群上,将封装模式从 VXLAN 切换到 BGP(需同一二层网络),验证切换后 Pod 通信是否正常,并对比切换前后的性能差异。
练习三:Cilium Hubble 可观测性
安装 Cilium 并启用 Hubble,部署一个微服务应用,通过 Hubble UI 观察服务间调用关系和流量拓扑。导出一段异常流量日志并分析原因。
学习检查点
学完本章后,请检验自己是否掌握以下内容:
| 检查项 | 自测问题 | 验证方法 |
|---|---|---|
| 概念理解 | 能用自己的话解释 CNI 插件的职责和 Calico/Cilium 架构 | 尝试向他人讲解 |
| 命令操作 | 能不查文档完成 CNI 插件安装和网络策略配置 | 在终端实际执行 |
| 原理掌握 | 能说出 CNI 的容器网络命名空间和路由原理 | 画出流程图 |
| 故障排查 | 能独立排查 CNI 插件导致 Pod 无法分配 IP 的问题 | 模拟故障并修复 |
| 最佳实践 | 能说明为什么生产环境推荐使用 Calico 或 Cilium | 对比不同方案 |
本章总结
CNI 选型应按集群规模与功能需求决定:Flannel 最简单、只保证连通性,适合小型集群;Calico 功能均衡,BGP 无封装性能好且 NetworkPolicy 成熟稳定;Cilium 基于 eBPF 性能与可观测性最强,支持 L3-L7 策略,但要求内核 5.10+。务必记住 NetworkPolicy 依赖 CNI 支持(Flannel 不支持),且插件须在 kubeadm init 后、节点 join 前安装,Pod CIDR 需避开现有网段。
延伸阅读
- 6.2:Kubernetes 入门 Kubernetes 容器编排入门
- k8s04 K8s 生产运维:NetworkPolicy 网络策略
- 5.12:eBPF 基础 eBPF 基础——现代 Linux 可观测性