除了Kubelet,每个工作节点还会运行kube-proxy,用于确保客户端可以通过Kubernetes API连接到你定义的服务。kube-proxy确保对服务IP和端口的连接最终能到达支持服务(或者其他,非pod服务终端)的某个pod处。如果有多个pod支撑一个服务,那么代理会发挥对pod的负载均衡作用。
感觉有些东西我们还是不够连贯我看有时间慢慢改,基础核心的概念还是需要眼熟的,后面会有大量的图片实践可以让我们理解云原生
为什么被叫作代理
kube-proxy最初实现为userspace代理。利用实际的服务器集成接收连接,同时代理给pod。为了拦截发往服务IP的连接,代理配置了iptables规则(iptables是一个管理Linux内核数据包过滤功能的工具),重定向连接到代理服务器。
userspace代理模式
kube-proxy之所以叫这个名字是因为它确实就是一个代理器,不过当前性能更好的实现方式仅仅通过iptables规则重定向数据包到一个随机选择的后端pod,而不会传递到一个实际的代理服务器。这个模式称为iptables代理模式
iptables代理模式
两种模式的主要区别是:数据包是否会传递给kube-proxy,是否必须在用户空间处理,或者数据包只会在内核处理(内核空间)。这对性能有巨大的影响。
另外一个小的区别是:userspace代理模式以轮询模式对连接做负载均衡,而iptables代理模式不会,它随机选择pod。
当只有少数客户端使用一个服务时,可能不会平均分布在pod中。例如,如果一个服务有两个pod支持,但有 5个左右的客户端,如果你看到 4个连接到pod A,而只有一个连接到pod B,不必惊讶。对于客户端数量更多的pod,这个问题就不会特别明显。
kube-proxy 如何使用iptables
-
当在API服务器中创建一个服务时,虚拟IP地址立刻就会分配给它。之后很短时间内,API服务器会通知所有运行在工作节点上的kube-proxy客户端有一个新服务已经被创建了。
-
每个kube-proxy都会让该服务在自己的运行节点上可寻址。原理是通过建立一些iptables规则,确保每个目的地为服务的IP/端口对的数据包被解析,目的地址被修改,这样数据包就会被重定向到支持服务的一个pod。
除了监控API对Service的更改,kube-proxy也监控对Endpoint对象的更改。
因为你基本上不会去手动创建它们,所以比较容易忘记它们的存在。Endpoint对象保存所有支持服务的pod的IP/端口对(一个IP/端口对也可以指向除pod之外的其他对象)。
这就是为什么kube-proxy必须监听所有Endpoint对象。毕竟Endpoint对象在每次新创建或删除支持pod时都会发生变更,当pod的就绪状态发生变化或者pod的标签发生变化,就会落入或超出服务的范畴。
现在让我们了解一下kube-proxy如何让客户端能够通过Service连接到这些pod.
图中描述kube-proxy做了什么,以及数据包如何通过客户端pod发送到支持服务的一个pod上。让我们检查一下当通过客户端pod(图中的pod A)发送数据包时发生了什么。
包目的地初始设置为服务的IP和端口(在本例中,Service是在 172.30.0.1:80)。发送到网络之前,节点A的内核会根据配置在该节点上的iptables规则处理数据包。
内核会检查数据包是否匹配任何这些iptables规则。其中有个规则规定如果有任何数据包的目的地IP等于 172.30.0.1、目的地端口等于 80,那么数据包的目的地IP和端口应该被替换为随机选中的pod的IP和端口。
本例中的数据包满足规则,故而它的IP/端口被改变了。在本例中,pod B2 被随机选中了,所有数据包的目的地IP变更为10.1.2.1(pod B2 的IP),端口改为8080(Service中定义的目标端口)。就好像是,客户端pod直接发送数据包给pod B而不是通过Service。
实际上可能比描述的要更复杂一点儿,但是上述内容是你需要理解的最重要的内容。
小故事
咳咳,各位亲们,听说了吗?在Kubernetes那个宇宙里,有个叫kube-proxy的小机灵鬼,它可是集群内部服务发现和流量分配的顶梁柱啊!
当初在1.2版本的时候,kube-proxy毅然决然地告别了它青涩的userspace时期,踏上了iptables这条快车道,从此摇身一变成了API Server的头号粉丝,每天24小时守着人家的一举一动,跟追星似的盯着Service和Endpoint的变化,随时准备变身超人,飞速修改iptables规则,保证客户端请求像坐火箭一样直奔目标Pod,你说这速度,比外卖小哥送餐还快,完全省去了用户空间和内核空间之间的“你侬我侬”,性能杠杠滴😂!
可素,iptables也不是万能的,毕竟谁还没点小烦恼呢~
当集群规模蹭蹭涨,Service和Pod的数量多到可以拍连续剧的时候,iptables的规则列表硬生生变成了一本《天龙八部》,翻页的速度都能把蜗牛急哭😭。
于是乎,Kubernetes团队在1.8版本的时候祭出了秘密武器——IPVS大侠,到了1.11版本,IPVS更是喜提“稳定出道”的荣誉勋章🎉。
IPVS大侠可不是吃素的,人家是专门为高端大气上档次的负载均衡打造的内核级高手,手里捏着一把神兵利器——优化过的Hash表,那处理起规则来,犹如行云流水,再大的集群都不带怕的🚀。
而且它还会耍些花哨招数,什么最小负载分配、最少连接数加权啥的,时不时还搞个服务器健康检查、连接重试的附加服务,堪称集群界的五星级服务员😍。
尽管IPVS威猛无比,但也并非无所不能,有些iptables的绝活(比如包过滤、SNAT之类的变装术)它还得甘拜下风。
不过,关键时刻,IPVS懂得借力打力,找来了ipset小助手,俩人组成了黄金搭档,ipset就好比是IP地址的百宝箱,把IP地址、IP范围、端口这些玩意儿收拾得整整齐齐,iptables只需一指禅,指向哪个集合,就能实现策略,真真是节约了不少时间和精力,堪比武林秘籍里的“一键召唤术”👌。
面对不同类型的Service,kube-proxy化身武林盟主,根据不同门派特点量身定做iptables规则,比如说,给Cluster IP披上防伪斗篷(KUBE-CLUSTER-IP),对外服务IP戴上酷炫面具(KUBE-EXTERNAL-IP),负载均衡器嘛,自然是要舞动乾坤,分配流量有如运筹帷幄(KUBE-LOAD-BALANCER系列),至于NodePort服务家族,那是各自都有独门心法(KUBE-NODE-PORT系列规则)。
最后,咱们来个大总结:kube-proxy这位武林盟主一路修炼升级,从用户空间的小喽啰成长为深谙内功的iptables+IPVS双剑合璧模式,不仅把集群的稳定性和速度拔高了一个档次,还巧妙化解了大规模部署时的重重困境,就跟破茧成蝶一样励志💪。
现在,IPVS凭借着傲视群雄的扩展能力和逆天的负载均衡实力,成功上位新一代kube-proxy的标配神器;但在某些特定情境下,iptables和ipset这对欢喜冤家还会携手共战,一起保障集群内的服务交流畅通无阻,如同相声搭档般默契配合,让Kubernetes集群在网络世界里既有高度的可靠性,又有十足的灵活性,实在是妙哉妙哉💃🕺。