Skip to content

iptables 模式详解

iptables 模式是 Kubernetes 从 v1.2 版本开始采用的默认 Service 代理模式,用于替代性能较差的 userspace 模式。该模式利用 Linux 内核的 iptables 功能,在 netfilter 框架中直接完成数据包的目的地址转换(DNAT),避免了用户态与内核态之间的频繁切换,大幅提升了 Service 的转发性能。

iptables 与 netfilter 基础

  • netfilter:Linux 内核中的一个框架,在网络协议栈的不同位置(钩子点)注册回调函数,允许对数据包进行修改、过滤或重定向。
  • iptables:用户空间的命令行工具,用于配置 netfilter 的规则表(filter、nat、mangle 等)。kube-proxy 使用 iptables 的 nat 表来实现 Service 的 DNAT。

当一个数据包进入节点内核时,会依次经过 PREROUTING、FORWARD、POSTROUTING 等钩子点。kube-proxy 在 PREROUTING 和 OUTPUT 链中插入自定义规则,将发往 Service IP 的流量劫持并重定向到后端 Pod。

工作原理

kube-proxy 以 iptables 模式运行时,会持续监听 API Server 中 Service 和 Endpoints 的变化,并据此刷新节点上的 iptables 规则。其核心机制是:

  1. 创建 KUBE-SERVICES 链:kube-proxy 在 nat 表中建立一个自定义链 KUBE-SERVICES,并在 PREROUTING 和 OUTPUT 链中跳转到该链。
  2. 为每个 Service 添加匹配规则:对于每个 Service(ClusterIP 类型),在 KUBE-SERVICES 链中添加一条规则,匹配目标 IP 为 Service ClusterIP、目标端口为 Service Port 的数据包,然后跳转到以 KUBE-SVC-<hash> 命名的专用链。
  3. 负载均衡与 DNATKUBE-SVC-<hash> 链中包含若干条统计随机规则(例如使用 statistic 模块的 random 模式),每条规则按概率匹配并跳转到 KUBE-SEP-<hash> 链。每一条 KUBE-SEP-<hash> 链对应一个后端 Pod,其规则会将数据包的目标地址和端口修改为该 Pod 的 IP 和容器端口(DNAT)。
  4. 回程路径处理:当后端 Pod 返回响应时,响应数据包的源地址是 Pod IP,目标地址是客户端 IP。由于之前已经通过 DNAT 修改过连接跟踪(conntrack)表,内核会自动将响应数据包的源地址还原为 Service IP,客户端无需感知后端变化。

配置示例与规则查看

可以通过以下命令查看节点上的 iptables 规则(需要进入 kube-proxy 所在节点或使用 nsenter):

bash
# 查看 nat 表中 KUBE-SERVICES 链的规则
iptables -t nat -L KUBE-SERVICES -n

# 查看某个 Service 对应的 KUBE-SVC 链
iptables -t nat -L KUBE-SVC-XYZ -n

一个简化的示例(假设 Service ClusterIP 为 10.96.0.10,端口 80,有两个后端 Pod IP 10.244.1.2 和 10.244.2.3):

bash
# KUBE-SERVICES 链中的条目
-A KUBE-SERVICES -d 10.96.0.10/32 -p tcp --dport 80 -j KUBE-SVC-ABCD

# KUBE-SVC-ABCD 链:50% 概率到第一个 SEP,剩余继续匹配
-A KUBE-SVC-ABCD -m statistic --mode random --probability 0.5 -j KUBE-SEP-1
-A KUBE-SVC-ABCD -j KUBE-SEP-2

# KUBE-SEP-1 链:执行 DNAT 到第一个 Pod
-A KUBE-SEP-1 -p tcp -j DNAT --to-destination 10.244.1.2:80

负载均衡算法

  • 默认算法:通过 statistic 模块的 random 概率匹配实现随机分发(不是轮询)。对于 n 个后端,每条规则的权重相等(概率为 1/n)。
  • 会话亲和性:通过设置 --dport 和连接跟踪的超时时间可以实现 ClientIP 会话亲和。具体是在 KUBE-SVC 链中增加 -m recent --set 等规则,将同一客户端 IP 的后续请求导向同一个 KUBE-SEP

优点

  • 性能较高:所有处理都在内核态完成,避免了 userspace 模式中的用户态/内核态上下文切换,转发延迟低,吞吐量高。
  • 实现简单:不需要运行额外的用户态代理进程(虽然 kube-proxy 依然运行,但仅负责规则刷新,不处理每条请求)。
  • 对 Pod 透明:后端 Pod 可以直接看到真实客户端 IP(通过修改 iptables 规则中的 --to-destination 配合 --preserve-literal 可能做不到完全保留,但配合 externalTrafficPolicy: Local 可解决),支持源 IP 白名单等需求。

缺点与限制

  • 规则数量线性增长:每个 Service 及其每个后端 Pod 都会产生多条 iptables 规则。当 Service 数量达到几千甚至上万级别时,节点上的 iptables 规则集变得非常庞大(可能几十万条),导致:
    • iptables-restore 刷新规则时间显著增长(从秒级到分钟级),影响 Service 更新的时效性。
    • 数据包遍历链的时间增加,CPU 使用率升高。
  • 不支持更复杂的负载均衡算法:iptables 仅支持随机分发(基于概率),不支持加权最少连接、IP 哈希等高级算法。
  • 连接跟踪(conntrack)负载:每个连接都需要在 conntrack 表中记录 DNAT 映射,高并发下 conntrack 表可能成为瓶颈(可通过调整内核参数缓解)。
  • 调试困难:当规则数量庞大时,排查数据包转发路径需要深入分析 iptables 链,较为复杂。

与 userspace 模式的对比

特性iptables 模式userspace 模式
数据包处理位置内核态(netfilter)用户态(kube-proxy 进程)
模式切换每次请求多次内核-用户切换
性能高,适合中大规模集群低,仅适合极小规模测试
负载均衡算法随机概率轮询
源 IP 保留支持(需配置 externalTrafficPolicy不支持
可扩展性中等,规则数量瓶颈极低,kube-proxy 单点瓶颈
当前状态Kubernetes 默认模式废弃

适用场景与使用建议

iptables 模式是 Kubernetes 默认且可靠的 Service 代理模式,适用于大多数生产环境,尤其是以下场景:

  • 集群规模中等(节点数 < 100,Service 数量 < 2000)。
  • 对延迟和吞吐量有较高要求,但不是极致性能(超大规模集群)。
  • 需要保留客户端源 IP 的 Service(可配合 spec.externalTrafficPolicy: Local)。

当 Service 数量超过 5000 或节点数量达到数百时,iptables 模式的规则刷新延迟和内存占用会成为问题,此时应考虑切换到 ipvs 模式。

切换到 ipvs 模式

若需要从 iptables 模式切换到 ipvs 模式,需要确保:

  • 内核加载了 ip_vsip_vs_rrip_vs_wrrip_vs_sh 等模块。
  • kube-proxy 启动参数中添加 --proxy-mode=ipvs
  • 安装 ipset 工具(ipvs 模式依赖)。

切换步骤一般通过修改 kube-proxy 的 ConfigMap(在 kube-system 命名空间)完成,然后重启 kube-proxy Pod。

总结

iptables 模式作为 Kubernetes Service 机制的成熟实现,在性能和实现复杂度之间取得了合理的平衡,是绝大多数集群部署的默认选择。理解其基于内核 DNAT 的工作原理、规则结构和限制,有助于在日常运维中诊断网络问题,并在集群规模增长到瓶颈时,顺利过渡到 ipvs 模式。