在K8S中,kube-proxy iptables原理是什么?
好的,我们来深入解析 Kubernetes 中 kube-proxy
的 iptables 模式 的工作原理。这是 kube-proxy
最经典和稳定的模式,虽然在新版本中 IPVS 因其性能成为默认,但理解 iptables 模式对掌握 Kubernetes 网络至关重要。
核心思想
kube-proxy
iptables 模式的核心思想是:使用 Linux 内核的 iptables
规则,来实现对 Service 的虚拟 IP(VIP)的访问请求的自动负载均衡和地址转换(NAT),将其转发到后端真实的 Pod IP 上。
kube-proxy
的角色是一个控制器,它监听 API Server 中 Service 和 Endpoint 的变化,然后动态地、智能地生成和维护本机上的 iptables
规则集。数据包的实际转发工作完全由内核中的 netfilter/iptables
来完成,kube-proxy
本身不转发任何数据包。
下图展示了这一核心流程,包括控制平面与数据平面的分工:
工作原理详细步骤
第 1 步:监听与规则生成 (控制平面)
- 监听 API Server:
kube-proxy
启动后,会通过 List-Watch 机制监听 Kubernetes API Server,获取所有 Service 和 Endpoint(或 EndpointSlice)的变更事件。 - 计算规则:当有 Service 或它的后端 Pod(Endpoints)发生变化时(如创建、删除、扩缩容),
kube-proxy
会根据最新的状态,在内存中计算出一套所需的iptables
规则。 - 应用规则:
kube-proxy
调用iptables-restore
等命令,将计算好的规则批量、原子性地应用到本机内核中,确保规则与集群状态一致。
第 2 步:数据包流转 (数据平面)
当一个数据包目标是 Service 的 ClusterIP:Port
时,它在节点上的旅程如下(以 ClusterIP
为例):
-
入口:
PREROUTING
链- 所有进入本机的数据包(包括来自本机进程和外部的)都会先经过
nat
表的PREROUTING
链。 - 这里有一条关键规则:“所有数据包都跳转到自定义链
KUBE-SERVICES
”。
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
- 所有进入本机的数据包(包括来自本机进程和外部的)都会先经过
-
服务匹配:
KUBE-SERVICES
链- 这个链是
kube-proxy
维护的所有 Service 规则的入口。 - 链中包含了许多规则,每条规则匹配一个 Service 的 IP 和端口。例如:
-A KUBE-SERVICES -d 10.96.0.1/32 -p tcp --dport 443 -j KUBE-SVC-XXXXX (API Server Service)
-A KUBE-SERVICES -d 10.96.0.10/32 -p udp --dport 53 -j KUBE-SVC-YYYYY (CoreDNS Service)
- 如果数据包的目标地址是
10.96.0.10:53
(UDP),它就会匹配上第二条规则,并跳转到链KUBE-SVC-YYYYY
。
- 这个链是
-
负载均衡:
KUBE-SVC-XXXX
链- 每个 Service 都有自己对应的
KUBE-SVC-XXX
链,该链负责实现负载均衡。 - 这个链中的规则会按概率随机地将流量分发到更后端的链(代表一个具体的 Pod)。规则的数量等于后端 Pod 的数量,每条规则的概率权重相同(实现简单的随机负载均衡)。
-A KUBE-SVC-YYYYY -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-AAAAA -A KUBE-SVC-YYYYY -j KUBE-SEP-BBBBB
- 上面的例子表示:有 50% 的概率跳转到
KUBE-SEP-AAAAA
,剩下的 50% 概率跳转到KUBE-SEP-BBBBB
(如果有两个 Pod)。
- 每个 Service 都有自己对应的
-
目标地址转换 (DNAT):
KUBE-SEP-XXXX
链- 每个 Pod Endpoint 都有自己对应的
KUBE-SEP-XXX
链(SEP 代表 Service EndPoint)。 - 这个链的核心作用是执行 DNAT(Destination Network Address Translation)。
-A KUBE-SEP-AAAAA -p udp -j DNAT --to-destination 172.17.0.3:53
- 这条规则的意思是:将数据包的目标 IP 和端口从 Service 的
10.96.0.10:53
修改为 Pod 的172.17.0.3:53
。
- 每个 Pod Endpoint 都有自己对应的
-
路由与出口
- 完成 DNAT 后,数据包会继续经过
FORWARD
链(如果目标是其他节点的 Pod)或POSTROUTING
链(如果目标是本机 Pod)。 - 在
POSTROUTING
链中,会再次经过一个KUBE-POSTROUTING
链,这里主要负责MASQUERADE(源地址伪装)。这是为了确保响应包在返回客户端时,源地址是 Service IP 而不是 Pod IP,否则客户端会因为收到来自未知 Pod IP 的响应而丢弃它。
- 完成 DNAT 后,数据包会继续经过
关键特点与优劣分析
特性 | 说明 |
---|---|
工作原理 | 依靠内核 iptables 规则链进行匹配和 NAT。 |
负载均衡算法 | 随机均衡:基于 statistic 模块的随机概率,不是轮询。它不支持更高级的算法(如最小连接数)。 |
性能 | 规则遍历是 O(n)。当 Service 和 Pod 数量极大时,iptables 规则列表会非常庞大,线性查找匹配规则会带来延迟和性能下降。规则同步也会变慢。 |
可靠性 | 极其成熟和稳定。作为 Linux 内核的标准功能,经受了长期考验。 |
调试 | 规则非常复杂,对人类不友好。使用 `iptables-save |
连接状态 | 依赖 conntrack 模块跟踪连接。在高并发短连接场景(如 HTTP 1.1 Keep-Alive)下,容易导致 conntrack 表满,引发丢包。 |
与 IPVS 模式的简单对比
方面 | iptables 模式 | IPVS 模式 |
---|---|---|
实现机制 | 长长的顺序规则链 | 内核哈希表 |
算法复杂度 | O(n) | O(1) |
负载均衡算法 | 随机 | 丰富(rr, lc, dh, sh等) |
大规模集群 | 性能下降明显 | 性能优异,扩展性好 |
操作复杂度 | 规则复杂难懂 | 规则简洁清晰 (ipvsadm ) |
总结
总而言之,kube-proxy
的 iptables 模式是一个精巧的“控制器”。它通过监听集群状态,将复杂的服务发现和负载均衡逻辑,翻译成一套标准、高效的 iptables
规则集。而真正繁重的数据包处理工作,则交给了 Linux 内核的 netfilter
框架来完成。
这种设计非常符合 Kubernetes 的通用模式:声明式 API + 控制器。虽然在大规模场景下有其性能瓶颈,但对于大多数中小型集群而言,它仍然是一个简单、可靠且无需额外依赖的优秀解决方案。