Skip to content

第7章 kube-proxy 实现原理

Service 的 ClusterIP 是一个虚拟 IP,本身没有进程监听。真正实现负载均衡的是运行在每个节点上的 kube-proxy。本章深入讲解 kube-proxy 的三种工作模式和数据包全链路。


7.1 kube-proxy 是什么

kube-proxy 是 Kubernetes 的网络代理组件,运行在每个节点上,负责:

  1. 监听 Service 和 EndpointSlice 的变化。
  2. 在本地节点上配置转发规则(iptables 或 ipvs)。
  3. 数据包到达节点时,由内核根据规则直接转发,不经过 kube-proxy 进程
text
Service/EndpointSlice


   kube-proxy (Watch)


   iptables / ipvs 规则


   内核直接转发数据包

7.2 三种工作模式

7.2.1 userspace 模式(已废弃)

  • kube-proxy 作为用户态代理进程监听端口。
  • 流量先进入 kube-proxy,再由它转发给后端 Pod。
  • 性能差、用户态/内核态切换开销大,现代集群已不再使用。

7.2.2 iptables 模式(默认)

  • kube-proxy 监听 Service/EndpointSlice 变化,动态生成 iptables 规则。
  • 数据包在内核态直接被 DNAT 到后端 Pod,无需用户态进程参与。
  • 负载均衡采用随机算法(probability 规则链)。

优点:性能较好,无额外进程。
缺点

  • 后端 Pod 数量多时规则链庞大,更新慢。
  • 负载均衡算法单一。
  • 无法处理长连接的优雅重试(老连接可能仍指向失效 Pod)。
text
数据包流向:
Client -> PREROUTING -> KUBE-SERVICES -> KUBE-SVC-XXX -> KUBE-SEP-XXX -> DNAT -> Pod

7.2.3 ipvs 模式(推荐大规模使用)

  • kube-proxy 调用 Linux IPVS(IP Virtual Server)模块创建虚拟服务器。
  • 每个 Service 对应一个 IPVS virtual server,每个后端 Pod 对应一个 real server。
  • 支持多种调度算法:rr(轮询)、lc(最少连接)、dhshsednq

优点

  • 转发性能接近直接路由,规则更新快。
  • 支持的负载均衡算法丰富。
  • 后端数量大时优势明显。

启用方式

bash
kube-proxy --proxy-mode=ipvs --ipvs-scheduler=rr

需要节点加载 ip_vs 等相关内核模块。


7.3 iptables 模式规则链结构

kube-proxy 会创建如下链:

text
KUBE-SERVICES      # 匹配所有 Service(ClusterIP + port)

  ├── KUBE-SVC-XXXXXXXXXXXXXXXX   # 某个 Service 的链
  │     │
  │     ├── KUBE-SEP-XXXXXXXXXXXXXXXX   # 后端 Pod 1
  │     │     └── DNAT to Pod-1:targetPort
  │     │
  │     └── KUBE-SEP-YYYYYYYYYYYYYYYY   # 后端 Pod 2
  │           └── DNAT to Pod-2:targetPort

  └── KUBE-NODEPORTS    # 匹配 NodePort

        └── KUBE-SVC-XXXXXXXXXXXXXXXX   # 跳转到对应 Service 链

模拟规则示例

text
Chain KUBE-SERVICES
 target          prot opt source      destination
KUBE-SVC-ABC123  tcp  --  0.0.0.0/0   10.96.123.45    tcp dpt:80
KUBE-NODEPORTS   all  --  0.0.0.0/0   0.0.0.0/0

Chain KUBE-SVC-ABC123
 target          prot opt source      destination
KUBE-SEP-POD111  all  --  0.0.0.0/0   0.0.0.0/0    statistic mode random probability 0.5000000000
KUBE-SEP-POD222  all  --  0.0.0.0/0   0.0.0.0/0

Chain KUBE-SEP-POD111
 target  prot opt source      destination
DNAT    tcp  --  0.0.0.0/0   0.0.0.0/0    tcp to:10.244.1.10:8080

Chain KUBE-NODEPORTS
 target          prot opt source      destination
KUBE-SVC-ABC123  tcp  --  0.0.0.0/0   0.0.0.0/0    tcp dpt:30080

负载均衡算法:随机

iptables 模式下,kube-proxy 通过 statistic mode random probability 实现概率随机

  • 2 个后端:第一个规则概率 0.5,第二个规则 1.0(兜底)。
  • 3 个后端:概率依次是 0.333、0.5、1.0。

这意味着 iptables 模式是随机负载均衡,不是轮询。


7.4 ipvs 模式数据结构

text
Virtual Server (VS)     = Service 的 ClusterIP:port
  ├── Real Server 1     = Pod-1:targetPort
  ├── Real Server 2     = Pod-2:targetPort
  └── ...

查看命令

bash
ipvsadm -Ln

输出示例

text
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.96.123.45:80 rr
  -> 10.244.1.10:8080             Masq    1      0          0
  -> 10.244.2.10:8080             Masq    1      0          0
TCP  192.168.1.10:30080 rr
  -> 10.244.1.10:8080             Masq    1      0          0
  -> 10.244.2.10:8080             Masq    1      0          0

IPVS 转发模式

模式缩写说明
NATMasq修改源/目的 IP,Pod 看到的源 IP 是节点 IP
DRRoute直接路由,Pod 直接回复客户端,性能最好
TunnelTunnelIPIP 隧道

Kubernetes 中 ipvs 默认使用 NAT/Masq 模式。


7.5 数据包完整流程(ClusterIP)

text
┌─────────────┐
│  Client Pod │
│ 10.244.1.5  │
└──────┬──────┘

       │ 目的地址:10.96.123.45:80

┌─────────────────────────┐
│ 本节点 kube-proxy 规则   │
│  (iptables / ipvs)      │
└──────┬──────────────────┘

       │ DNAT / 负载均衡
       │ 10.96.123.45:80 -> 10.244.1.10:8080 或 10.244.2.10:8080

┌─────────────────────────┐
│    CNI 网络(vxlan/    │
│    host-gw/calico 等)   │
└──────┬──────────────────┘

┌─────────────┐
│  Backend    │
│  Pod        │
│ 10.244.x.x:8080
└─────────────┘

核心认知:ClusterIP 不是一个真实网卡上的 IP,它只是 iptables/ipvs 规则中的一个匹配条件。


7.6 NodePort 数据包流程

外部流量进入节点网卡的 30080:

text
1. 数据包目的地址:<Node-1-IP>:30080
2. PREROUTING -> KUBE-SERVICES -> KUBE-NODEPORTS
3. 命中 KUBE-NODEPORTS 中 tcp dpt:30080 的规则
4. 跳转到 KUBE-SVC-ABC123
5. 后续流程与 ClusterIP 相同:DNAT 到 Pod:8080

7.7 连接跟踪与返回包

无论是 iptables 还是 ipvs,都需要 conntrack(连接跟踪) 来处理返回包:

text
请求包:
  源:Client-IP:random-port
  目的:10.96.123.45:80

经过 DNAT 后:
  源:Client-IP:random-port
  目的:10.244.1.10:8080

Pod 回复:
  源:10.244.1.10:8080
  目的:Client-IP:random-port

返回包经过节点时,conntrack 做反向 DNAT:
  源:10.96.123.45:80
  目的:Client-IP:random-port

这样客户端一直认为自己在和 ClusterIP 通信。

长连接与端点变化

如果一个 Pod 在连接建立后被删除:

  • iptables/ipvs 会更新规则,移除这个后端。
  • 已经建立的连接仍然存在于 conntrack 表中,会继续发给旧 Pod。
  • 新连接才会被负载均衡到剩余后端。

这就是滚动更新时偶发 502/连接重置的原因之一。


7.8 iptables vs ipvs 对比

特性iptables 模式ipvs 模式
负载均衡层iptables 规则链IPVS virtual server
调度算法随机(probability)rr / lc / dh / sh / sed / nq
后端数量大时规则链膨胀,更新慢结构稳定,更新快
性能较好更好
长连接重试较差较好
内核要求需要 ip_vs 模块
调试工具iptables -Lipvsadm

7.9 关键命令

bash
# 查看 iptables 中 Service 相关链
iptables -t nat -L KUBE-SERVICES -n -v

# 查看某个 Service 的链
iptables -t nat -L KUBE-SVC-XXX -n -v

# 查看 NodePort 链
iptables -t nat -L KUBE-NODEPORTS -n -v

# 查看 ipvs 虚拟服务
ipvsadm -Ln

# 查看连接状态
ipvsadm -Lnc

# 查看 conntrack
conntrack -L | grep 10.96.123.45

7.10 本章小结

  • kube-proxy 是实现 Service 负载均衡的引擎,运行在每个节点上。
  • iptables 模式是默认,通过 DNAT 和随机概率实现负载均衡。
  • ipvs 模式更适合大规模集群,支持多种调度算法。
  • ClusterIP 不是真实 IP,只是规则中的匹配条件。
  • 返回包依赖 conntrack,长连接在端点变化时可能异常。

本章练习

  1. 查看你集群中 kube-proxy 的工作模式(iptables 还是 ipvs)。
  2. 在节点上查看 KUBE-SERVICES 链,找到自己创建的 Service 对应的规则。
  3. 做一个滚动更新实验,观察长连接是否会出现异常。