Kubernetes CNI 部署与调优实践¶
这篇文章解决什么问题¶
如果你要去做云服务实施工程师,对方要求“有 CNI 部署调优实践经验”,那面试官真正想确认的通常不是你会不会背 CNI = Container Network Interface,而是想知道:
- 你是否理解 Kubernetes Pod 网络为什么要靠 CNI 实现
- 你是否知道不同 CNI 插件的网络模型差异
- 你是否能把 CNI 部署起来,并知道部署前要检查什么
- 你是否排查过 Pod 不通、Service 不通、DNS 慢、跨节点丢包这类问题
- 你是否知道 MTU、iptables、IPVS、eBPF、NetworkPolicy、Pod CIDR 这些关键词背后的工程影响
这篇文章会按“理解原理 -> 部署实施 -> 调优排障 -> 面试表达”的顺序整理。目标不是一次变成网络专家,而是先建立一套能落地、能解释、能排障的 CNI 知识框架。
CNI 到底是什么¶
CNI,全称 Container Network Interface,是容器网络接口规范。它本身不是某一个具体网络组件,而是一套标准接口。
在 Kubernetes 里,Pod 创建出来以后,不能只是有容器进程,还必须拥有符合 Kubernetes 网络模型的网络能力。这里至少包括:
- 每个 Pod 有自己的 IP
- Pod 之间默认可以直接互通
- Pod 访问 Service 能被正确转发
- 跨节点 Pod 能互通
- 网络策略可以按命名空间、Pod 标签、端口等维度做访问控制
Kubernetes 自己并不直接实现这些底层网络细节,而是把“给 Pod 接入网络”的动作交给 CNI 插件。常见插件包括 Flannel、Calico、Cilium、Canal、Weave Net 等。
更准确地说,CNI 负责的是“容器网络命名空间如何接入宿主机和集群网络”。当 kubelet 创建 Pod sandbox 时,会通过容器运行时调用 CNI 插件。CNI 插件会完成分配 IP、创建 veth、配置路由、设置网桥或隧道、写入 iptables 或 eBPF 规则等动作。
Kubernetes 网络模型¶
理解 CNI 之前,先要理解 Kubernetes 对网络的基本假设。
Kubernetes 的 Pod 网络模型可以概括成三句话:
- 每个 Pod 都有独立 IP
- 任意 Pod 可以通过对方 Pod IP 直接通信,不需要 NAT
- 节点上的组件也可以和 Pod IP 通信
这套模型看起来简单,但工程上并不简单。因为 Pod 会分布在不同节点上,节点之间可能在同一个二层网络,也可能跨交换机、跨可用区、跨 VPC,甚至底层网络不支持直接路由 Pod CIDR。
所以 CNI 插件的核心任务就是让下面这件事成立:
不同 CNI 插件的差异,本质上就是它们用什么方式让 Pod IP 在集群里可达。
Pod 创建时 CNI 做了什么¶
一次典型 Pod 启动过程中,网络相关流程大致如下:
用户提交 Pod YAML
|
apiserver 写入期望状态
|
scheduler 把 Pod 调度到某个 Node
|
kubelet 发现本节点有新 Pod
|
containerd 创建 Pod sandbox
|
containerd 调用 CNI 插件
|
CNI 插件分配 IP、创建网卡、配置路由和规则
|
Pod 进入 Running
在节点上,Pod 一般运行在自己的 network namespace 里。CNI 会创建一对 veth pair,一端放进 Pod 的网络命名空间,作为 Pod 内看到的 eth0;另一端留在宿主机上,连接到 Linux bridge、路由表、隧道设备或 eBPF datapath。
可以用下面的简化图理解:
Pod network namespace
eth0 10.244.1.10
|
| veth pair
|
Host network namespace
vethxxxx
|
| bridge / route / vxlan / eBPF
|
Node network
如果你能把这张图讲清楚,面试官基本会认为你不是只背概念,而是真的理解 Pod 网络是怎么接到宿主机网络里的。
CNI 配置文件在哪里¶
在大多数 Linux 节点上,CNI 相关文件通常位于:
常见含义如下:
/etc/cni/net.d/保存 CNI 配置文件,例如10-calico.conflist/opt/cni/bin/保存 CNI 二进制插件,例如bridge、loopback、calico/var/lib/cni/保存 IP 分配记录等运行时状态
排查 CNI 问题时,这几个目录很重要。比如节点重装、CNI 切换、IP 分配异常时,经常需要检查这里是否存在旧配置、旧缓存或多个 CNI 配置文件冲突。
主流 CNI 插件对比¶
Flannel¶
Flannel 是入门最常见的 CNI 之一,部署简单,理解成本低,适合实验环境、小规模集群或对网络策略要求不高的场景。
Flannel 常见后端包括:
vxlan:通过 VXLAN 隧道封装跨节点流量,最常见host-gw:通过宿主机路由转发,性能较好,但要求节点二层可达udp:老方案,性能较差,生产环境很少使用
Flannel 的优点是简单稳定,缺点是默认不提供完整 NetworkPolicy 能力。如果实施场景要求网络隔离、租户隔离、东西向访问控制,Flannel 往往不够。
Calico¶
Calico 是生产环境非常常见的 CNI。它的核心特点是基于三层路由模型,可以支持 BGP,也可以使用 IP-in-IP 或 VXLAN 封装。
Calico 的优势:
- 支持 Kubernetes NetworkPolicy
- 支持 Calico 自己更强的网络策略能力
- 性能和可控性较好
- 适合生产集群、多租户集群和需要访问控制的场景
Calico 常见模式:
BGP:通过 BGP 分发 Pod 路由,适合网络条件可控的生产环境IPIP:通过 IP-in-IP 封装跨节点流量,兼容性较好VXLAN:通过 VXLAN 封装跨节点流量,不依赖 BGPCrossSubnet:同网段不封装,跨网段才封装,兼顾性能和兼容性
如果面试问“你用过哪个 CNI”,选择 Calico 来讲通常更容易展开,因为它既能讲部署,也能讲 NetworkPolicy、BGP、MTU、封装模式和排障。
Cilium¶
Cilium 是近年来很受关注的 CNI,核心技术是 eBPF。它可以用 eBPF 替代一部分传统 iptables 转发路径,在可观测性、安全策略和性能方面都有优势。
Cilium 常见能力:
- 基于 eBPF 的网络转发
- 支持 L3/L4/L7 网络策略
- 支持 Hubble 做网络可观测性
- 可替代 kube-proxy
- 适合云原生平台、微服务治理、安全可观测要求较高的场景
Cilium 的学习曲线比 Flannel 和 Calico 更高,但如果你目标是云服务实施工程师,了解 Cilium 是加分项。尤其是现在很多云厂商和大规模集群开始关注 eBPF 网络方案。
CNI 选型思路¶
实施项目里选 CNI,不应该只看“哪个更流行”,而要看底层网络、隔离要求、性能要求和团队维护能力。
可以按下面几个问题判断:
- 是否需要 NetworkPolicy
- 节点是否在同一个二层网络
- 是否允许 BGP 和路由打通
- 是否跨可用区、跨网段、跨 VPC
- 是否对性能和延迟敏感
- 是否需要网络可观测性
- 团队是否熟悉 eBPF、BGP、iptables、Linux 网络排障
常见建议:
- 学习环境、小规模演示:
Flannel - 通用生产集群:
Calico - 需要强网络策略、云原生可观测、eBPF 能力:
Cilium - 云厂商托管 Kubernetes:优先使用云厂商官方 CNI,例如 AWS VPC CNI、Azure CNI、Terway 等
部署前要确认什么¶
部署 CNI 之前,一定要先确认集群的网络规划。很多 CNI 问题不是安装命令错了,而是一开始网段规划就有问题。
Pod CIDR¶
Pod CIDR 是 Pod IP 使用的地址段。它不能和下面这些网段冲突:
- 节点物理网段
- Service CIDR
- VPC CIDR
- 机房已有内网网段
- VPN、专线、对端系统网段
例如:
如果 Pod CIDR 和已有内网冲突,后面可能出现非常隐蔽的问题:某些外部服务访问不了、跨网络访问走错路由、Pod 到机房数据库偶发不通。
Service CIDR¶
Service CIDR 是 Kubernetes ClusterIP 使用的地址段,一般在集群初始化时确定。它也不能和 Pod CIDR、节点网段、已有业务网段冲突。
Service CIDR 后期修改成本很高,生产环境要在初始化前确认清楚。
MTU¶
MTU 是 CNI 调优里非常容易被忽略的一点。
如果 CNI 使用 VXLAN、IPIP、Geneve 等封装方式,会额外增加报文头开销。底层网卡 MTU 如果是 1500,Pod 侧 MTU 就不能也简单设置成 1500,否则可能出现分片、丢包、连接卡顿、TLS 握手失败等问题。
常见经验值:
不同插件和云厂商环境会有差异,实施时要查官方建议,并结合 ping -M do -s、tracepath、业务压测确认。
内核参数¶
部署前常见检查项:
sysctl net.ipv4.ip_forward
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables
lsmod | grep br_netfilter
常见要求:
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
这些参数会影响 Linux 转发和 bridge 流量进入 iptables 的行为。不同发行版、不同 kubeadm 版本、不同 CNI 对这些参数的依赖不完全一样,但作为实施工程师,至少要知道它们和 Pod 网络转发有关。
以 Calico 为例的部署流程¶
下面用 Calico 举例说明 CNI 部署思路。实际生产部署时建议以官方文档和目标 Kubernetes 版本为准。
1. 初始化集群时指定 Pod CIDR¶
如果使用 kubeadm,可以在初始化时指定:
Calico 默认常见 Pod CIDR 是 192.168.0.0/16,但生产环境不一定照抄,应该根据企业内网规划调整。
2. 安装 Calico¶
常见方式是应用官方 manifest 或使用 Operator。
安装后检查:
kubectl get pods -n kube-system | grep calico
kubectl get nodes -o wide
kubectl describe node <node-name>
重点看:
calico-node是否 Running- 节点是否从
NotReady变为Ready - Pod 是否能获得 IP
- CoreDNS 是否正常启动
- 跨节点 Pod 是否互通
3. 验证 Pod 网络¶
可以创建两个测试 Pod,分别调度到不同节点,然后互相访问。
kubectl run test-a --image=busybox:1.36 -- sleep 3600
kubectl run test-b --image=busybox:1.36 -- sleep 3600
kubectl get pod -o wide
kubectl exec -it test-a -- ping <test-b-pod-ip>
还要验证 Service:
kubectl expose pod test-b --port=80 --target-port=80
kubectl get svc
kubectl exec -it test-a -- wget -S -O- http://<service-cluster-ip>
如果 Pod IP 能通但 Service 不通,问题可能不在 CNI 本身,而在 kube-proxy、iptables、IPVS、CoreDNS 或 Service Endpoints。
CNI 调优关注点¶
封装模式¶
封装模式直接影响性能、兼容性和网络复杂度。
以 Calico 为例:
IPIP Always:所有跨节点流量都封装,兼容性好,但有额外开销IPIP CrossSubnet:同网段不封装,跨网段封装VXLAN Always:使用 VXLAN 封装,常见于不方便使用 BGP 的环境BGP:直接通过路由打通 Pod CIDR,性能好,但对网络规划和运维能力要求更高
实施建议是:如果客户网络能力一般、项目交付周期紧,优先选择兼容性更好的封装方案;如果是自建机房、大规模生产集群、网络团队能配合,则可以考虑 BGP 或 CrossSubnet 来降低封装开销。
MTU 优化¶
MTU 不合理的表现经常不是“完全不通”,而是:
- 小包能通,大包不通
ping正常,HTTP 上传卡住- TLS 握手偶发失败
- 跨节点访问比同节点访问更容易出问题
- 大量重传导致吞吐下降
排查命令:
如果底层 MTU 是 1500,而 CNI 使用 VXLAN,Pod MTU 设置到 1450 往往更稳。云环境里还要考虑云厂商 VPC、Overlay 网络、负载均衡、专线网关的限制。
kube-proxy 模式¶
kube-proxy 常见模式有 iptables 和 ipvs。
iptables 模式简单通用,但 Service 数量很多时规则膨胀明显,排查也会比较痛苦。
ipvs 模式适合 Service 数量较多、并发较高的集群,性能和可观测性通常更好,但要求内核模块支持。
检查方式:
如果使用 Cilium 的 kube-proxy replacement,则要换成 Cilium 自己的诊断方式,例如 cilium status、cilium service list。
NetworkPolicy¶
NetworkPolicy 是很多生产环境必须考虑的能力。它可以限制哪些 Pod 能访问哪些 Pod,按命名空间、标签、端口做控制。
需要注意:Kubernetes 定义了 NetworkPolicy API,但具体执行依赖 CNI 插件。不是所有 CNI 都支持 NetworkPolicy。
简单示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: app
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
policyTypes:
- Ingress
实施时要提醒客户:NetworkPolicy 一旦启用默认拒绝策略,很容易误伤 DNS、监控、日志采集、Ingress Controller 到后端服务的访问。上线前必须做流量梳理和灰度验证。
DNS 性能¶
很多人把 DNS 问题归到 CoreDNS,其实 CNI、kube-proxy、conntrack、节点负载也会影响 DNS 体验。
常见表现:
- Pod 内解析域名慢
- 偶发
Temporary failure in name resolution - CoreDNS CPU 高
conntrack表满- NodeLocal DNSCache 未启用时高并发服务大量打到 CoreDNS
排查命令:
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
kubectl logs -n kube-system deploy/coredns
kubectl exec -it <pod> -- nslookup kubernetes.default
conntrack -S
sysctl net.netfilter.nf_conntrack_max
调优方向:
- 给 CoreDNS 配合理的副本数和资源限制
- 高并发集群启用 NodeLocal DNSCache
- 检查 conntrack 表容量
- 避免应用频繁短连接和过度 DNS 查询
conntrack¶
conntrack 是 Linux 连接跟踪表,Service NAT、iptables 转发、DNS 短连接等场景都可能依赖它。
conntrack 表满时,典型现象是网络偶发失败,而且很难从应用日志直接看出来。
检查方式:
sysctl net.netfilter.nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count
dmesg | grep conntrack
如果 nf_conntrack_count 长期接近 nf_conntrack_max,就需要结合节点规格、业务连接数、DNS 行为和 Service 访问模式做调优。
常见故障排查路径¶
Pod 一直 ContainerCreating¶
先看事件:
如果看到类似 CNI add failed、failed to setup network、plugin not found,就重点查:
- CNI DaemonSet 是否正常
/etc/cni/net.d/是否有配置/opt/cni/bin/是否有插件二进制- kubelet 日志是否有 CNI 错误
- 节点是否存在旧 CNI 配置残留
常用命令:
kubectl get pods -n kube-system -o wide
journalctl -u kubelet -f
ls /etc/cni/net.d/
ls /opt/cni/bin/
Pod IP 互相不通¶
先判断是同节点不通,还是跨节点不通。
如果同节点通、跨节点不通,通常关注:
- 节点之间防火墙或安全组是否放通
- CNI 封装端口是否被拦截
- 路由是否正确
- MTU 是否异常
- Calico BGP 邻居是否正常
- VXLAN 设备是否存在
例如 VXLAN 常用 UDP 端口 4789,IPIP 使用协议号 4。云安全组或机房防火墙没放通时,会出现跨节点 Pod 不通。
Pod 能通,Service 不通¶
这类问题要把 CNI 和 Service 转发分开看。
检查顺序:
如果 Endpoints 为空,说明 Service selector 没匹配到 Pod,和 CNI 没直接关系。
如果 Endpoints 正常,但 ClusterIP 不通,再看 kube-proxy:
使用 Cilium 替代 kube-proxy 时,要用 Cilium 的命令检查 Service 转发。
DNS 不稳定¶
DNS 问题不要只盯 CoreDNS。建议按下面顺序拆:
- Pod 到 CoreDNS Service IP 是否通
- CoreDNS Pod 是否健康
- CoreDNS 到上游 DNS 是否通
- kube-proxy 或 CNI 转发是否异常
- conntrack 是否接近上限
- 应用是否高频创建短连接并重复解析
验证命令:
kubectl exec -it <pod> -- nslookup kubernetes.default.svc.cluster.local
kubectl exec -it <pod> -- cat /etc/resolv.conf
kubectl logs -n kube-system deploy/coredns
节点 Ready 但新 Pod 没有 IP¶
这种情况经常和 IPAM 有关。
IPAM 负责 IP 地址管理。不同 CNI 的 IPAM 实现不同,比如 host-local、Calico IPPool、云厂商 ENI IP 分配等。
排查方向:
- Pod CIDR 是否耗尽
- Calico IPPool 是否配置正确
- 云厂商 ENI 辅助 IP 是否达到节点上限
/var/lib/cni/是否有异常缓存- CNI 控制器是否正常运行
云上 Kubernetes 特别要注意节点可分配 Pod 数。比如基于 ENI 的 CNI,单节点 Pod 数可能受实例规格、网卡数量和辅助 IP 数限制。
实施工程师应该怎么积累 CNI 经验¶
如果你现在经验不足,最有效的方式不是只看文章,而是搭一个小实验环境,把关键链路跑一遍。
建议按这个顺序练:
- 用 kubeadm 搭一个 2 到 3 节点集群
- 先安装 Flannel,观察 Pod IP、路由、veth、cni 配置文件
- 重建集群或清理后安装 Calico
- 测试同节点 Pod、跨节点 Pod、Service、DNS
- 开启一个 NetworkPolicy,验证访问被允许或拒绝
- 故意改错 MTU 或阻断 VXLAN 端口,观察故障表现
- 对比 iptables 和 IPVS 模式下 Service 转发规则
- 整理一份自己的排障记录
你不需要一开始就做特别大的项目。一个 3 节点实验集群,只要你真的看过路由表、iptables、CNI 配置、Pod 网络命名空间,就已经比单纯背概念强很多。
面试中可以怎么表达¶
如果面试官问:“你有没有 CNI 部署调优经验?”
可以这样答:
我做过 Kubernetes 集群 CNI 的部署和基础排障练习,主要以 Calico 为主,也了解 Flannel 和 Cilium 的差异。部署前我会先确认 Pod CIDR、Service CIDR、节点网段和客户内网是否冲突,然后根据底层网络选择封装模式,比如 VXLAN、IPIP 或 BGP。部署后会验证节点 Ready、CoreDNS、跨节点 Pod 通信、Service ClusterIP、DNS 解析和 NetworkPolicy。
调优方面我会重点关注 MTU、kube-proxy 模式、conntrack、CoreDNS 压力和 NetworkPolicy 规则影响。比如 Overlay 网络下如果底层 MTU 是 1500,Pod MTU 设置不合理就可能导致大包丢包或连接卡顿;Service 规模较大时也会关注 iptables 规则膨胀,必要时考虑 IPVS 或 eBPF 方案。
排障时我一般先拆分问题边界:Pod 创建失败先看 kubelet 事件和 CNI 插件日志;Pod IP 不通先区分同节点和跨节点;Pod 能通但 Service 不通就看 Endpoints 和 kube-proxy;DNS 慢则会同时检查 CoreDNS、Service 转发、conntrack 和节点负载。
这段回答比较稳,因为它既承认你不是在吹“大规模生产经验”,又能体现你知道实施时真正要看什么。
可落地的检查清单¶
部署前:
- 确认 Kubernetes 版本和 CNI 插件版本兼容
- 确认 Pod CIDR、Service CIDR、节点网段不冲突
- 确认节点安全组、防火墙、路由策略
- 确认是否需要 NetworkPolicy
- 确认是否跨网段、跨可用区、跨 VPC
- 确认底层 MTU 和 CNI 封装模式
部署后:
kubectl get nodes节点 Readykubectl get pods -n kube-systemCNI Pod Running- CoreDNS Running
- Pod 能分配 IP
- 同节点 Pod 互通
- 跨节点 Pod 互通
- Pod 能访问 Service ClusterIP
- Pod DNS 解析正常
- NetworkPolicy 行为符合预期
调优和巡检:
- 检查 CNI 插件日志
- 检查 kube-proxy 模式和规则规模
- 检查 MTU
- 检查 conntrack 使用率
- 检查 CoreDNS 延迟和错误日志
- 检查节点路由表和安全组
- 检查 Pod CIDR 或 IPPool 是否接近耗尽
最后总结¶
CNI 是 Kubernetes 网络最核心的落地点。真正的重点不是记住某个插件安装命令,而是理解 Pod 网络如何接入宿主机、跨节点流量如何转发、Service 流量如何被 kube-proxy 或 eBPF 处理、NetworkPolicy 如何生效,以及故障发生时如何拆分边界。
对云服务实施工程师来说,CNI 能力可以分成三层:
- 第一层:能部署,让节点 Ready,让 Pod 正常分配 IP
- 第二层:能验证,确认 Pod、Service、DNS、NetworkPolicy 都符合预期
- 第三层:能排障和调优,知道 MTU、conntrack、封装模式、安全组、路由、iptables/IPVS/eBPF 对业务访问的影响
如果你能围绕这三层准备,再结合一个自己动手搭建的 Calico 实验记录,面试时就不会显得空。CNI 这块确实有点深,但它的学习路径很清楚:先跑通,再看链路,最后练排障。