Kubernetes当集群内访问ClusterIP类型的 Service

ClusterIP 流量路径

客户端 Pod → ClusterIP → kube-proxy 规则(iptables/IPVS) → DNAT → 后端 Pod(可能跨节点)
  • 不涉及 Node 端口:与 NodePort/LoadBalancer 不同,ClusterIP 仅通过集群内部虚拟 IP 转发。
  • 跨节点依赖 CNI:由 CNI 插件(如 Calico、Flannel)实现 Pod 间的跨节点通信。
  • 无 SNAT:集群内流量保留客户端 Pod IP
举例子
  • 假设:
Service 的 ClusterIP: 10.96.1.2,端口 80。
后端 Pod: 172.16.1.2:9376(运行在 NodeA 上),172.16.2.3:9376(运行在 NodeB 上)
  • (1)kube-proxy 会创建类似以下规则
# 1. 匹配目标为 ClusterIP 的流量
-A KUBE-SERVICES -d 10.96.1.2/32 -p tcp --dport 80 -j KUBE-SVC-XXXX

解释:(匹配目标为 ClusterIP 的流量)
-A KUBE-SERVICES
将规则追加到 KUBE-SERVICES 链(Kubernetes 自定义链,用于处理所有 Service 流量)。
-d 10.96.1.2/32
匹配目标 IP 为 10.96.1.2(Service 的 ClusterIP),/32 表示精确匹配。
-p tcp --dport 80
匹配 TCP 协议且目标端口为 80(Service 的端口)。
-j KUBE-SVC-XXXX
跳转到 KUBE-SVC-XXXX 链(该 Service 专用的负载均衡链)。

作用:
将所有发往 10.96.1.2:80 的流量交给 KUBE-SVC-XXXX 链处理

# 2. 负载均衡到后端 Pod(概率随机分发)
-A KUBE-SVC-XXXX -m statistic --mode random --probability 0.5 -j KUBE-SEP-YYYY1
-A KUBE-SVC-XXXX -j KUBE-SEP-YYYY2

解释:(负载均衡到后端 Pod)
第一条负载均衡规则
-m statistic --mode random --probability 0.5
使用 statistic 模块进行概率匹配:
--mode random:随机模式。
--probability 0.5:50% 的概率匹配该规则。
-j KUBE-SEP-YYYY1
如果匹配成功(50% 概率),跳转到 KUBE-SEP-YYYY1 链(对应第一个后端 Pod)。
第二条负载均衡规则
-j KUBE-SEP-YYYY2
如果未匹配第一条规则(剩余 50% 概率),跳转到 KUBE-SEP-YYYY2 链(对应第二个后端 Pod)

作用:
实现简单的随机负载均衡,将流量均匀分发到两个后端 Pod。

# 3. DNAT 规则:将 ClusterIP 转换为 Pod IP
-A KUBE-SEP-YYYY1 -p tcp -j DNAT --to-destination 172.16.1.2:9376  # Pod 在 NodeA
-A KUBE-SEP-YYYY2 -p tcp -j DNAT --to-destination 172.16.2.3:9376  # Pod 在 NodeB

解释:(DNAT 转换(目标地址转换)
第一条 DNAT 规则
-j DNAT --to-destination 172.16.1.2:9376
将数据包的目标 IP 和端口从 ClusterIP:80 修改为 172.16.1.2:9376(第一个 Pod 的 IP 和端口)。
第二条 DNAT 规则
-j DNAT --to-destination 172.16.2.3:9376
将目标地址修改为 172.16.2.3:9376(第二个 Pod 的 IP 和端口)。

作用:
完成从 Service 虚拟 IP 到实际 Pod IP 的转换,使流量最终到达后端 Pod。



规则链的层级关系
KUBE-SERVICES:所有 Service 流量的入口链。
KUBE-SVC-XXXX:单个 Service 的负载均衡链。
KUBE-SEP-YYYY:单个后端 Pod(Endpoint)的 DNAT 链。
  • (2)流量转发流程
客户端 Pod(如 172.16.3.4)发起请求到 10.96.1.2:80。
数据包进入内核协议栈,匹配 KUBE-SERVICES 链的规则。
根据负载均衡策略(如随机),选择一条 KUBE-SEP-YYYY 规则。
DNAT 生效:目标 IP 从 10.96.1.2:80 改为 172.16.1.2:9376(假设选中 NodeA 的 Pod)。
数据包通过 CNI 插件(如 Calico、Flannel) 跨节点路由到 NodeA 的 Pod(如果客户端与 Pod 不在同一节点)。

调试技巧

  1. 查看完整 iptables 规则
conntrack -L -d 10.96.1.2 -p tcp --dport 80
  1. 检查 DNAT 转换结果
tcp  src=172.16.3.4 dst=10.96.1.2 sport=12345 dport=80 \
     [DNAT] to=172.16.1.2:9376
  1. 检查所有 Node 的 iptables 规则
# 在任意 Node 上执行
iptables -t nat -L KUBE-SERVICES -n | grep 10.96.1.2
  1. 对比不同 Node 的 DNAT 规则
# 在 NodeA 和 NodeB 上分别执行
iptables -t nat -L KUBE-SVC-XXXX -n
替换为 IPVS 规则
# 查看 IPVS 规则
ipvsadm -Ln

# 输出示例
TCP  10.96.1.2:80 rr  # ClusterIP 服务,调度算法为轮询(rr)
  -> 172.16.1.2:9376    Masq    1    0    0  # 后端 Pod1
  -> 172.16.2.3:9376    Masq    1    0    0  # 后端 Pod2
关键变化点
  • (1) 负载均衡算法的差异
    iptables:
    使用 statistic 模块的随机概率分发(概率权重)。
    IPVS:
    支持多种调度算法(如 rr、lc、sh),默认 rr(轮询)。

  • (2) 规则存储方式
    iptables:
    规则以链式结构存储在内核的 nat 表中,线性匹配效率较低(O(n))。
    IPVS:
    规则以哈希表存储,查找效率为 O(1),适合大规模 Service。

  • (3) NAT 行为的保留
    SNAT(Masq):
    IPVS 默认启用 Masq(类似 iptables 的 MASQUERADE),确保回复流量经过节点。
    DNAT:
    IPVS 直接修改目标地址,无需显式 DNAT 规则。

总结
  • 每个 Node 上的 kube-proxy 会维护基本相同的 iptables/IPVS 规则,但具体规则细节会根据该 Node 上是否运行相关 Pod 而略有差异
  • 确保无论从哪个 Node 或 Pod 访问 ClusterIP,都能正确负载均衡到后端 Pod
  • 实现: 可能跨节点(依赖 CNI)
  • 例外情况
    externalTrafficPolicy: Local:
    仅适用于 NodePort/LoadBalancer,对 ClusterIP 无影响。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容