本文是张磊《深入剖析 Kubernetes》的学习记录。
假设某 svc 代理了 3 个 Pod,Pod IP 是 10.244.1.7,10.244.2.3,10.244.3.6,Pod 监听的端口是 9376。
svc 的 IP 是 10.0.1.175,svc 代理的端口是 80。
该 svc 提交到 k8s 之后,发生 2 件事:
- DNS 组件添加一条 A 记录
- kube-proxy 做出相应动作
根据 kube-proxy 所做动作的不同,svc 分为两种模式,iptables 模式和 IPVS 模式。
iptables 模式
此模式下,所有节点的 kube-proxy 修改本机的 iptables 规则。
主要原理
iptables 规则可以示意为:
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
这条 iptables 规则的含义是:凡是目的地址是 10.0.1.175、目的端口是 80 的 IP 包,都应该跳转到另外一条名叫 KUBE-SVC-NWV5X2332I4OT4T3 的 iptables 链进行处理。
而 KUBE-SVC-NWV5X2332I4OT4T3 是一组规则的集合:
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR
这是一组随机模式(--mode random
)的 iptables 链。
它表示,第一条被选中的概率是 1/3,第二条是 1/2,最后一条是 1。于是,这 3 条链等概率地被选中。
而这 3 条链的明细如下:
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
这是 3 个 DNAT 规则,DNAT 规则的作用是,在数据包进入路由之前,把 IP 包的目的 IP 和目的端口,改成 --to-destination
所指定的 IP 和端口,也就是具体 Pod 的 IP 和端口。
于是,在本机被发往 svc 的数据包,目的地址被改成了那个 svc 所代理的某个 Pod 的地址。
问题所在
一旦 svc 个数比较多,每个节点就会有成百上千条 iptables 规则,而且还要在控制循环中不断刷新以确保这些规则的正确。这可能导致 CPU 资源被大量占用,甚至造成宿主机卡住。
IPVS 模式
此模式下,所有节点的 kube-proxy 会在所在主机创建一个叫 kube-ipvs0 的虚拟网卡。
主要原理
虚拟网卡的 IP 就是 svc 的 VIP。
之后,kube-proxy 会使用 Linux 的 IPVS 模块给这个 IP(也就是 svc 的 VIP)创建 3 个 IPVS 虚拟主机,并给这 3 个虚拟主机使用轮询模式(RR)的负载均衡策略。而这 3 个虚拟主机的 IP 和端口,就是 svc 对应 Pod 的 IP 和端口。
此时,任何发送到 svc 的数据包,都会被 IPVS 模块转发到某个具体 Pod。
注意事项
IPVS 的转发也是 NAT,所以,它的转发性能不比 iptables 好,但它的优势在于不用维护大量的 iptables 规则.
需要注意的是,IPVS 模块只负责上述的负载均衡和代理功能。而一个完整的 svc 流程正常工作所需要的包过滤、SNAT 等操作,还是要靠 iptables 来实现。只不过,这些辅助性的 iptables 规则数量有限,也不会随着 Pod 数量的增加而增加。
标签:comment,iptables,Service,Kubernetes,--,IP,svc,原理,KUBE From: https://www.cnblogs.com/jthmath/p/17149839.html