Kube-proxy
在k8s集群,每个节点都运行一个 kube-proxy 服务,它监听 API server 中 service 和 endpoint 的变化情况,并通过 iptables 等来为服务配置负载均衡(仅支持 TCP 和 UDP)。
kube-proxy 可以直接运行在物理机上,也可以以 static pod 或者 daemonset 的方式运行。
kube-proxy 当前支持几种模式:
- userspace:最早的负载均衡方案,它在用户空间监听一个端口,所有服务通过 iptables 转发到这个端口,然后在其内部负载均衡到实际的 Pod。该方式最主要的问题是效率低,有明显的性能瓶颈。
- iptables:以 iptables 规则的方式来实现 service 负载均衡。该方式最主要的问题是在服务多的时候产生太多的 iptables 规则,非增量式更新会引入一定的时延,大规模情况下有明显的性能问题。
- ipvs:为解决 iptables 模式的性能问题,v1.11 新增了 ipvs 模式(v1.8 开始支持测试版,并在 v1.11 GA),采用增量式更新,并可以保证 service 更新期间连接保持不断开。
- winuserspace:同 userspace,但仅工作在 windows 节点上。
iptables模式原理
在 iptables 模式下,会根据 service 以及 endpoints 对象的改变来实时刷新规则,kube-proxy 使用了 iptables 的 filter 表和 nat 表,并对 iptables 的链进行了扩充,自定义了 KUBE-SERVICES、KUBE-EXTERNAL-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING、KUBE-MARK-MASQ、KUBE-MARK-DROP、KUBE-FORWARD 七条链。
由 kube-proxy 在 PREROUTING 链中创建的规则用于确定数据包是用于节点上的本地套接字,还是应该转发到 pod。
正是这些iptables规则确保了对 < kubernetes-node-ip > : < NodePort > 的请求继续被路由到 pods,即使另一个进程正在使用 NodePort或者 kube-proxy服务down掉。
这是一个简单的流程图:
(图片来源:cilium/k8s-iptables-diagram)
具体的流程,一图胜千言:
(图片来源@Tim Hockin)
ipvs模式原理
kube-proxy 在 ipvs 模式下自定义了八条链,分别为 KUBE-SERVICES、KUBE-FIREWALL、KUBE-POSTROUTING、KUBE-MARK-MASQ、KUBE-NODE-PORT、KUBE-MARK-DROP、KUBE-FORWARD、KUBE-LOAD-BALANCER。
由于 linux 内核原生的 ipvs 模式只支持 DNAT,不支持 SNAT,所以,在以下几种场景中 ipvs 仍需要依赖 iptables 规则:
- kube-proxy 启动时指定 –-masquerade-all=true 参数,即集群中所有经过 kube-proxy 的包都做一次 SNAT;
- kube-proxy 启动时指定 --cluster-cidr= 参数;
- 对于 Load Balancer 类型的 service,用于配置白名单;
- 对于 NodePort 类型的 service,用于配置 MASQUERADE;
- 对于 externalIPs 类型的 service;
IPVS vs IPTABLES
ipvs 和 iptables 都是基于netfilter
,不同的是:
- IPVS为大型群集提供更好的可扩展性和性能。
- IPVS支持比Iptables更复杂的负载平衡算法。(最小负载,最少连接,位置,加权等)
- IPVS支持服务器运行状况检查和连接重试等。
IPTables 模式下的 Kube-proxy 按顺序处理连接,这导致计算复杂度为 0(n),其中 n 的增长大致与服务数量和每个服务的后端 pod 数量成比例。
IPVS 模式下的 Kube-proxy:IPVS 实现使用由内核管理的哈希表来建立数据包的目的地。 kube-proxy 在 IPVS 模式下的连接处理计算复杂度为 O(1),其连接处理性能将保持不变,与集群大小无关。
下面是性能对比:
(图片来源:comparing-kube-proxy-modes-iptables-or-ipvs)
从图中可以看到,在超过 1,000 个服务(10,000 个后端 pod)之前,iptables 和 IPVS 之间平均往返响应时间的差异是微不足道的。
随着集群规模的增加,ipvs的优势会越加明显。