文章目录
- 1.kube-proxy概述
- 2.userspace模式
- 3.iptables模式
- 4.ipvs模式
1.kube-proxy概述
kube-proxy组件是用来实现service的请求转发,具体实现方式是kube-proxy运行在每个node上,通过watch监听
API Server 中service资源的create,update,delete事件,以获取新的Pod 和 vip映射关系,然后通过更新 iptables 规则来实现请求数据的转发,构建并维护各节点路由信息。
kubernetes中kube-proxy支持三种模式,在v1.8之前使用的是iptables 以及 userspace两种模式,在kubernetes 1.8之后引入了ipvs模式,并且在v1.11中正式使用,其中iptables和ipvs都是内核态也就是基于netfilter,只有userspace模式是用户态。
在详细了解kube-porxy前,先看下service的配置文件,这里面定义了转发涉及到的了3个port:
- port: 对外的service port
- target port: 提供服务的pod port
- node port: 中间转发的node port
# cat service-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: mynginx
namespace: default
spec:
selector:
app: mynginx
clusterIP: 10.10.98.98 # service ip
type: NodePort # service 类型
ports:
- port: 80 # service端口
targetPort: 8000 # pod端口
nodePort: 30080 # node端口
2.userspace模式
在userspace模式下,kube-proxy进程是一个真实的TCP/UDP代理,当某个pod以clusterIP方式访问某个service的时候,这个流量会被pod所在的本机的iptables转发到本季的kube-proxy进程,然后将请求转发到后端某个pod上。
- kube-proxy监听API Server 已添加和删除service和Endpoint对象,获取映射关系。
- 在本地节点上打开一个随机端口(nodePort),访问该随机端口的流量将会转发到后端pod(通过映射关系)。会通过SessionAffinity策略决定要转发到哪个后端Pod。(用户空间)
- 安装iptables规则,以捕获service的clusterIP和port的请求流量。规则会将流量重定向到随机端口(nodePort)。(内核空间)
- 当流量重定向到nodePort时,kube-proxy 作为一个负载均衡,将流量分发到后端的pod。默认情况下,用户空间模式下的kube-proxy通过轮询算法选择后端pod。(用户空间)
- clusterip重定向到kube-proxy服务的过程存在内核态到用户态的切换,开销很大,因此有了iptables模式,而userspace模式也被废弃了。
3.iptables模式
kubernets从1.2版本开始将iptabels模式作为默认模式,这种模式下kube-proxy不再起到proxy的作用。其核心功能:通过API Server的Watch接口实时跟踪Service和Endpoint的变更信息,并更新对应的iptables规则,Client的请求流量通过iptables的NAT机制
“直接路由”到目标Pod。
- kube-proxy监听API Server 已添加和删除service和Endpoint对象,获取映射关系。
- kube-proxy 对每个service安装iptables规则,以捕获service的clusterIP和port的请求流量,规则会将流量重定向到某个后端集。(内核空间)
- 对于每个Endpoint对象,将继续安装iptables规则,通过iptables将作为一个负载均衡,分发流量到后端的pod。默认情况下,iptables随机选择后端pod。(内核空间)
- 不同于userspace模式,iptables模式由kube-proxy动态的管理,kube-proxy不再负责转发,数据包的走向完全由iptables规则决定,这样的过程不存在内核态到用户态的切换,效率明显会高很多。
- 随着service的增加,iptables规则会不断增加,导致内核十分繁忙(等于在读一张很大的没建索引的表),2个svc,8个pod就有34条iptabels规则了,随着集群中svc和pod大量增加以后,iptables中的规则开会急速膨胀,导致性能下降,某些极端情况下甚至会出现规则丢失的情况,并且这种故障难以重现和排查。
- 如果通过iptables规则转发的第一个Pod没有响应,则连接失败,不会自动重试。但可以使用Pod Readiness Probe来验证后端Pod 是否正常运行,若正常iptables即可转发流量到后端pod,若异常,kube-proxy会直接从service中剔除pod。
4.ipvs模式
从kubernetes 1.8版本开始引入第三代的IPVS模式,它也是基于netfilter实现的,但定位不同:iptables是为防火墙设计的,IPVS则专门用于高性能负载均衡,并使用高效的数据结构Hash表,允许几乎无限的规模扩张。
一句话说明:ipvs使用ipset存储iptables规则,在查找时类似hash表查找,时间复杂度为O(1),而iptables时间复杂度则为O(n)。
- kube-proxy监听API Server 已添加和删除service和Endpoint对象,获取映射关系。
- 调用netlink接口创建相应IPVS规则,并定期通过service和endpoint同步IPVS规则。
- 访问service时,IPVS将流量分到后端Pod之一。
- IPVS代理模式也基于netfilter挂钩函数,工作在内核空间,但是使用哈希表作为基础数据结构。这意味着,与iptables模式下的kube-proxy相比,IPVS模式下的kube-proxy重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。而且ipvs作为一个四层负载均衡器,与其他代理模式相比,支持多种负载均衡算法和更高的网络流量吞吐量。
- 可以将ipset简单理解为ip集合,这个集合的内容可以是IP地址、IP网段、端口等,iptabels可以直接添加规则对这个可变集合进行操作,这样做的好处可以大大减少iptables规则的数量,从而减少性能损耗。假设要禁止上万个IP访问我们的服务器,如果用iptables的话,就需要一条一条的添加规则,会生成大量的iptabels规则;但是用ipset的话,只需要将相关IP地址加入ipset集合中即可,这样只需要设置少量的iptables规则即可实现目标。
- 由于ipvs无法提供包过滤、地址伪装、SNAT等功能,所以某些场景下(比如NodePort的实现)还要与iptables搭配使用。
IPVS提供多种负载均衡算法:
- rr:轮循
- lc:连接最少(打开的连接最少)
- dh:目标哈希
- sh:源哈希
- sed:最短的预期延迟
- nq:永不排队