k8s-kube-proxy运行机制分析
在每个Node上都会运行一个kube-proxy服务进程,这个进程可以看做service的透明代理和负载均衡器。其核心功能是将某个service的访问请求转发到后端的某个Pod上。对每一个TCP类型的service,kube-proxy都会在本地Node上建立一个socketserver来负责接收请求,然后均匀发送到后端某个Pod端口上。这个过程默认采用Round Robin负载均衡算法。此外,s
在每个Node上都会运行一个kube-proxy服务进程,这个进程可以看做service的透明代理和负载均衡器。其核心功能是将某个service的访问请求转发到后端的某个Pod上。对每一个TCP类型的service,kube-proxy都会在本地Node上建立一个socketserver来负责接收请求,然后均匀发送到后端某个Pod端口上。这个过程默认采用Round Robin负载均衡算法。
此外,service的cluster IP和Nodeport概念是proxy通过Iptables的NAT转换实现的。proxy在运行过程中动态创建于service相关的Iptables规则,这些规则实现了Cluster IP及NodePort的请求流量重定向到proxy进程上对应服务的代理端口的功能。
也就是说,访问service的请求,都会被节点机的Iptables规则重定向到kube-proxy监听service服务代理端口,那么proxy如何选择后端的pod呢?
目前proxy只支持round robin算法,该算法是轮询查询。
接下来深入分析proxy实现细节:
kube-proxy通过查询和监听API server中service和endpoint的变化。为每个service都建立了一个服务代理对象。并自动同步。服务代理对象是proxy程序内部的一种数据结构,它包括一个用于监听此服务请求的socketserver,socketserver的端口是随机选择的一个本地空闲端口。此外,kube-proxy内部也创建了一个负载均衡器-LoadBalancer,LoadBalancer上保存了service到对应的后端endpoint列表的动态转发路由表。而具体的路由选择则取决于Round Robin负载均衡算法及service的session会话保持这两个特性。
针对发生变化的service列表,proxy会逐个处理,下面是具体处理流程:
1.如果该service没有设置Cluster IP,则不做任何处理,否则获取该service的所有端口定义列表(spec.ports域)
2.逐个读取服务端口定义列表中的端口信息,根据端口名称,service名称和namespace判断本地是否已经存在对应的服务代理对象,如果不存在则新建,若存在并且service端口被修改过,则先删除Iptables中和该service端口相关的规则,关闭服务代理对象,然后走新建流程,也就是为该service端口分配服务代理对象并为创建相关的Iptables规则。
3.更新负载均衡器组件中对应service的转发地址列表,对于新建的service,确定转发时的会话保持策略。
4.对于已删除的service则进行清理。
proxy在启动时和坚挺到service或endpoint变化后,会在本机的Iptables的NAT表中添加4条规则链。
a,KUBE-PORTALS-CONTAINER:从容器中通过service Cluster IP和端口号访问service的请求。
b,KUBE-PORTALS-HOST:从主机通过service Cluster IP和端口号访问service的请求。
c,KUBE-NODEPORT-CONTAINER:从容器中通过service的NodePort端口号访问service的请求。
d,KUBE-NODEPORT-HOST:从主机通过service的NodePort端口号访问service的请求。
此外,kube-proxy在Iptables上为每个service创建由Cluster IP+service端口到kube-proxy所在主机IP+service代理服务所监听的端口的转发规则。
可以看到对“redis-master”service的6379端口的访问将被转发至物理机的42872端口。而42872端口就是proxy为这个service打开的随机本地端口。
更多推荐
所有评论(0)