「Kubernetes」- kube-proxy

  CREATED BY JENKINSBOT

集群中的每个节点上都有 kube-proxy 服务,负责为 Service (除 ExternalName 外)实现一种形式的 虚拟网络地址 。
1)在 Kubernetes v1.0 中, Service 是“第4层”(基于IP的TCP/UDP)构造,代理纯粹在用户空间中。
2)在 Kubernetes v1.1 中,添加 Ingress API(beta)来表示“第7层”(HTTP)服务,也添加 iptables 代理,并成为自 Kubernetes v1.2 以来的默认操作模式。
3)在 Kubernetes v1.8.0-beta.0 中,添加 ipvs 代理。

下面是kube-proxy运行的三种模式:

代理模式:userspace

该模式下,kube-proxy观察Kubernetes master节点,然后删除和添加Service与Endpoints对象。为每个Service在本地节点打开一个端口(随机),任何访问该“代理端口”的连接将被代理到Service的后端Pod上。至于用哪个后端Pod,要基于Service的SessionAffinity。最后,它安装防火墙规则,捕获到Service的Cluster IP(虚拟)和端口的流量,然后重定向流量到“代理端口”。

默认后端是循环选择的。

Client  =>  ClusterIP:Port(iptables)  =>  proxy port(kube-proxy)  =>  Backend Pod 1 ~ N

(”为每个Service在本地节点打开一个端口“,该端口号存在于 Cluster IP 上)

代理模式:iptables

该模式下,kube-proxy观察Kubernetes master节点,然后删除和添加Service与Endpoints对象。对于每个Service,它安装防火墙规则,捕获到Service的Cluster IP(虚拟)和端口的流量,然后重定向流量到Service的后端集合。对于每个Endpoints对象,它安装防火墙规则,来选择后端的Pod。

默认后端是循环选择的。

Client  =>  ClusterIP:Port(iptables)  =>  Backend Pod 1 ~ N
											^
											|
										kube-proxy <= api-server

代理模式:ipvs

该模式下,kube-proxy观察Kubernetes的Service和Endpoints,然后调用netlink接口来创建ipvs规则,并定期和k8s的Service和Endpoints同步ipvs规则,确保ipvs状态符合预期。当访问服务时,流量将被重定向到其中一个后端Pod上。

类似于iptables,ipvs基于netfilter的钩子函数,但是使用哈希表作为底层的数据结构,并工作在内核空间。这表示ipvs重定向流量更快,当同步规则时由更好的效率。并且ipvs提供了更好的负载均衡算法:

rr: round-robin

lc: least connection

dh: destination hashing

sh: source hashing

sed: shortest expected delay

nq: never queue

使用 ipvs 模式需要在节点上安装了 IPVS 内核模块,然后再运行 kube-proxy 服务。当kube-proxy以ipvs代理模式启动时,kube-proxy将验证节点上是否安装了IPVS模块,如果未安装,则kube-proxy将回退到iptables代理模式。

Client  =>  ClusterIP:Port(Virtual Server(ipvs))  =>  Backend Pod 1 ~ N
											^
											|
									kube-proxy <- apiserver

代理模式的总结

在任何一种代理模式中,访问IP:Port的流量被代理到对应的后端,而不需要Client知道任何的k8s的Service和Endpoints或Pod。基于Client-IP的Session亲和可以通过将service.spec.sessionAffinity设置为ClientIP来实现。基于此,还可以设置service.spec.sessionAffinityConfig.clientIP.timeoutSeconds来实现最大的 Session粘贴时间 (默认10800)。

常用维护操作

查看 kube-proxy 的当前模式

// 查看配置文件指定的模式

# kubectl get configmaps kube-proxy -n kube-system -o yaml | grep mode
    mode: "ipvs"

// 查看当前正在使用的模式

# kubectl exec -n kube-system -it  "<dsname>" -- cat /var/lib/kube-proxy/config.conf

# kubectl exec -n kube-system -it  kube-proxy-952qm -- cat /var/lib/kube-proxy/config.conf
...
mode: mode: "ipvs"
...

// 或者,直接查看 kube-proxy 运行日志

...
W0322 08:09:44.312816       1 server_others.go:578] Unknown proxy mode "", assuming iptables proxy
I0322 08:09:44.313052       1 server_others.go:185] Using iptables Proxier.
...

修改 kube-proxy 的运行模式

How to set kube-proxy settings using kubectl on AKS

如果要修改配置文件,使用命令:

# kubectl -n kube-system edit configmap kube-proxy

参考文献

kubernetes – How to find which mode kube-proxy is running in – Stack Overflow
Manage kube-proxy by using IPVS