主题
第7章 kube-proxy 实现原理
Service 的 ClusterIP 是一个虚拟 IP,本身没有进程监听。真正实现负载均衡的是运行在每个节点上的 kube-proxy。本章深入讲解 kube-proxy 的三种工作模式和数据包全链路。
7.1 kube-proxy 是什么
kube-proxy 是 Kubernetes 的网络代理组件,运行在每个节点上,负责:
- 监听 Service 和 EndpointSlice 的变化。
- 在本地节点上配置转发规则(iptables 或 ipvs)。
- 数据包到达节点时,由内核根据规则直接转发,不经过 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 -> Pod7.2.3 ipvs 模式(推荐大规模使用)
- kube-proxy 调用 Linux IPVS(IP Virtual Server)模块创建虚拟服务器。
- 每个 Service 对应一个 IPVS virtual server,每个后端 Pod 对应一个 real server。
- 支持多种调度算法:
rr(轮询)、lc(最少连接)、dh、sh、sed、nq。
优点:
- 转发性能接近直接路由,规则更新快。
- 支持的负载均衡算法丰富。
- 后端数量大时优势明显。
启用方式:
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 0IPVS 转发模式
| 模式 | 缩写 | 说明 |
|---|---|---|
| NAT | Masq | 修改源/目的 IP,Pod 看到的源 IP 是节点 IP |
| DR | Route | 直接路由,Pod 直接回复客户端,性能最好 |
| Tunnel | Tunnel | IPIP 隧道 |
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:80807.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 -L | ipvsadm |
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.457.10 本章小结
- kube-proxy 是实现 Service 负载均衡的引擎,运行在每个节点上。
- iptables 模式是默认,通过 DNAT 和随机概率实现负载均衡。
- ipvs 模式更适合大规模集群,支持多种调度算法。
- ClusterIP 不是真实 IP,只是规则中的匹配条件。
- 返回包依赖 conntrack,长连接在端点变化时可能异常。
本章练习
- 查看你集群中 kube-proxy 的工作模式(iptables 还是 ipvs)。
- 在节点上查看 KUBE-SERVICES 链,找到自己创建的 Service 对应的规则。
- 做一个滚动更新实验,观察长连接是否会出现异常。