1、概述
我觉得只要大家知道kube-proxy是用来配置网络规则的而不是转发流量的,真正的流量由iptables/ipvs来转发就可以了。
网络是k8s的一个关键部分。理解k8s中网络组件如何工作可以帮助更好的设计和配置我们的应用。
kube-proxy就是K8s网络的核心组件。它把我们应用使用的service翻译为网络规则。
kube-proxy这个名气会有让人产生一点歧义,因为有技术背景的朋友们看到后不了解之前就会想到用户的流量是先经过kube-proxy,然后kube-proxy转发到集群的,其实并不是这样的。kube-proxy只负责网络规则的创建,修改和删除,真正的流量还是依赖于Linux/Windows来接受和转发。如果从这个角度来理解,kube-proxy在Linux环境上主要控制和配置iptables或ipvs, 在windows则控制和配置kernelspec。 从这个角度来看kube-proxy像是一个控制平面,iptables/ipvs/kernelspec像是一个数据平面。
正因为kube-proxy不处理用户流量,所以k8s的性能不会有什么问题,反观Istio使用边车模式(sidecar),对流量进行管理才会导致性能问题。
在开始说明kube-proxy之前,我们可以想一下kube-proxy主要想解决哪些问题。
2.kube-proxy需要解决哪些问题?
- 服务发现,给Pod提供一个统一的入口来访问服务
- 负载均衡:这里主要是kube-proxy把Pod的路由信息写到iptables或者ipvs,让内核对根据支持的负载均衡算法进行流量转发
另外,我想额外说明的是kube-proxy时刻都要监听Api Server(kube-proxy的老板)发送过来的Pod的CUD(创建,更新和删除)信息,有变更就改规则。
3.什么是kube-proxy
k8s中的Pod是临时的,因为Pod中运行的是我们的应用,我们的应用可能随时会崩溃,崩溃了以后k8s会为我们重新创建,我们不能用Pod的IP通信,因为Pod每次崩溃重启IP会变更,而且Pod的数量也会改变。
所以K8s就增加了Service来提供Pod统一的入口。Service提供了连接一个或者多个的Pod静态地址。我们可以这么理解:进入k8s集群的流量先到达Service,然后流量被重定向到Pod,同时Service保证流量不转发到不健康的Pod。这个保证会在一个短的时间无法保证,就是Pod从进入不健康状态到被检测出不健康的这个时间区间。
但是在网络层如何实现Service到Pod的映射?kube-proxy就是干这事的。
kube-proxy会被安装在每个k8s的Node之上。它用来监控Service和Endpoint的变化。然后他会将这些变化转换为自己Node上的网络规则。
kube-proxy是以DaemonSet的形式运行在k8s集群中的。但是它也可以以进程的方式安装在Linux系统之中。安装方式可以参考官网自己选择。
- kubeadmin安装k8s,kube-proxy会被安装位DaemonSet
- 使用Linux tar方式安装,kube-proxy会以Linux进程方式运行
4.kube-proxy工作原理
在kube-proxy安装完成后,它会与API Server完成认证。
当新的Service或者EndPoint被添加或者移除,那么API Server会将这些变更通知给kube-proxy。
kube-proxy在收到通知后会将这些变化应用于Node的NAT规则中。这些NAT规则就是简单的件Service IP映射到Pod IP。
当有流量发送给Service时,Service会基于NAT的这些规则将流量转发给Pod。
我们来看几个例子。
假设我们有一个Service,这个Service名字为SVC01,类型为ClusterIP。当这个Service创建完成后,API Server会检查需要关联到这个Service的Pod。我们一般是通过在Service中配置Pod的标签来选择一组Pod,所以API Server会查找与Service中标签匹配的Pod。
假设API Server查找到的Pod为Pod01和Pod02,其中Pod1在Node1,Pod2在Node2。API Server会创建一个抽象的Endpoint。每个EndPoint。每个EndPoint代表了一个Pod的IP地址。SVC01可以绑定到这两个Pod对应的Endpoint。假设这两个EndPoint为EP01和EP02。
这些配置在Control Plane完成后,k8s还在将这些Mapping关系体现在Node上。一旦这些配置在Node上配置完成后,SVC01 Servvice的流量就会被转发到EP01和EP02,如下图所示:
在这种情况下,如果有流量进入SVC01,则流量转发如下图:
Service和EndPoint映射说明:
- Service和EndPoint是IP和端口的映射而不只是IP的映射
- DNAT转换发生在源Node。因为Service类型是ClusterIP,只能从集群内部进行访问
- 如果Service类型是其他方式,比如:NodePort,这些规则会被应用到Linux。
- NAT规则会随机选择其中一个Pod进行流量转发,但是这个会根据kube-proxy的模式而改变
下面我们来看下kube-proxy的模式。
5.kube-proxy模式
kube-proxy支持不同的网络转发模式。每种模式用来描述Kube-proxy如何来实现NAT规则。想要知道每种模式的好坏,我们需要理解每种模式的工作原理。
5.1.IPtables 模式
IPTables是最通用和最常用的模式。在这个种模式下,kube-proxy依赖于Linux的IPTables的功能特性。Iptable用来处理数据和过滤数据包。它会检查Linux机器上的入站和出站流量,然后IPtable可以根据规则来匹配数据包并将其转发。
当k8s使用这种模式时,kube-proxy会将Service到Pod的NAT规则写入到IPTables中。IPTables根据kube-proxy写入到这些规则将流量重定向到对应的Pod。
5.1.1.IPTables劣势
IPTables劣势就是在大规模集群下性能低。
使用IPTables模式的不好之处就是它的规则是链式的,因为IPTables的设计目的是为了数据包的过滤组件。那么IPTables在处理大量规则时性能就会很低,因为链式查找速度慢。所以选择这种模式时你需要考虑你的k8s集群Service和Pod的数量,如果数量太大的话就考虑选择其他模式了。
另外,IPTables不支持一些特定的负载均衡算法,只支持简单轮询方式来实现负载均衡。
5.2.IPVS 模式
IPVS (IP Virtual Server)是一种高效的Layer-4交换机,实现了运行在LVS下的提供负载平衡功能的技术。IPVS基本上是一种高效的Layer-4交换机,它提供负载平衡的功能。这个是k8s kube-proxy的一个较好的选择。在IPVS模式下,kube-proxy将转发规则写入到IPVS中。
由于IPVS是一个专门用于交换的模块,所以它的查找算法最小可以在O(1)时间复杂度完成,所以它在大规模集群下能够表现出很好且很稳定的性能。
IPVS模式也支持很多负载均衡算法,比如:轮询,最小连接和其他哈希算法。
5.2.1.劣势
IPVS模块不一定默认安装在Linux系统中,你可能需要手动安装或启用它。并且如果不是大规模集群,IPTables就可以满足你的场景。
IPVS和Iptable对比
tigera公司提供的数据,就是开源Colico网络组件的那个公司。
-
服务数量与平均响应时间
-
服务数量与CPU占用
如何iptables和ipvs如何选择?
上面的两个图表表示:在1000个Pod时ipvs和iptables性能没有什么差别,超过1000个ipvs模式性能更高。
另外,如果你不确定使用哪个,你就选择ipvs吧。
5.3.KernelSpace 模式
这个模式时Windows节点专用的。在这个模式下,kube-proxy会将包过滤规则写入到windows的VFP(Windows Virtual Filtering Platform)。Windows上的VFP的工作原理和Linux的IPTables一样,这就意味着VFP会将数据包中的目的IP地址替换为Pod的IP地址。
如果你不熟悉Windows平台的虚拟机,那么你可以认为VFP是Hyper-V的一个扩展,这个扩展专门用于虚拟机网络。
5.4.如果检查kube-proxy的模式?
你可以通过接口查询kube-proxy的模式,kube-proxy默认端口为10249.
你可以使用**/proxyMode** 来查询kube-proxy模式,
curl -v localhost:10249/proxyMode
COPY
上图展示了这个kube-proxy使用了ipvs模式。
5.5.IPVS规则查看
IPVS可以通过ipvsadm命令进行查看,可能需要先安装
sudo apt install ipvsadm
sudo ipvsadm -L
COPY
5.6.IPTables规则查看
使用iptables命令查看nat规则列表
iptables -t nat -n -L
COPY
6.FAQ
6.1.k8s Service是一个代理吗 ?
k8s service使用起来像是一个代理,它为客户端提供了一个静态接入点。
6.2.kube-proxy会进行负载均衡吗 ?
这个视情况而定。
如果你说的是的kube-proxy这个k8s的网络agent,那么kube-proxy不会进行负载均衡。因为kube-proxy并不接收流量进行转发,而是依赖于OS提供的能力。
如果你说的是kube-proxy创建的规则,那么会。因为kube-proxy会创建对多个Pod创建具有负载均衡能力的Service,这个依赖于iptables/ipvs/kernelspec。
7.总结
kube-proxy是k8s的网络代理,它主要将Service的定义转换为网络规则。它在集群中的每个Node上运行,并与API Server通信以接收Service的更新,然后将这些更新同步到自己的Node中。
kube-proxy并不会直接接收流量并将其转发,而是依赖于OS提供的相关能力来完成。