Kubernetes 网络三部曲:CNI、kube-proxy 与 CoreDNS 是如何协作的?

引言

"Service 配好了,为什么调用还是失败?""Pod 明明在 Running,却收不到任何流量!""DNS 解析不了服务名,但 kubectl get svc 显示一切正常!"

如果你在 Kubernetes 中反复遭遇这类"玄学"问题,很可能是因为你只记住了命令,却没看清 K8s 网络与服务发现的底层协作机制。

Kubernetes 的网络模型看似简单------每个 Pod 有独立 IP,Service 提供稳定入口------但在这层抽象之下,CNI、kube-proxy、CoreDNS 三大组件环环相扣,任何一个环节出错,都会导致"不通"。今天这篇文章,就带你彻底搞懂这三者分别负责什么,以及它们是如何配合完成一次完整的访问请求的。


一、CNI(Calico / Flannel)

核心职责:分配 IP 地址,保证基本连通。

Kubernetes 本身并不实现网络,而是依赖 CNI(Container Network Interface)插件来为 Pod 分配 IP 并打通跨节点通信。

你可以这样理解:CNI 就像是给你的电脑插上网线,分配一个固定的内网 IP(比如 172.17.0.3),并且保证你能 ping 通隔壁工位同事的电脑(不同 Node 上的 Pod)。

只要 CNI 正常工作,任意 Pod 都可以直接通过 IP 访问其他 Pod,无需 NAT 或端口映射。跨节点通信是 CNI 的核心能力之一:当 Pod 分布在不同节点时,数据需要跨越物理网络。Flannel 等插件通过 VXLAN 隧道封装数据包,使跨节点流量像在同一局域网内传输;而 Calico 则基于 BGP 路由协议,通过节点路由表直接转发,性能更高。

CNI 插件 工作模式 性能 网络策略 适用场景
Flannel VXLAN / Host-gw 中等 ❌ 不支持 快速上手、小规模集群
Calico BGP / IPIP / eBPF 高 ✅ 支持 生产环境、需安全隔离

CNI 的局限在于:Pod 是"短命"的 ------今天这个 Pod 的 IP 是 172.17.0.3,明天它挂了重启后可能就变成了 172.17.0.5。你不能让前端写死这个 IP,否则一变就挂。


二、kube-proxy

核心职责:提供虚拟 IP(ClusterIP)和负载均衡。

kube-proxy 是 Kubernetes 集群的关键组件,负责 Service 和其后端 Pod 之间的负载均衡转发。每个 Kubernetes 节点上都运行着一个 kube-proxy。

你可以这样理解:kube-proxy 就像公司前台的总机号码(ClusterIP)。你不用记住每个员工的手机号(Pod IP),只需要打总机号码,前台(kube-proxy)会自动帮你转接到当前空闲的对应员工(Pod)上。

具体来说,kube-proxy 做了两件事:

  1. 给 Service 分配一个永不过期的虚拟 IP(ClusterIP)。

  2. 当流量访问 ClusterIP 时,劫持该流量,并随机/轮询地转发给后端真正健康的 Pod IP。

kube-proxy 本身不做实际的包转发,而是根据从 API Server 监听到的 Service 与 EndpointSlice 的变化,维护节点上的包处理规则(iptables 或 IPVS 规则),最终由 Linux 内核来完成真实流量的转发。

两种主流模式:

  • iptables 模式(默认) :利用 Linux 内核的 iptables 规则链实现 DNAT(目标地址转换)。规则数量随 Service 数量线性增加,大规模集群下性能下降明显。

  • IPVS 模式(生产推荐) :基于 IP Virtual Server 内核模块,使用哈希表管理后端,负载均衡算法丰富(rr、lc、dh 等),性能 O(1),更适合高并发、大规模场景。

关键点 :kube-proxy 不负责连通性 (连通性是 CNI 干的),它只负责修改 Linux 内核的网络转发规则。


三、CoreDNS

核心职责:域名解析(服务名 → ClusterIP)。

CoreDNS 是 Kubernetes 集群中默认内置的 DNS 服务器,用于提供动态服务发现和域名解析的能力。

你可以这样理解:CoreDNS 就像公司的通讯录/电话黄页 。你只需要喊一句"转接财务部"(DNS 查询),它告诉你财务部总机号码是 10.96.1.2(ClusterIP),然后你再去找 kube-proxy。

CoreDNS 监听 API Server,每当创建 Service,它就将 服务名 → ClusterIP 的映射记录存入 DNS。这样一来,Pod 就可以通过服务名称 (如 mysql.db-namespace.svc.cluster.local)来查找目标,而不是写死 IP 地址。


四、一次完整的访问流程(串联三者)

现在,让我们用一个完整的例子,把三个组件串起来。

假设前端 Pod(A)要访问后端 Pod(B,如 MySQL),完整流程如下:

步骤 负责组件 动作描述
① 服务发现 CoreDNS 前端代码写死域名 mysql.db.svc.cluster.local,发起 DNS 查询。CoreDNS 返回 Service 的固定虚拟 IP(ClusterIP)
② 流量拦截 kube-proxy 数据包发往 ClusterIP 后,宿主机内核检查到该 IP 是 Service 网段,立即触发 iptables/IPVS 规则。kube-proxy 负责维护这些规则,挑选一个健康的 Pod IP
③ DNAT 转换 内核 Netfilter 内核将数据包的目标 IP 和端口 (ClusterIP:3306)改写 为后端 Pod 的真实 IP(172.17.0.8:3306)
④ 路由转发 CNI(Calico/Flannel) 内核根据目标 Pod IP 查询路由表。CNI 提供该路由表(BGP 路由或 VXLAN 隧道信息),决定数据包从哪张网卡发出
⑤ 响应返回 内核 SNAT 后端 Pod 处理后,响应包返回给前端。内核自动执行 SNAT,将源 IP(Pod IP)还原为 Service 的 ClusterIP,前端 Pod 感受不到后端真实 IP 的变化

用一句话概括:

前端代码写域名 → CoreDNS 返回 ClusterIP → kube-proxy 的 iptables/IPVS 规则将 ClusterIP 转为 Pod IP → CNI 负责把包送到目标 Pod。


五、如果少了某一个,会怎样?

  • 如果你只有 CNI,没有 kube-proxy:Pod 间能互相 ping 通,但一旦 Pod 重启换 IP,你的程序就挂了,而且无法做多副本的负载均衡。

  • 如果你没有 CoreDNS :你得手动在程序里填写 ClusterIP(比如 10.96.100.1)。虽然这个 IP 通常不变,但如果 Service 被删掉重建,IP 变了,程序还得改配置重启,极不方便。

  • 如果 CNI 出问题:连最基本的 Pod 间 IP 互通都做不到,上层的一切都无从谈起。


六、选型建议

在实际生产环境中,如何选择这些组件?

  • CNI 选型:

    • Flannel:配置简单,适合学习环境、小规模集群,但不支持 NetworkPolicy。

    • Calico:性能更优,支持细粒度网络策略,适合生产环境。

  • kube-proxy 模式:

    • iptables:兼容性好,适合中小规模集群。

    • IPVS:性能更高,适合大规模、高并发场景。

  • DNS 优化 :在大规模集群中,可以考虑启用 NodeLocal DNSCache,将 DNS 缓存代理以 DaemonSet 形式跑在每台节点上,缩短 DNS 查询路径,降低 CoreDNS 压力。


总结

用一个形象的比喻来收尾:

  • CNI(Calico/Flannel) 是 "路和车" ------解决"能不能到"(底层物理网络和路由)。

  • kube-proxy 是 "交警和调度员" ------解决"找哪个 IP 去"(虚拟 IP 转换和负载均衡)。

  • CoreDNS 是 "导航地图" ------解决"那个 IP 叫什么名字"(服务发现,方便代码不写死 IP)。

三者配合,Kubernetes 的网络才算真正可用。下次再遇到"网络不通"的问题,按这个思路逐层排查:先看 CNI(Pod IP 能不能通),再看 kube-proxy(Service 能不能通),最后看 CoreDNS(域名能不能解析)。

相关推荐
Cry丶12 小时前
ubuntu安装vsftpd
服务器·网络·ubuntu
SHENGWEI胜为15 小时前
交换机端口显示正常,终端却获取不到 IP 地址?从 DHCP 流程定位故障
服务器·网络·测试工具·缓存·通信工程
IMPYLH17 小时前
Linux 系统备份与镜像
linux·服务器·网络
淘气包海鸟18 小时前
水声网络框架
网络·ns3·水
国科安芯19 小时前
星间激光通信终端CANFD控制网络的时延确定性与辐射可靠性
网络·嵌入式硬件·信息与通信·canfd·低轨卫星·商业航天·抗辐射
中屹指纹浏览器svip19 小时前
网络抖动会标记账号异常?分清两种波动
网络
承渊政道20 小时前
Linux网络学习【传输层协议UDP】
linux·网络·网络协议·学习·ubuntu·udp
小此方20 小时前
Linux网络(三十三):告别O(n)噩梦:从select/poll的挣扎到epoll红黑树+回调的降维打击,一文打通IO多路复用
linux·网络·驱动开发
2301_7779983420 小时前
Linux 网络:数据链路层
linux·服务器·网络
国科安芯20 小时前
空间锂离子电池组管理系统CANFD通信网络的辐射可靠性设计
网络·信息与通信·canfd·电池·低轨卫星·抗辐射