Erda 开源地址: https://github.com/erda-project/erda
Erda cloud 官网:Erda Cloud
在kubernetes出现之前,我们通常会使用nginx,haproxy,甚至是lvs这些负载均衡技术来实现业务的服务均衡,需要专门的工程师去维护这些组件,当有业务节点上下线时,也需要人工的去进行相应的配置或者写一些自动化的脚本来处理这些变动。
kube-proxy是kubernetes提供的集群内的标准负载均衡方案,我们知道在kubernetes中pod是作为承载业务的小单元,并且pod的IP是动态分配的并且经常变化,需要在前面需要一个叫做service的东西,通过标签选择器和pod进行关联,实现pod的负载均衡。
kube-proxy部署在每个node节点上,它是实现service的通信与负载均衡机制的重要组件,kube-proxy负责为Pod创建代理服务,从apiserver获取所有server信息,并根据server信息创建代理服务,实现server到Pod的请求路由和转发,从而实现K8S层级的虚拟转发网络。
从功能上看kube-proxy的工作模式很简单,从kubernetes-apiserver去获取service的信息,然后部署在每个node节点上的kube-proxy组件来创建对应的负载均衡策略,实现pod的负载均衡。

kube-proxy主流支持iptables和ipvs两种方式来创建负载均衡均衡策略,关于这两种方式的优缺点在其他文档应该都会介绍,这里稍作总结下:
这里也稍微蹭一个热点--eBPF, linux提供的内核虚拟机,为用户程序访问内核空间提供了可能,腾讯的TKE基于eBPF提供了ipvs-bpf的模式进一步优化了k8s service的性能。
cilium也出了一个"kubernetes without kube-proxy"的方案将eBPF技术用在了service上,相信在不久会出现很多eBPF的实现方案,甚至是成为kubernetes的默认行为。
先来看一个service的yaml文件,该svc创建了一个26880的端口映射,对应的后端服务的端口也是26880,我看看一下这个iptables的流量走向。
apiVersion: v1
kind: Service
metadata:
name: services-prod-6059-oms-api
namespace: default
spec:
clusterIP: 10.21.7.223
ports:
- name: http-0
port: 26880
protocol: TCP
targetPort: 26880
selector:
appid: 5d891e37-0ba3-42de-8495-c8c256734e05
sessionAffinity: None
type: ClusterIP对应的pod IP如下:

比如我们要从某台节点通过ClusterIP:10.21.7.223访问对应的pod,那么它的数据包会在iptables中经过如下流转:
1, filter表通过OUTPUT链规定所有的出报文都要经过KUBE-SERVICES

2,数据包会交给nat表的KUBE-SERVICES链来处理,在KUBE-SERVICE链中我们可以找到对目的IP10.21.7.223的处理,会继续交由给KUBE-SVC-KLU3DS3WRPTYAOLU来处理

3,再来看看KUBE-SVC-KLU3DS3WRPTYAOLU的处理逻辑,会通过权重交由给如下两个链来处理,这里就是使用iptables来实现了负载均衡。

4,再看看KUBE-SEP链的内容,在该链中完成了终的DNAT,将目的地址转换成了POD的IP和端口


跟iptables模式一样的是,kube-proxy依然监听service以及endpoint对象的变化,不一样的是这里不是创建大量的iptables规则,而是通过ipvsadm来创建ipvs规则。
这里我们一这个nexus的svc为例,该svc分别映射了3个端口,那么对应的也会创建三条不同的ipvs规则
apiVersion: v1
kind: Service
metadata:
name: addon-nexus
namespace: default
spec:
clusterIP: 10.99.100.18
ports:
- name: addon-nexus-tcp-8081
port: 8081
protocol: TCP
targetPort: 8081
- name: addon-nexus-tcp-5000
port: 5000
protocol: TCP
targetPort: 5000
- name: addon-nexus-tcp-5500
port: 5500
protocol: TCP
targetPort: 5500
selector:
dice/addon: addon-nexus
sessionAffinity: None
type: ClusterIP
在平时的故障排查过程中,比如遇到svc不通的时候,我们可以先查看对应的ipvs是不是被正确创建了,如果对应的IP不对,那应该就是kube-proxy没有在正常工作了,可以去查看下对应的kube-proxy日志,如果规则都是被正确创建了,那么应该就是容器网络的问题了,可以继续再去查看对应节点上的网络组件是否健康,以及对应的组件日志。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3168453/ ,如需转载,请注明出处,否则将追究法律责任。