2. Kubernetes网络模型精讲
Kubernetes 的网络模型不是一张“网络拓扑图”,而是一组对 CNI 插件提出的契约。理解这些契约,才能判断某个 CNI 实现是否满足集群需求,也才能在排障时快速定位问题出在 Pod 网络、Service 转发还是策略执行层。本节围绕四类核心对象——Pod、Service、Ingress、NetworkPolicy——逐一拆解它们对网络提出的要求,以及这些要求在实现层面的约束。
一、Pod:最小网络单元的三条硬性要求
Pod 是 Kubernetes 调度的最小单位,也是网络模型的基本单元。它对网络提出的要求可以归纳为三条:
- 每个 Pod 拥有独立 IP:Pod 内的所有容器共享同一个网络命名空间,因此共享同一个 IP 和端口空间。容器之间通过
localhost通信,不存在端口冲突问题。 - Pod 之间可直接通信:任意两个 Pod,无论是否在同一节点,都应能在不经过 NAT 的情况下直接通过 Pod IP 互访。这是“扁平网络”的核心含义。
- 节点与 Pod 可互访:节点上的进程(如 kubelet、kube-proxy)能够直接访问 Pod IP,反之亦然。
这三条要求看似简单,却直接决定了 CNI 插件的实现方式。例如,Overlay 方案(如 VXLAN)通过隧道封装满足“跨节点直连”的语义,但会带来 MTU 开销;Underlay 方案(如 Calico BGP 模式)通过路由通告实现原生互通,性能更好但对底层网络有要求。无论哪种方案,都必须保证 Pod IP 在集群内全局唯一且可路由。
ping 对方 Pod IP,并抓包确认没有发生源地址 NAT。二、Service:虚拟 IP 与负载均衡的抽象
Pod IP 是易变的——Pod 重建后 IP 会变化。Service 的作用就是为一组 Pod 提供一个稳定的虚拟 IP(ClusterIP)和 DNS 名称。它对网络的要求体现在三个层面:
第一,ClusterIP 必须可被 Pod 访问。ClusterIP 是一个虚拟地址,不存在于任何网卡上。它的实现依赖节点上的转发规则:kube-proxy 在 iptables 模式下生成 DNAT 规则,将发往 ClusterIP 的包改写为某个后端 Pod IP;在 IPVS 模式下则使用内核 IPVS 虚拟服务器。无论哪种模式,都要求节点内核支持相应的转发机制。
第二,Service 需要知道哪些 Pod 是后端。这通过 EndpointSlice(或 Endpoints)对象实现。kube-controller-manager 根据 Service 的 selector 匹配 Pod,并将就绪(Ready)的 Pod IP 写入 EndpointSlice。只有通过 readinessProbe 的 Pod 才会被加入后端列表,这是流量不落入未就绪 Pod 的关键保障。
第三,Service 有多种类型,约束各不相同。ClusterIP 仅在集群内可达;NodePort 在每个节点上开放一个端口,要求节点端口范围(默认 30000-32767)未被占用;LoadBalancer 依赖云厂商或 MetalLB 等实现,要求底层具备外部 IP 分配能力。
# 查看 Service 的后端端点
kubectl get endpointslice -l kubernetes.io/service-name=my-svc
# 查看 kube-proxy 生成的 iptables 规则(iptables 模式)
iptables -t nat -L KUBE-SERVICES -n | grep my-svc
三、Ingress:七层入口的转发约束
Service 工作在四层(TCP/UDP),而 Ingress 工作在七层(HTTP/HTTPS),提供基于域名和路径的路由。Ingress 本身只是一个规则声明,真正生效需要 Ingress Controller(如 NGINX Ingress、Traefik)来监听并生成反向代理配置。
Ingress 对网络的要求包括:Controller 自身必须以 Pod 形式运行并能被外部访问(通常通过 NodePort 或 LoadBalancer 类型的 Service 暴露);Controller 需要能访问后端 Service 的 ClusterIP 或直接访问 Pod IP;TLS 终止需要证书以 Secret 形式挂载。此外,Ingress 规则中的 host 和 path 匹配依赖 Controller 的实现,不同 Controller 对注解(annotation)的支持差异较大,这是实际使用中最容易踩坑的地方。
四、NetworkPolicy:从“能通”到“该不该通”
前面三类对象解决的是“能不能通”的问题,NetworkPolicy 解决的是“该不该通”的问题。它是一组 Pod 级别的防火墙规则,通过 label selector 选中目标 Pod,然后定义允许的入站(Ingress)和出站(Egress)流量。
关键约束有三点:其一,NetworkPolicy 是白名单模型——一旦某个 Pod 被某条策略选中,未被明确允许的流量默认被拒绝。其二,策略是命名空间隔离的——默认只能选中同命名空间的 Pod,跨命名空间需要显式使用 namespaceSelector。其三,策略能否生效取决于 CNI 是否支持——Calico、Cilium、Weave 等支持,而 Flannel 默认不支持。如果集群使用 Flannel 且未叠加策略引擎,创建 NetworkPolicy 对象不会报错,但也不会有任何效果,这是排障中极易被忽略的陷阱。
五、四类对象的约束关系与排障思路
把四类对象放在一起看,它们构成了一条从“身份”到“入口”再到“管控”的链路:Pod 提供可路由的身份,Service 提供稳定的访问入口,Ingress 提供七层路由能力,NetworkPolicy 提供访问管控。每一层都依赖 CNI 或控制器满足特定契约。
实际排障时,可以按这条链路逐层验证:先确认 Pod IP 是否可跨节点直连(排除 CNI 基础问题),再确认 Service 的 EndpointSlice 是否有就绪后端(排除 readinessProbe 或 selector 问题),然后确认 Ingress Controller 是否生成了正确的上游配置(排除注解或路径匹配问题),最后确认 NetworkPolicy 是否意外拦截了流量(排除策略选择器或 CNI 不支持问题)。这条链路的价值在于:它把“网络不通”这个模糊描述,拆解成了四个可独立验证的环节。
curl 测试被策略禁止的流量,观察是否真的被拒绝。理解这些约束的最终目的,是在选型和排障时有据可依。选 CNI 时,先问“是否需要 NetworkPolicy”“是否需要跨节点直连的低延迟”“底层网络是否支持 BGP”,再决定用 Overlay 还是 Underlay、用 Calico 还是 Cilium。排障时,先定位问题出在哪一层契约,再深入该层的实现细节,而不是盲目重启组件。