4. Kubernetes 网络模型

聊到 Kubernetes,网络这块是绕不过去的坎。很多人刚开始接触 K8s 时,会被它那套「每个 Pod 都有独立 IP」的模型搞懵。我当年第一次部署集群,Pod 之间 ping 不通,折腾了一整天才发现是 CNI 插件没配好。嗯,今天我们就来把这套网络模型彻底讲透。

一、K8s 网络模型的核心原则

Kubernetes 对网络有几个硬性要求,说白了就是三条铁律:

  • 所有 Pod 可以不经过 NAT 直接通信——不管它们在哪个节点上
  • 所有节点可以直接访问所有 Pod——节点和 Pod 是对等的
  • Pod 看到的自身 IP 就是其他 Pod 访问它的 IP——没有地址转换

这个模型的好处很明显:你不需要操心端口映射,也不用管 NAT 规则。Pod 就像一台独立的物理机,IP 就是它的身份证。

关键理解:K8s 网络模型是「扁平 IP 空间」。每个 Pod 拿到一个真实可路由的 IP,而不是 Docker 默认的 NAT 桥接模式。这意味着从集群内任何位置,都能直接用 Pod IP 访问它。

二、CNI 插件:谁在背后干活?

K8s 本身不实现网络,它只定义接口。这个接口就是 CNI(Container Network Interface)。CNI 插件负责给 Pod 分配 IP、配置网络接口、维护路由规则。

市面上主流的 CNI 插件有几种,我挑几个常用的说说:

插件 网络模式 特点 适用场景
Flannel Overlay(VXLAN) 简单易用,性能一般 小规模集群、学习环境
Calico 纯三层(BGP) 高性能,支持网络策略 生产环境、大规模集群
Cilium eBPF 驱动 极高性能,可观测性强 云原生、安全敏感场景
Weave Overlay(fastdp) 加密通信,跨云部署 多集群、混合云

我的建议:如果你刚开始学,用 Flannel 上手最快。但生产环境我推荐 Calico,它用 BGP 直接路由,没有 Overlay 的封装开销。我在一个 200 节点的集群上用过 Calico,延迟表现非常稳定。

三、Service 发现:Pod 挂了怎么办?

Pod 是脆弱的,随时可能被调度到别的节点,IP 也会变。那客户端怎么找到它?K8s 的答案是 Service。

Service 是一个抽象层,它有一个固定的虚拟 IP(ClusterIP)。你访问这个 IP,K8s 会把流量转发到后端的某个 Pod 上。Pod 挂了?没关系,Service 会自动剔除它。

Service 的发现方式有两种:

  • 环境变量:Pod 启动时,K8s 会把 Service 的 IP 和端口注入到环境变量里。比如 MY_SERVICE_SERVICE_HOST 和 MY_SERVICE_SERVICE_PORT。
  • DNS:K8s 集群内部有一个 CoreDNS,它会为每个 Service 创建一条 A 记录。你直接用 Service 名字就能访问,比如 my-service.namespace.svc.cluster.local。

我个人更推荐 DNS 方式。环境变量有个坑:如果 Pod 在 Service 创建之前启动,它就拿不到环境变量。DNS 就没这个问题,随时都能解析。

四、负载均衡:iptables vs IPVS

Service 的流量转发,底层靠的是 kube-proxy。kube-proxy 有三种模式,最常用的是 iptables 和 IPVS。

4.1 iptables 模式

这是默认模式。kube-proxy 会为每个 Service 创建一堆 iptables 规则。当请求到达 Service IP 时,iptables 通过 DNAT 规则把目标地址改成某个 Pod 的 IP。

举个例子,你创建一个 Service,后端有 3 个 Pod。kube-proxy 会生成类似这样的规则:

-A PREROUTING -m comment --comment "default/my-service" -j KUBE-SERVICES
-A KUBE-SVC-XXXXX -m statistic --mode random --probability 0.33 -j KUBE-SEP-AAAAA
-A KUBE-SVC-XXXXX -m statistic --mode random --probability 0.50 -j KUBE-SEP-BBBBB
-A KUBE-SVC-XXXXX -j KUBE-SEP-CCCCC

每条规则对应一个 Pod,概率值决定了流量分配。iptables 是线性匹配的,规则越多,性能越差。我在一个集群里见过上万条 iptables 规则,那延迟……嗯,不提了。

避坑指南:我曾经在一个大集群里用 iptables 模式,Service 数量超过 5000 个时,节点上的 iptables 规则达到了 10 万条。每次更新规则都要好几秒,Pod 调度都受影响。后来切到 IPVS 才解决。

4.2 IPVS 模式

IPVS 是 Linux 内核自带的 L4 负载均衡器。它用哈希表来存储转发规则,查找时间复杂度是 O(1),不管有多少条规则,性能都很稳定。

启用 IPVS 模式很简单,在 kube-proxy 配置里设置:

mode: "ipvs"

IPVS 支持多种调度算法:

  • rr:轮询,默认算法
  • lc:最少连接
  • dh:目标地址哈希
  • sh:源地址哈希
  • sed:最短预期延迟
  • nq:永不排队

你想想看,如果你的服务对延迟敏感,用 lc 或 sed 会更合理。我一般用 rr,简单够用。

五、一张图看懂 K8s 网络模型

下面这张图展示了从客户端到 Pod 的完整流量路径:

Kubernetes 网络模型:从客户端到 Pod 客户端 Service kube-proxy iptables/IPVS Pod 1 Pod 2 Pod 3 ClusterIP:80 DNAT 到 Pod IP 说明: 1. 客户端访问 Service 的 ClusterIP(虚拟 IP)。 2. kube-proxy 在节点上维护 iptables 或 IPVS 规则。 3. 请求到达节点后,规则将目标地址 DNAT 为某个 Pod 的真实 IP。

六、如何选择?

说了这么多,到底用哪个?我总结一下:

  • 小集群(< 50 个 Service):iptables 完全够用,配置简单,不用额外操心。
  • 中大规模集群(> 100 个 Service):建议切到 IPVS。性能稳定,规则更新快。
  • 对延迟极度敏感:IPVS + Cilium(eBPF)是绝配,延迟几乎为零。

一个小技巧:如果你不确定当前集群用的是哪种模式,可以查看 kube-proxy 的 Pod 日志:kubectl logs -n kube-system kube-proxy-xxxxx | grep "Using"。它会告诉你当前是 iptables 还是 IPVS。

好了,K8s 网络模型的核心内容就这些。CNI 插件负责 Pod 的网络连通,Service 解决了 Pod IP 动态变化的问题,而 iptables 和 IPVS 是流量转发的底层实现。理解这三层,你就能搞定大部分 K8s 网络问题了。