探究K8S Service内部iptables路由规则

栏目: 后端 · 发布时间: 5年前

内容简介:​ 在​ 为便于讲解,我们先创建如下应用及​ 作者的

前言

​ 在 K8S 集群内部,应用常使用 Service 互访,那么,了解 Service 技术优缺点将有利于应用规划与部署,鉴于此,本文将通过简单案例以探索 Cluster-Ip 类型 Service 服务的利弊。

​ 为便于讲解,我们先创建如下应用及 Service 服务:

# kubectl run --image=nginx nginx-web-1 --image-pull-policy='IfNotPresent'
# kubectl expose deployment nginx-web-1 --port=80 --target-port=80

Service 探索

​ 作者的 K8S 环境是 1.9 版本,其 Service 内部服务由 Kube-Proxy 提供,且默认用 iptables 技术实现,故本文探索 K8S 集群 Service 技术,即研究 iptablesK8S 上的技术实现。

Service Route (服务路由)

​ 如下可知,通过 nginx-web-1 服务可实际访问到后端 pod

# nginx pod ip地址:
# kubectl describe pod nginx-web-1-fb8d45f5f-dcbtt | grep "IP"
IP:             10.129.1.22

# Service服务,通过172.30.132.253:80则实际访问到10.129.1.22:80
# kubectl describe svc nginx-web-1 
...
Type:              ClusterIP
IP:                172.30.132.253
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.129.1.22:80
Session Affinity:  None
...

# 重置nginx web页面:
# kubectl exec -it nginx-web-1-fb8d45f5f-dcbtt -- \
               sh -c "echo hello>/usr/share/nginx/html/index.html"

# curl 10.129.1.22
hello
# curl 172.30.132.253
hello

Service 服务分配的 CLUSTER-IP 以及监听的端口均虚拟的,即在 K8S 集群节点上执行 ip anetstat -an 命令均无法找到,其实际上, IPPort 是由 iptables 配置在每 K8S 节点上的。在节点上执行如下命令可找到此 Service 相关的 iptables 配置,简析如下:

  1. 当通过 Service 服务 IP:172.30.132.253:80 访问时,匹配第 3 条规则链( KUBE-SERVICES )后,跳转到第 4 条子链( KUBE-SVC-... )上;
  2. 4 条子链做简单注释后,继而跳转到第 1、2 规则链( KUBE-SEP-... )上;
  3. 当源 Pod 通过 Service 访问自身时,匹配第 1 条规则,继而跳转到 KUBE-MARK-MASQ 链中;
  4. 匹配到第 2 条规则,此时通过 DNAT 被重定向到后端 Pod:108.29.1.22:80
# iptables-save | grep nginx-web-1
-A KUBE-SEP-UWNFTKZFYWNNNTK7 -s 10.129.1.22/32 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-MARK-MASQ
-A KUBE-SEP-UWNFTKZFYWNNNTK7 -p tcp -m comment --comment "demo/nginx-web-1:" \
   -m tcp -j DNAT --to-destination 10.129.1.22:80
-A KUBE-SERVICES -d 172.30.132.253/32 -p tcp -m comment \
   --comment "demo/nginx-web-1: cluster IP" -m tcp --dport 80 -j KUBE-SVC-SNP24T7IBBNZDJ76
-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-SEP-UWNFTKZFYWNNNTK7

​ 详细分析 iptables 规则,执行 iptables-save 命令可发现 natPREROUTINGOUTPUT 链中均有 KUBE-SERVICES 规则链,且处于第一顺位。

*nat
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

当通过 Service 访问应用时,流量经由 nat 表中的 PREROUTING 规则链处理后,跳转到 KUBE-SERVICES 子链,而此链包含了对具体 Service 处理的规则。如下所示,访问 172.30.132.253:80 将被跳转到 KUBE-SEP-... 子规则链中。

-A KUBE-SERVICES -d 172.30.132.253/32 -p tcp -m comment \
   --comment "demo/nginx-web-1: cluster IP" -m tcp --dport 80 -j KUBE-SVC-SNP24T7IBBNZDJ76
-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-SEP-UWNFTKZFYWNNNTK7

​ 如下所示, KUBE-SEP-... 子链存在两条规则:

  1. 1 条规则: Pod 通过 Service 访问自身时匹配,此规则仅作标记( MARK )处理;
  2. 2 条规则:通过 DNAT 重定向到后端 Pod 实例上,至此,通过 Service 最终将流量导向到后端实例上;
-A KUBE-SEP-UWNFTKZFYWNNNTK7 -s 10.129.1.22/32 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-MARK-MASQ
-A KUBE-SEP-UWNFTKZFYWNNNTK7 -p tcp -m comment --comment "demo/nginx-web-1:" \
   -m tcp -j DNAT --to-destination 10.129.1.22:80

-A KUBE-MARK-MASQ -j MARK --set-xmark 0x1/0x1

Loadbalance (负载均衡)

​ 执行如下命令将 Deployment 扩展为 3Pod 后,继而再观察 Service 负载均衡方面的技术或问题。

# kubectl scale deploy/nginx-web-1 --replicas=3

​ 再次 dump 防火墙规则,发现 Service 经由 iptablesstatistic 模块,以 random 方式均衡的分发流量,也即负载均衡模式为 轮训

  1. 存在 3DNATKUBE-MARK-MASQ 规则,分别对应 3 个后端 Pod 实地址;
  2. KUBE-SERVICES 链中存在 3 条子链,除最后一条 KUBE-SVC-... 子链外,其余子链使用模块 statisticrandom 模式做流量分割或负载均衡:第 1KUBE-SVC-... 应用 33% 流量,第 2KUBE-SVC-... 规则应用剩余的 50% 流量,第 3KUBE-SVC-... 规则应用最后的流量。
# iptables-save | grep nginx-web-1
-A KUBE-SEP-BI762VOIAZZWU5S7 -s 10.129.1.27/32 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-MARK-MASQ
-A KUBE-SEP-BI762VOIAZZWU5S7 -p tcp -m comment --comment "demo/nginx-web-1:" \
   -m tcp -j DNAT --to-destination 10.129.1.27:80

-A KUBE-SEP-CDQIKEVSTA766BRK -s 10.129.1.28/32 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-MARK-MASQ
-A KUBE-SEP-CDQIKEVSTA766BRK -p tcp -m comment --comment "demo/nginx-web-1:" \
   -m tcp -j DNAT --to-destination 10.129.1.28:80

-A KUBE-SEP-W5HTO42ZVNHJQWBG -s 10.129.3.57/32 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-MARK-MASQ
-A KUBE-SEP-W5HTO42ZVNHJQWBG -p tcp -m comment --comment "demo/nginx-web-1:" \
   -m tcp -j DNAT --to-destination 10.129.3.57:80

-A KUBE-SERVICES -d 172.30.132.253/32 -p tcp -m comment \
   --comment "demo/nginx-web-1: cluster IP" -m tcp --dport 80 -j KUBE-SVC-SNP24T7IBBNZDJ76

-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-BI762VOIAZZWU5S7
-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CDQIKEVSTA766BRK
-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-SEP-W5HTO42ZVNHJQWBG

Session Affinity (会话保持)

​ 如下所示,调整 Service 服务,打开会话保持功能,并设置会话保持期限为 3 小时( PS :若不设置,则默认是 3 小时):

# kubectl edit svc nginx-web-1
...
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800
...

​ 继续观察 iptables 实现,发现在原有基础上, iptables 规则中添加了 recent 模块,此模块被用于会话保持功能,故 kube-proxy 通过在 iptables 中结合 statisticrecent 模块,实现了 Service 的轮训负载均衡与会话保持功能。

  1. 通过 Service 服务访问应用,封包进入 KUBE-SERVICES 规则链,并跳转到 KUBE-SVC-... 子链中;
  2. KUBE-SVC-SNP... 子链中, recent 位于 statistic 模块前,故而,有如下情况出现:

    • 当客户端第一次访问 Service 时, KUBE-SVC-... 子链中的规则( -m recent --rcheck --seconds 10800 --reap ...--rsource )池中未记录客户端地址,故封包匹配失败,从而封包被后续的 statistic 模块规则处理后,均衡分发到 KUBE-SEP-... 子链中,此链中使用 recent 模块的 --set 参数将客户源地址记录到规则池后, DNAT 到实际后端实例上;
    • KUBE-SVC-... 子链中 recent 模块配置了源地址记录期限,若客户端 3--seconds 10800 --reap )小时内未访问服务,则 recent 规则池中的客户端记录将被移除,此时客户端再次访问 Service 就如同第一次访问 Service 一样;
    • 当客户端在 3 小时内再次访问 Service 时,匹配 KUBE-SVC-... 子链中的 recent 模块规则后,跳转到 KUBE-SEP 子链,其规则中 recent 模块 --set 参数将更新规则池中的 Record TTL ,而后 DNAT 到实际后端实例上;
# iptables-save | grep nginx-web-1
-A KUBE-SEP-BI762VOIAZZWU5S7 -s 10.129.1.27/32 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-MARK-MASQ
-A KUBE-SEP-BI762VOIAZZWU5S7 -p tcp -m comment --comment "demo/nginx-web-1:" \
   -m recent --set --name KUBE-SEP-BI762VOIAZZWU5S7 --mask 255.255.255.255 \
   --rsource -m tcp -j DNAT --to-destination 10.129.1.27:80
# 省略2条类似的KUBE-SEP规则
...

-A KUBE-SERVICES -d 172.30.132.253/32 -p tcp -m comment \
   --comment "demo/nginx-web-1: cluster IP" -m tcp --dport 80 -j KUBE-SVC-SNP24T7IBBNZDJ76

-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -m recent --rcheck --seconds 10800 --reap --name KUBE-SEP-BI762VOIAZZWU5S7 \
   --mask 255.255.255.255 --rsource -j KUBE-SEP-BI762VOIAZZWU5S7
# 省略2条类似的KUBE-SVC规则
...

-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-BI762VOIAZZWU5S7
-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CDQIKEVSTA766BRK
-A KUBE-SVC-SNP24T7IBBNZDJ76 -m comment --comment "demo/nginx-web-1:" \
   -j KUBE-SEP-W5HTO42ZVNHJQWBG

总结

K8S 中的 Service 服务可提供负载均衡及会话保持功能,其通过 Linux 内核 netfilter 模块来配置 iptables 实现,网络封包在内核中流转,且规则匹配很少,故效率非常高;而 Service 负载均衡分发比较薄弱,其通过 statisticrandom 规则实现轮训分发,无法实现复杂的如 最小链接 分发方式,鉴于此, K8S 1.9 后续版本调整了 kube-proxy 服务,其可通过 ipvs 实现 Service 负载均衡功能。

  1. K8S 1.9 版本可使用kube-router替换 kube-proxy ,且可使用 ipvs 替换 iptables 来实现 service 服务。

以上所述就是小编给大家介绍的《探究K8S Service内部iptables路由规则》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Introduction to the Design and Analysis of Algorithms

Introduction to the Design and Analysis of Algorithms

Anany Levitin / Addison Wesley / 2011-10-10 / USD 117.00

Based on a new classification of algorithm design techniques and a clear delineation of analysis methods, Introduction to the Design and Analysis of Algorithms presents the subject in a coherent a......一起来看看 《Introduction to the Design and Analysis of Algorithms》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具