千家信息网

k8s-service中iptable cluster ip实现原理

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,本篇文章为大家展示了k8s-service中iptable cluster ip实现原理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。在这里我们主要介绍集群内
千家信息网最后更新 2024年11月30日k8s-service中iptable cluster ip实现原理

本篇文章为大家展示了k8s-service中iptable cluster ip实现原理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

在这里我们主要介绍集群内的负载均衡。对于k8s集群中的服务是需要相互访问的,一般我们都会为之创建相应的service,对于集群内部的service类型我们一般设置成cluster ip。对于一个cluster ip后面会关联多个endpoints,也就是实际的pod。对于cluster ip的访问,也就是实现了对cluster ip关联的多个endpoints访问。关于cluster ip和endpoints的流量负载均衡,一般有iptable方式和ipvs方式,在以前文章里有所介绍。这里我们主要以实际例子来介绍iptable的实现方式。另外cluster ip是虚拟ip,言外之意就是这个ip没有和任何device绑定,所以当你对这个ip进行例如ping或者traceroute命令的时候是不会得到应答的。

查看部署的nginx application的service,我们可以看到:

  • 这个service为cluster ip类型

  • cluster ip为10.254.226.173

  • 这个cluster ip关联了2个endpoints:10.1.27.4:80和10.1.79.3:80


kubectl describe service service-nginx-app -n default

查看host network namespace iptable的nat表:


iptables -nvL -t nat

对于PREROUTING chain中,所有的流量都走到了KUBE-SERVICES这个target中。请注意PREROUTING chain是流量到达之后的第一个入口。试想我们在pod里运行命令curl http://10.254.226.173,根据以前文章里介绍的容器内部路由表,数据包应该是这样的流动:

  • 在pod中,根据路由表发现cluster ip(10.254.226)走默认路由,选择了默认网关。

  • 在pod中,默认网关的ip地址就是宿主netwok namespace的docker0的ip地址,并且默认网关为直连路由。

  • 在pod中,根据路由表,使用eth0 device发送数据,根据以前文章,eth0本质是veth pair在pod network namespace的一端,另一端attach在宿主netwok namespace的docker0 bridge上。

  • 根据以前文章介绍的veth pair,数据从pod network namespace的一端发出,进入到了attached到docker0 bridge上的另一端。

  • docker0 bridge收到数据之后,自然就来到了host network namesapce的PREROUTING chain。

查看KUBE-SERVICES target:


iptables -nvL -t nat | grep KUBE-SVC

在KUBE-SERVICES target中我们可以看到目标地址为cluster ip10.254.226.173的匹配target为KUBE-SVC-ETZVW7ENORYJBYB4。

查看KUBE-SVC-ETZVW7ENORYJBYB4 target:


iptables -nvL -t nat

在KUBE-SVC-ETZVW7ENORYJBYB4 target中我们可以看到:

  • 有2个target,分别是KUBE-SEP-L6A5J2X5SCQGCA7Z和KUBE-SEP-U7JQ3R4SRIDMQ4UH

  • 在KUBE-SEP-L6A5J2X5SCQGCA7Z中有statistic mode random probability 0.5

  • 对于statistic mode random probability 0.5是利用了iptable内核随机模块,随机比率为0.5,也就是50%。

  • 所以对于上面的意思是有一半的随机比率进入到KUBE-SEP-L6A5J2X5SCQGCA7Z target当中,那么自然另一个target的随机比率也是一半了。

  • 由此可见,是通过随机模块来均匀的实现负载均衡的。

查看KUBE-SEP-L6A5J2X5SCQGCA7Z和UBE-SEP-L6A5J2X5SCQGCA7Z target:


iptables -nvL -t nat

在这2个target中我们可以看到:

  • 分别做了MASQ操作,当然这个应该是出站engress流量(限定了source ip),不是我们的入站ingress流量。

  • 做了DNAT操作,把原来的cluster ip给DANT转换成了pod的ip 10.1.27.4和10.1.79.3。把原来的port转换成了80 port

  • 经过这个一系列iptable的target我们的原始请求10.254.226.173:80就变成了10.1.27.4:80或者10.1.79.3:80,而且两者转变的机率各是50%。

  • 根据iptable,经过PREROUTING chain发现DNAT之后的10.1.27.4或者10.1.79.3不是本地的ip(肯定不是,因为这两个ip是pod的ip,当然不会在host的network namespace里)。所以就走到了Forwarding chain中,根据host network namespace的路由表来决定下一跳地址。

所以综合上面的例子,对于ipable方式的k8s集群内cluster-ip类型的service总结为:

  • 流量从pod network namespace中走到host netwok namespace的docker0中。

  • 在host netwok namespace的PREROUTING chain中会经过一系列target。

  • 在这些target里根据iptable内核随机模块来实现匹配endpoint target,随机比率为均匀分配,实现均匀的负载均衡。

  • 在endpoint target里实现了DNAT,也就是将目标地址cluster ip转化为实际的pod的ip。

  • cluster ip是虚拟ip,不会和任何device绑定。

  • 负载均衡为内核实现,使用均匀负载均衡,不可以有自定义的负载均衡算法。

  • 需要host开启路由转发功能(net.ipv4.ip_forward = 1)。

  • 数据包在host netwok namespace中经过转换以及DNAT之后,由host network namespace的路由表来决定下一跳地址。

上述内容就是k8s-service中iptable cluster ip实现原理,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

0