集群中的每个节点上都有 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提供了更好的负载均衡算法:
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)。
参考文献
kubernetes – How to find which mode kube-proxy is running in – Stack Overflow
Manage kube-proxy by using IPVS