1. Kubernetes 网络模型到底在解决什么问题1.1 先理清四个逃不掉的需求很多人一上来就纠结“选哪个 CNI”结果把 Flannel 换成 Calico、Calico 换成 Cilium折腾一圈也没搞明白自己到底要解决什么问题。实际上 Kubernetes 的网络需求可以拆成四件非常具体的事容器与容器之间怎么通信、Pod 与 Pod 之间怎么通信、Pod 与 Service 之间怎么通信、集群与外部世界怎么通信。把这四件事摆清楚选型就不是玄学而是按需匹配。先说容器与容器的通信。同一个 Pod 里的多个容器共享 Network Namespace共享同一个 IP 和端口空间所以它们之间走 localhost 就行这部分基本不需要 CNI 参与Pod 内的 pause 容器负责持有网络命名空间。这个机制很多人容易忽略但它恰恰是后续理解 CNI“只负责 Pod 与 Pod、Pod 与外部”的分界线。然后是 Pod 与 Pod 的通信。这是 CNI 的核心战场。Kubernetes 的网络模型要求集群内每一个 Pod 都必须拥有一个集群内唯一的 IP 地址并且任意两个 Pod 之间可以不经过 NAT 直接通信。这句话包含两层意思第一IP 必须唯一不能冲突第二不管两个 Pod 在不在同一个节点上通信路径都要是通的而且不能做地址转换。这就是为什么我们需要地址分配机制、路由机制或封装机制的根因。第三是 Pod 与 Service 的通信。Service 是一组 Pod 的抽象入口它有自己的虚拟 IPClusterIP。Pod 访问 Service 时流量会被 kube-proxy 的 iptables 规则或 IPVS 规则转发到后端某个具体的 Pod 上。这里要注意一点Service 的 ClusterIP 是 iptables/IPVS 层面的虚拟概念它不属于 CNI 的职责范围但 CNI 选择会影响 kube-proxy 的工作模式比如 eBPF 模式下可以直接绕过 kube-proxy由 Cilium 自己处理 Service 转发。最后是集群对外通信。包括从 Pod 访问互联网出站以及从外部访问集群内的服务入站。出站流量通常依赖 NAT 完成入站则依赖 NodePort、LoadBalancer 或 Ingress。这部分的路径设计也会受 CNI 影响比如 Calico 在云环境下可以跟云厂商的 NAT 网关集成Cilium 可以用 eBPF 实现更高效的入站转发。1.2 每个 Pod 一个 IP 凭什么能做到要理解 CNI 为什么能实现“每个 Pod 一个 IP”得先搞清楚 IP 分配、网络接口创建、路由下发这三个环节是怎么配合的。IP 分配方面Kubernetes 集群在初始化时会给整集群划一个大网段通常用--cluster-cidr指定比如10.244.0.0/16。每个节点再从这个大网段里分到一个子网段比如10.244.1.0/24节点上所有 Pod 的 IP 都会从这个子网段里出。这个“大网段切小网段、按节点分发”的过程是通过 kube-controller-manager 的--allocate-node-cidrstrue参数触发的各个 CNI 方案会通过监听 Kubernetes 的 Node 资源来感知每个节点被分配的子网。网络接口创建方面当调度器把 Pod 调度到某个节点后容器运行时会调用 CNI 插件。CNI 插件要做的第一件事是在宿主机上创建一个虚拟网卡通常是 veth pair一头塞进 Pod 的网络命名空间成为 Pod 里的eth0另一头挂在宿主机的一个中间设备上。这个中间设备在不同 CNI 里不一样Flannel 用的是 cni0 网桥Calico 直接用宿主机的路由表Cilium 则用名为 cilium_host 的虚拟设备。路由下发方面每个方案的路由策略差异很大。Flannel 的 VXLAN 模式会维护一张“节点 IP - 宿主机 IP”的映射表收到跨节点的包就封装成 VXLAN 隧道包送过去Calico 则直接把每个节点当作一台路由器通过 BGP 把路由信息广播出去Cilium 在 eBPF 层面埋点用 eBPF Map 维护节点和 Pod 的关联关系数据路径上不做封装而是直接转发。所以选 CNI 的本质就是选“IP 分配方式 网络接口模型 路由/封装策略”的组合。把这个框架装进脑子里后面看各个方案的对比就顺了。2. 主流 CNI 方案横向对比与核心原理2.1 Flannel入门必经之路但天花板明显Flannel 是 CoreOS 出品的老牌 CNI也是很多新手集群的“初恋”。它的设计哲学非常纯粹只要做到“每个 Pod 唯一 IP、跨节点互通”就行别的一概不管。Flannel 支持三种后端模式VXLAN、host-gw、UDP。UDP 模式性能太差现在基本没人用VXLAN 是默认模式适合所有环境host-gw 性能最好但要求所有节点二层直连。VXLAN 模式的原理可以这样理解每个节点上跑一个 flanneld 守护进程这个进程会监听节点的子网分配情况并在本地维护一张“Pod 网段 - 宿主机 IP”的映射表。当一个 Pod 要访问另一个节点上的 Pod 时cni0 网桥发现目的 IP 不在本节点子网内就把包扔给 flannel.1 这个 VXLAN 隧道设备flannel.1 根据映射表找到对端宿主机 IP把原始的二层帧封装在一个 UDP 包里发过去对端的 flannel.1 收到包后拆掉封装再把包交给对端 cni0 网桥最后送达到目标 Pod。整个过程对 Pod 里的应用完全透明应用感知不到隧道存在。Flannel 最大的优势是简单。二进制架构就一个 DaemonSet不依赖 etcd、不依赖 BGP、不依赖 eBPF部署上去几乎不会出什么问题。它把所有节点当做一个等于号的二层网络来看待逻辑清晰。但 Flannel 的短板也极其明显。第一它没有实现 NetworkPolicy这意味着你无法用 Kubernetes 的原生网络策略做东西向流量的访问控制对大部分生产环境来说这是不可接受的。第二VXLAN 模式把数据包多封装了一层 UDP 头性能有损耗尤其是在高吞吐场景下 CPU 开销会明显上升。第三Flannel 的 VXLAN 转发是查表转发节点规模大了之后每台机器要维护全量节点的映射表ARP 风暴和流表膨胀的问题会被放大。第四不支持多网卡场景下的精细路由选择绑定数据面网卡时得手动配置。坦率说如果你的集群规模在 50 节点以内、对网络策略没有硬性要求、主要用来学习和跑测试环境Flannel 是性价比最高的入门选择。但一旦要考虑生产环境我建议直接跨过 Flannel 去看下面两个方案。2.2 Calico三层路由的典型代表生产环境的常青树Calico 的底层思想与 Flannel 完全不同它不做隧道封装而是把整个集群当成一台“分布式路由器”。Calico 的每个节点上都运行着一个 BGP AgentFelix BirdFelix 负责在宿主机上写入 iptables 规则和路由表Bird 负责通过 BGP 协议与其他节点的 Agent 交换路由信息。Calico 默认的 IPIP 模式会在跨节点通信时做一个简单的 IP 包外层封装。之所以保留这个封装是为了解决“跨网段三层隔离环境下路由不可达”的问题——只要两个节点不在同一个二层网络里IPIP 隧道就成了默认通道。如果你的集群所有节点都在一个大二层内完全可以把 IPIP 模式关掉切到 BGP 纯路由模式这时候数据包不经过任何隧道网络路径和物理网络几乎没有差别性能和延迟都非常接近宿主机原生网络的水平。Calico 在路由层面的表现只是基本功它真正的护城河是丰富的数据面策略能力。Felix 会把 NetworkPolicy 翻译成 iptables 规则逐个 Pod 地匹配生效支持命名空间级、Label 级、IP 级乃至端口级的策略控制。在 Kubernetes 原生网络策略之外Calico 还支持 GlobalNetworkPolicy、GlobalNetworkSet、Profile 等扩展对象可以做跨命名空间、跨集群的安全策略编排。这一点在政企、金融类的合规性要求非常高的场景里尤其有分量。不过 Calico 也不是没毛病。iptables 规则在高并发场景下会带来不可忽视的性能开销。每个新建连接都要遍历规则链Pod 数量上来后规则数量会变得非常大数据面的转发延迟和 CPU 消耗都会涨。如果你的集群形态是“少量大规格节点 海量 Pod”Calico 的 iptables 瓶颈会更明显。再有一个隐性问题Calico 用 BGP 在全网广播路由在节点数超过几百个时BGP 会话的数量和路由表规模会快速膨胀。虽然 Calico 有 Route Reflector 的解决方案但毕竟增加了架构复杂度是需要投入精力去调的。2.3 CiliumeBPF 加持的新一代选手Cilium 是近年社区热度上升最快的 CNI核心卖点是基于 eBPF 技术重构数据面。传统 CNI 在转发路径上要经过“iptables - 内核协议栈 - 用户态 - 内核协议栈”的多次拷贝和遍历Cilium 则把 eBPF 程序直接挂载到网卡收包路径上数据包在进入协议栈之前就被处理掉了。这意味着连接跟踪、负载均衡、网络策略、可观测性数据采集这些事情全部在 eBPF 这个内核虚拟机里完成不需要反复在用户态和内核态之间切换。性能方面 Cilium 的优势在延迟和吞吐两条曲线上都有体现。由于绕过了 iptables 和 kube-proxy 的用户态组件Service 的负载均衡在 eBPF 层直接完成新连接的处理时延可以压缩到微秒级在重负载场景下 CPU 消耗明显低于传统 iptables 方案。我还记得有压测数据表明Cilium 在高并发短连接的场景下P99 延迟能比 iptables 模式低 30% 以上。这个差距在支付、交易、游戏对战类的高频服务里是非常有感知的。Cilium 在功能丰富度上也走了完全不同的路线。它不只是做 Pod 互通而是把 Service Mesh 的可观测性、零信任安全、多集群互联、透明加密全部纳入自己的生态。Cilium 支持 L3/L4 层网络策略也支持 L7 层策略比如只允许特定 HTTP 方法和路径通过——这是绝大多数 CNI 做不到的。它还内置了 Hubble可以直接可视化展示集群内的流量关系排查问题的时候比对着 tcpdump 抓包要直观得多。Cilium 的代价是学习曲线和运维复杂度明显上升。它引入的概念远比 Flannel、Calico 多endpoint、identity、policy、CiliumNetworkPolicy、CiliumClusterwideNetworkPolicy、Hubble 等等。排查问题时可能要同时打开 kubectl、cilium CLI、hubble CLI、各种 CRD 对象对排障者的知识结构要求更高。此外eBPF 对内核版本有硬性要求一般建议至少 5.10 以上内核且要确认节点环境中的内核编译选项是否打开了 CONFIG_BPF、CONFIG_BPF_JIT、CONFIG_BPF_SYSCALL 等相关配置。低内核版本的机器上就算安装了 Cilium也会退回到 xfrm 隧道等兼容模式性能打了折扣。2.4 其他方案与差异化定位在 Flannel、Calico、Cilium 之外还有几个值得关注的方案它们在特定场景下可能比“三巨头”更合适。Weave Net早期以“网状覆盖网络 内置 DNS 与加密”著称。它每个节点上会运行一个 Weave Router所有 Router 之间建立 TCP 和 UDP 连接形成一个网格数据包通过 mesh 转发。Weave 最大的优点是跨主机即使在三层网络环境中也能自动建立加密隧道非常适合多数据中心的场景。缺点是 mesh 模式在节点多的时候连接数量按平方级增长超过 100 节点就会明显吃力现在用得越来越少了。AntreaVMware 开源的项目基于 Open vSwitch 实现 OpenFlow 流表转发。它在数据面上继承了 OVS 的成熟度和高性能同时天然兼容 VMware 的虚拟化体系在混合负载虚拟机和容器共存的场景里有优势。如果你已经重度使用 vSphereAntrea 会是值得评估的选项。Kube-OVN由国内社区主导的项目把 OVNOpen Virtual Network引入 Kubernetes支持 VPC 网络隔离、QoS 限速、固定 IP、网络多租户等高级功能。在需要做云平台自研、多租户网络的场景下Kube-OVN 的功能深度比 Calico 还要高一个档次但社区的国际化程度和生态成熟度目前仍然有限。下面一张表可以直观对比这些方案的关键差异方案数据面模型封装方式NetworkPolicy性能特征典型场景Flannel网桥vethVXLAN / host-gw不支持中低VXLAN 有额外开销学习、测试、小型集群Calico路由表iptablesIPIP / BGP直连支持L3/L4高纯BGP模式随规则变差生产环境、合规安全CiliumeBPF无/DSR/隧道支持 L3-L7极高CPU 消耗低高并发、微服务网格、可观测Weave Netmesh路由器自有封装 可选加密支持能 App 层中低mesh 规模受限多数据中心小规模集群AntreaOVS OpenFlowGeneve / VXLAN支持中高VMware 生态、混合负载Kube-OVNOVNGeneve / VXLAN支持中高多租户、VPC隔离3. 选型决策框架与场景化推荐3.1 选型不是选最好是选最匹配很多人的选型误区是“性能越高越好”于是直接无脑上 Cilium。但如果你只是跑一个小型内部系统Cilium 引入的复杂度反而让日常运维变得痛苦。我的建议是建立一个多维度的决策矩阵把每个维度量化打分后再权衡而不是凭感觉拍脑袋。第一个维度是集群规模与节点形态。50 节点以下的集群Flannel 或 Calico 的 BGP 模式都能轻松驾驭感受不到明显瓶颈200 节点以上的规模Flannel 基本可以排除Calico 需要认真配置 Route ReflectorCilium 因为天生是分布式 eBPF Map 结构在大规模下的表现要更平坦一些。另外还要看单个节点的 Pod 密度Pod 密度高比如单节点超过 100 个 Pod时Cilium 的内存占用和规则复杂度控制得更好。第二个维度是功能需求清单。网络安全策略是不是刚需如果是Flannel 直接出局。是否需要 L7 层策略如果需要Calico 在这一点上并不完整Cilium 的 Envoy 集成方案更成熟。是否需要透明的流量可观测性Cilium Hubble 的开箱体验是无敌的。有没有多租户隔离的需求Kube-OVN 或 Cilium 的多集群特性更合适。第三个维度是运维能力与团队技术栈。你团队里有没有懂 eBPF 或内核的人如果出了问题能不能快速定位对于大多数团队来说Calico 的文档和社区方案最丰富网络问题基本都能搜到答案而 Cilium 的问题是当你真的遇到内核态的疑难杂症社区能提供的帮助是有限的。运维能力和工具链的熟悉程度往往会成为最后的决定性因素。第四个维度是底层基础设施。如果跑在公有云上要考虑云厂商的 VPC 是否支持 IP 直通如阿里云的 Terway、AWS 的 VPC CNI。如果跑在裸机机房要考虑二层网络是否贯通。如果是混合云环境则要评估隧道方案的兼容性。底层网络环境决定了你能不能用纯 BGP 直连还是必须走 VXLAN 这类隧道模式。3.2 场景化推荐照着抄都行我这里给几个偏“模板化”的推荐谈不上绝对正确但适合大多数读者作为起点。场景一学习环境、单机试验、小团队内部工具。推荐 Flannel VXLAN。一套命令就能装完不依赖 BGP、不要求内核版本即使配置出问题把 flannel.1 和 cni0 删掉重新初始化也就十分钟。没什么好纠结的用起来再说。场景二标准生产环境、中等规模50-300节点、有安全合规要求。推荐 Calico BGP 直连模式。这种场景下 Calico 的 iptables 规则数量是可控的NetworkPolicy 能覆盖大部分需求BGP 的成熟度和可排查性都很好。这是目前生产集群中占比最高的组合各种云厂商托管集群也默认提供 Calico算是全行业经验最丰富的组合。场景三大规模集群、高并发微服务、对延迟和性能有极致要求、且团队有内核排查经验。推荐 Cilium开启 eBPF 主机路由和 DSRDirect Server Return模式。Cilium 会把 Service 负载均衡直接放进数据面配合 Hubble 做可观测性排障效率非常高。前提是你要能接受学习成本。场景四VMware 虚拟化平台、机房已有网络设备、希望做网络精细管理。推荐 Antrea 或 Kube-OVN。这两个方案与底层虚拟化生态的整合更紧密而且对现有运维团队的技术栈更友好——OVS 和 OpenFlow 的思路与 VM 网络的运维经验是能对应上的。4. 实操从零部署一套多 CNI 可切换的集群4.1 部署前的关键环境确认我自己踩过不少坑之后总结了几个部署前必须确认的点。先说内核版本这是最容易被忽略的。很多人的 CentOS 7 服务器内核还在 3.10这个版本对网络命名空间、veth、iptables 的支持没问题但跑 Cilium 就费劲了。建议至少升级到 5.10 以上几条命令就能搞定这里不展开。然后是 kubelet 和 kube-controller-manager 的启动参数。kubelet 上要确保--network-plugincni和--cni-conf-dir/etc/cni/net.d、--cni-bin-dir/opt/cni/bin这些参数正确。kube-controller-manager 上则必须设置--allocate-node-cidrstrue和--cluster-cidr10.244.0.0/16。如果不设置节点就分不到子网段CNI 插件自然没法分配 Pod IP这个问题表现成“Pod 启动后一直 ContainerCreating事件里报 failed to get subnet”。很多朋友用的是 kubeadm 部署kubeadm 会为 kube-controller-manager 生成默认静态 Pod 清单你可以在/etc/kubernetes/manifests/kube-controller-manager.yaml这个文件里看到默认的--cluster-cidr配置。kubeadm 默认的 Pod 网段是 10.244.0.0/16但不同 CNI 建议的网段可能不同Calico 建议 192.168.0.0/16 或 10.0.0.0/16Cilium 则推荐 10.0.0.0/8 之外的网段以避免冲突。这里我强烈建议先确定 CNI 方案再初始化集群否则初始化完之后发现网段不对改起来就是整个集群推倒重建别提多痛苦了。4.2 Flannel 部署实操记录初始化集群时指定 Pod 网段为10.244.0.0/16然后执行kubeadm init --pod-network-cidr10.244.0.0/16完成之后部署 Flannelkubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.ymlFlannel 的 DaemonSet 会在每个节点上启动一个 flanneld 容器和一个名为 kube-flannel 的 Pod。检查是否部署成功的核心命令是kubectl -n kube-flannel get pods -o wide然后验证集群内部 Pod 之间的通信。我习惯的验证方式是用 iperf3 压测两个跨节点的 Pod先记录两个 Pod 的 IP在一端启动服务端另一端跑客户端。# Pod A iperf3 -s # Pod B iperf3 -c PodA_IP如果输出显示带宽稳定且在预期范围内说明 Flannel 的 VXLAN 通道是通的。这里有个很常见的坑如果压测结果非常差只有几百 Kbps大概率是 MTU 问题。VXLAN 隧道会额外占用 50 字节的包头开销所以物理网卡的 MTU 如果是 1500VXLAN 的 MTU 一般要设置成 1450。Flannel 默认会检测物理网卡 MTU 并自动扣减但如果你物理网卡启用了巨帧MTU 9000或者多层隧道叠加比如 Kubernetes 跑在虚拟机里虚拟机再套一层 VXLAN就很容易出现 MTU 不匹配导致的分片问题表现为大包不通、小包能通。可以使用如下命令测试kubectl exec -it podA -- ping -M do -s 1472 podB_IP如果丢包逐步降低-s的大小找到能通过的最大包大小然后用这个值反推 MTU。4.3 Calico 部署实操记录Calico 推荐使用 Tigera Operator 方式部署。先安装 operatorkubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml然后创建一个名为installation的自定义资源对象来触发 Calico 安装kubectl create -f - EOF apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: calicoNetwork: ipPools: - name: default-ipv4-ippool blockSize: 26 cidr: 10.244.0.0/16 encapsulation: VXLANCrossSubnet natOutgoing: true nodeAddressAutodetectionV4: interface: eth0 EOF这里说明一下几个关键参数。blockSize是每个节点能拿到的子网掩码大小26 表示每个节点分配/26网段64 个 IP如果单节点 Pod 密度高可以改成 24。encapsulation有三个选项IPIP表示启用 IPIP 隧道VXLANCrossSubnet表示只有跨子网时才用 VXLAN 封装同子网走 BGP 直连这个模式在国内多数机房环境中是体验和性能的平衡点。natOutgoing表示出站流量做 NAT也就是 Pod 访问外部网络时源 IP 会替换成节点 IP一般建议打开否则 Pod 的流量出去时可能被网络设备丢弃。安装完成后查看运行状态kubectl get pods -n calico-systemCalico 的验证我习惯先确认 BGP 邻居状态。如果每个节点的 bird 进程显示 Established说明 BGP 路由已经交换成功。然后跑到一个测试 Pod 里 ping 另一个节点的 Pod能通就说明路由是通的。kubectl exec -it podA -- ping podB_IPCalico 有个容易踩的坑是IP_AUTODETECTION_METHOD没设置对。节点上有多个网卡时Calico 默认选择第一个网卡的 IP 作为 BGP 监听地址。如果你的默认路由网卡和实际业务网卡不是同一个就会导致 Pod 流量能到宿主机但出不去或者 BGP 邻居建不起来但实际上网络是通的这类诡异问题。解决办法是明确指定网卡kubectl set env daemonset/calico-node -n calico-system IP_AUTODETECTION_METHODinterfaceeth04.4 Cilium 部署实操记录Cilium 推荐用 Helm 安装也可以直接用 cilium CLI。先安装 CLI 工具然后执行cilium install --version 1.15.0 \ --set kubeProxyReplacementtrue \ --set ipam.modekuberneteskubeProxyReplacementtrue表示让 Cilium 完全接管 Service 负载均衡不再运行 kube-proxy。这个功能需要在节点上配置kubelet --network-plugincni之外还要保证内核支持 eBPF 的bpf_host模式。如果条件不满足Cilium 会自动降级到兼容模式但这时一些高级特性不会生效建议安装时留意安装日志。安装完成后Cilium 自带的连接测试功能是我用过的最省心的验证工具cilium connectivity test这个工具会创建一组测试 Pod自动跑 DNS 解析、跨节点通信、Service 负载均衡、网络策略等测试最后给出每个检查项的结果。跑完之后如果一切通过基本可以确认数据面是健康的。Cilium 现场排障时最有用的命令是cilium status cilium endpoint list cilium monitor -vcilium monitor可以实时打印数据面收到的每个数据包的信息包括源 IP、目的 IP、源端口、目的端口、决策结果允许/拒绝/转发。遇到 Pod 访问不通的问题时这个命令能很快定位是策略拒绝还是路由丢失。比如你看到包被 DROP 且 Reason 是 Policy denied那问题就聚焦到 NetworkPolicy 上直接去查 CiliumNetworkPolicy 的规则即可。5. 常见问题与排查技巧实录5.1 高频问题速查表我根据这些年踩过的坑和平时答疑遇到过的问题整理了一份高频问题速查表按故障表现分类方便大家直接索引故障表现常见原因定位命令解决方案Pod 一直 ContainerCreatingCNI 插件未安装 / 节点未分配到子网 / CNI 配置文件损坏kubectl describe pod; journalctl -u kubelet检查 CNI DaemonSet 是否 Running确认--allocate-node-cidrs; 重新执行 CNI 安装跨节点 Pod 互 ping 不通BGP 会话未建立 / VXLAN 隧道 MTU 不匹配 / 宿主机 iptables 误拦截calicoctl node status; ping -M do -s 1472调整 MTU检查 BGP 邻居状态检查 FORWARD 链Pod 能访问集群内 Service但访问不了外网natOutgoing 未配置 / 宿主机 IP 转发未开启 / 云安全组拦截sysctl net.ipv4.ip_forward; iptables -t nat -L开启net.ipv4.ip_forward1; 调整 CNI nat 开关检查云安全组Service 访问不通但 Pod IP 通kube-proxy 的 iptables/IPVS 规则损坏 / Cilium kubeProxyReplacement 与 kube-proxy 冲突iptables -t nat -L -n; ipvsadm -L -n清理 kube-proxy 残留规则确认是否启用 kubeProxyReplacement集群节点数超过 50 后网络时延明显上升BGP 全网互联或 Flannel 映射表膨胀calicoctl get nodes; netstat -anp配置 Route Reflector 或切换 Cilium 方案5.2 三个最容易被忽略的坑第一个坑是iptables 规则与 Docker 的网络冲突。很多人部署完 Kubernetes 后发现所有 Pod 都启动不了kubelet 日志里报 CNI 失败。我排查过几次最后定位到是 Docker 自身创建的 DOCKER 链和 Kubernetes 的 KUBE 链冲突。解决办法是在 kubelet 启动参数里加上--network-plugincni同时确保 iptables 的 FORWARD 链默认策略是 ACCEPT。这个问题在新版本里出现得少了但如果你用老版本 Docker Kubernetes还是要注意。第二个坑是修改 CNI 后旧路由残留。有人从 Flannel 切换到 Calico直接把 Flannel 的 DaemonSet 删了然后套用 Calico 的 manifests 部署结果发现部分节点上 Pod 能通、部分节点上 Pod 时好时坏。这时候多半是节点上还残留着 Flannel 的 cni0 网桥、flannel.1 隧道设备和旧的 VXLAN 路由。切换 CNI 时务必先清掉所有旧 CNI 的网卡、路由和配置再部署新方案。# 在每台节点上 ip link delete cni0 ip link delete flannel.1 rm -rf /etc/cni/net.d/*清理完之后再让 kubelet 重新触发 CNI 调用才能干净地切换到新方案。第三个坑是多个 CNI 混用导致的 Pod 网络命名空间错乱。我见过有人为了“增强网络能力”同时部署了 Calico 和 Flannel然后创建 Pod 的时候 kubelet 会从/etc/cni/net.d/目录里拿第一个配置文件结果索引顺序不稳定导致部分 Pod 用了 Calico 网络、部分 Pod 用了 Flannel 网络集群里直接炸了。CNI 规范规定一个节点只能使用一个插件链共存是绝对不行的。如果你非要试多个方案建议用 kubeadm 重置集群再重新初始化kubeadm reset rm -rf /var/lib/cni/ rm -rf /etc/cni/net.d/5.3 排障时最有用的三板斧结合我的排障经验再分享三个最值得先试的定位方法它们能覆盖大多数网络问题。第一招从 Pod 视角出发逐步拆解。用kubectl exec进入 Pod执行ip addr和ip route确认 Pod 的 IP 和路由配置是否符合预期。然后从 Pod 里 ping 同节点 Pod、跨节点 Pod、Service VIP、外部 IP逐步缩小故障范围。这一步能很快速地区分问题是出在“Pod 的网卡配置”还是“节点的路由/隧道”上。第二招看 kubelet 日志。网络问题大概率会在 kubelet 日志里留下线索。尤其在 Pod 创建失败的时候kubelet 日志里的 CNI 调用输出信息非常详细会直接告诉你插件名称、配置文件、错误原因。这类日志的位置在 systemd 环境里是journalctl -u kubelet -f在非 systemd 环境里是/var/log/kubelet.log根据你的发行版选择合适的查看方式。第三招在宿主机上抓包。如果 Pod 内 ping 不通问题大概率在数据路径上。在源节点上tcpdump -i cni0看 Pod 流量是否到达网桥在tcpdump -i eth0看流量是否出宿主机在对端节点上再看流量是否进来。哪一段出现丢包问题就在哪一段。这个方法虽然朴素但往往比空想高效得多。6. 最后再分享一点选型的心得从 Flannel 到 Calico 再到 Cilium我每个方案都在生产环境里经历过完整的上线和排障周期。回头再看这些走过的路最深的体会是网络方案没有绝对的好坏只有是否匹配当前的规模、团队能力和业务需求。我不建议社区里出现“某某方案已经过时”这种论调每个方案都有它适合存在的场景关键是你要清楚自己的位置。如果你现在的集群很小、团队只有两三个人尽管用 Flannel 或者云厂商默认的 CNI把精力放在业务代码上远比纠结网络方案重要。等集群规模上来、对安全和可观测性有需求了再迁移到 Calico 或 Cilium。迁移其实是比较成熟的操作了Cilium 官方提供了从 Calico 迁移的文档实际做下来也不会太惊险。核心是先跑通业务然后在压力点出现时再升级方案这样每一步都走得稳。另外多说一句关于 Cilium 的小技巧。如果你已经决定要上 Cilium我强烈建议从部署第一天就把 Hubble 的 UI 组件打开。虽然它对集群资源有一点额外的占用但在排查东西向流量问题时能省下大量时间。我见过太多人跑着 Cilium 却从不用cilium monitor遇到问题还是一头扎进局域网里抓包那就浪费了这个方案本身的强大能力了。
