ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] 本节我们主要介绍一下Kube-proxy在IPVS模式下,数据包的转发流程。 ### **IPVS的模式** 在kube-proxy中,实际上使用的是IPVS的NAT模式。 ### **ClusterIP的转发** 我们知道,IPVS模块其实是在netfilter框架的NF_INET_LOCAL_IN钩子处注册了一个钩子函数,而且这个函数的优先级是最高的,也就是每一个到达该钩子处的数据包,最先都是由IPVS的钩子函数进行处理。如果IPVS对数据包做了DNAT,那么就会把数据包发送到NF_INET_POST_ROUTING去。 当我们在容器里通过`ClusterIP:Port`访问Service时,那么数据包在K8S主机上的流程应该是:`NF_INET_PRE_ROUTING -> 路由选择 -> NF_INET_LOCAL_IN`。在NF_INET_LOCAL_IN处,由IPVS模块注册的钩子函数进行DNAT的处理。 数据包要到达NF_INET_LOCAL_IN,那么在路由选择的时候,这个数据包的目的地址要是本机IP。我们知道,这个数据包从容器里出来的时候,目的IP就是Service的ClusterIP,在NF_INET_PRE_ROUTING处由于不再做DNAT,所以目的地址是不会变的。那么如何识别ClusterIP为本机IP呢? 其实,当启用IPVS模式时,kube-proxy会在本机上创建一个名为`kube-ipvs0`的网卡,每创建一个Service,kube-proxy都会把Service的ClusterIP设置在这个网卡上。 如下,集群中有两个Service,ClusterIP分别为10.96.0.1和10.96.0.10,然后我们查看ipvs0网卡的信息,发现刚好有这两个IP ``` $ kubectl get service --all-namespaces NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 86m kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 86m $ ip addr show kube-ipvs0 11: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default link/ether 3e:11:b4:33:0d:a8 brd ff:ff:ff:ff:ff:ff inet 10.96.0.1/32 brd 10.96.0.1 scope global kube-ipvs0 valid_lft forever preferred_lft forever inet 10.96.0.10/32 brd 10.96.0.10 scope global kube-ipvs0 valid_lft forever preferred_lft forever ``` ### **NodePort的转发** 我们在K8S集群中发布一个Deployment,它有两个Pod,然后为其创建一个NodePort的Service,如下: ``` $ kubectl get node NAME STATUS ROLES AGE VERSION 192.168.2.102 Ready master 108m v1.17.3 192.168.2.103 Ready <none> 108m v1.17.3 $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES tomcat-565cd88dc7-ddvk4 1/1 Running 0 4m31s 172.26.190.194 192.168.2.103 <none> <none> tomcat-565cd88dc7-v542c 1/1 Running 0 4m31s 172.26.190.193 192.168.2.103 <none> <none> $ kubectl get service tomcat NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE tomcat NodePort 10.105.6.182 <none> 8080:30230/TCP 98s ``` 两个Pod在103主机上。接下来我们来分析一下,当我们从外部通过主机IP+NodePort(192.168.2.102:30230)来访问时,数据包在102主机上的流程。 数据包在102主机上的流程如下: ``` NF_INET_PRE_ROUTING -> 路由选择 -> NF_INET_LOCAL_IN(IPVS做DNAT) -> NF_INET_POST_ROUTING(SNAT) ``` 数据包首先到达NF_INET_PRE_ROUTING处,在nat表的PREROUTING链中的KUBE-SERVICES链下有如下规则: ``` $ iptables -t nat -nL KUBE-SERVICES Chain KUBE-SERVICES (2 references) target prot opt source destination ... KUBE-NODE-PORT all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL ... $ iptables -t nat -nL KUBE-NODE-PORT Chain KUBE-NODE-PORT (1 references) target prot opt source destination KUBE-MARK-MASQ tcp -- 0.0.0.0/0 0.0.0.0/0 /* Kubernetes nodeport TCP port for masquerade purpose */ match-set KUBE-NODE-PORT-TCP dst $ iptables -t nat -nL KUBE-MARK-MASQ Chain KUBE-MARK-MASQ (10 references) target prot opt source destination MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 $ ipset list KUBE-NODE-PORT-TCP Name: KUBE-NODE-PORT-TCP Type: bitmap:port Revision: 3 Header: range 0-65535 Size in memory: 8268 References: 1 Number of entries: 1 Members: 30230 ``` 从上面可以看出,当访问102主机的NodePort时,在NF_INET_PRE_ROUTING处,数据包会被打上一个标记(0x4000),然后经过路由选择进入到NF_INET_LOCAL_IN处,在这里IPVS模块的钩子函数对数据包进行DNAT操作,然后再把数据包投递到NF_INET_POST_ROUTING处。 我们来看一下nat表的POSTROUTING链中的规则,如下: ``` $ iptables -t nat -nL POSTROUTING Chain POSTROUTING (policy ACCEPT) target prot opt source destination ... KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */ ... $ iptables -t nat -nL KUBE-POSTROUTING Chain KUBE-POSTROUTING (1 references) target prot opt source destination MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000 ... ``` 从上面的iptables规则可以看出,在NF_INET_POST_ROUTING钩子处,数据包由于有标记0x4000,所以它会做一个Masqurade源地址转换。 ### **IPVS的优点** 相对于iptables,IPVS具有如下的优点: * 支持多种负载均衡策略 iptables只支持随机策略,而ipvs支持轮询、加权等多种策略 * 支持虚拟服务器的健康检测与重试机制 how? * 对于大规模集群,性能更好 iptables的规则在内核中是链表的形式存在,kube-proxy更新iptables规则都是做全量更新。如果Service和Pod数量过大,更新时间会过长,导致iptables锁住。 ipvs规则在内核中是以哈希表的形式存在, kube-proxy更新规则为增量更新,更新的时间复杂度为O(1)。 可参考以下文章 https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/ipvs/README.md https://zhuanlan.zhihu.com/p/37230013 ### **FAQ** **Q:什么时候应该选择iptables模式,什么时候应该选择ipvs模式?** A:参考 https://docs.ucloud.cn/uk8s/introduction/kubeproxy_mode **Q: IPVS如何支持健康检测与重试机制?** ### **参考** * https://docs.ucloud.cn/uk8s/introduction/kubeproxy\_mode