k8s services iptables规则探究
结论
本文只讨论iptables的services实现,ipvs实现有所不同,这里先说结论如下:
service 使用iptables 来进行pod的dnat,services本身只是一条虚拟的iptables规则,不存在实体。
service 使用iptales 扩展模块来实现pod轮询策略故而无法实现最小链接数等负载算法
多pod下的RR实现使用iptables statistic模块的random算法加权实现
sessionAffinity 使用iptables recent模块实现保持,功能主要依赖于nf_conntrack来实现连接标记
单pod时service iptables 规则实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # nginx pod ip地址: $ kubectl describe pod nginx-fb8d45fxt-dcc1t | grep "IP" IP: 10.200.1.21 # Service服务,通过172.30.13.253:80则实际访问到10.200.1.21:80 $ kubectl describe svc nginx ... Type: ClusterIP IP: 172.30.13.25 Port: <unset> 80/TCP TargetPort: 80/TCP Endpoints: 10.200.1.21:80 Session Affinity: None ... $ iptables-save (选取部分关键规则) ... -A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES -A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES ... -A KUBE-SEP-UWNFTKZFYWNNNTK7 -s 10.200.1.21/32 -m comment --comment "demo/nginx:" \ -j KUBE-MARK-MASQ -A KUBE-SEP-UWNFTKZFYWNNNTK7 -p tcp -m comment --comment "demo/nginx:" \ -m tcp -j DNAT --to-destination 10.200.1.21:80 -A KUBE-SERVICES -d 172.30.13.25/32 -p tcp -m comment \ --comment "demo/nginx: cluster IP" -m tcp --dport 80 -j KUBE-SVC-1T7IBBNZDJ76 -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -j KUBE-SEP-UWNFTKZFYWNNNTK7
分析:
当访问 172.30.13.25/32 的80 端口时,iptables 规则会被第三条规则命中KUBE-SERVICES,在转发到 KUBE-SVC-1T7IBBNZDJ76 链 ,KUBE-SVC-1T7IBBNZDJ76链对流量进行comment标记之后 转发到 KUBE-SEP-UWNFTKZFYWNNNTK7
该链上实现了第一条访问外网的和一条对内的DNAT,此时是向内访问规则会命中第二条向内部进行DNAT 转发到pod地址上,进行路由寻址。
负载算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $ kubectl scale deploy/nginx --replicas=3 $ iptables-save (选取部分规则) -A KUBE-SEP-BI123VOIAZZ5S7 -s 10.129.1.12/32 -m comment --comment "demo/nginx:" \ -j KUBE-MARK-MASQ -A KUBE-SEP-BI123VOIAZZ5S7 -p tcp -m comment --comment "demo/nginx:" \ -m tcp -j DNAT --to-destination 10.129.1.12:80 -A KUBE-SEP-CDQIKASRG66RK -s 10.129.1.13/32 -m comment --comment "demo/nginx:" \ -j KUBE-MARK-MASQ -A KUBE-SEP-CDQIKASRG66RK -p tcp -m comment --comment "demo/nginx:" \ -m tcp -j DNAT --to-destination 10.129.1.13:80 -A KUBE-SEP-W5HTO42ZVNHJQWBG -s 10.129.1.14/32 -m comment --comment "demo/nginx:" \ -j KUBE-MARK-MASQ -A KUBE-SEP-W5HTO42ZVNHJQWBG -p tcp -m comment --comment "demo/nginx:" \ -m tcp -j DNAT --to-destination 10.129.1.14:80 -A KUBE-SERVICES -d 172.30.13.25/32 -p tcp -m comment \ --comment "demo/nginx: cluster IP" -m tcp --dport 80 -j KUBE-SVC-1T7IBBNZDJ76 -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-BI123VOIAZZ5S7 -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CDQIKASRG66RK -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -j KUBE-SEP-W5HTO42ZVNHJQWBG
分析:
iptable 在实现多pod 负载算法的时候使用了 statistic模块的random 加权算法 -m statistic --mode random --probability 0.33332999982
来实现。具体模块用法可以参考:http://ipset.netfilter.org/iptables-extensions.man.html
会话保持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 $ kubectl edit svc nginx ... sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 3600 ... $ iptables-save (选取部分规则) -A KUBE-SEP-BI123VOIAZZ5S7 -s 10.129.1.12/32 -m comment --comment "demo/nginx:" \ -j KUBE-MARK-MASQ -A KUBE-SEP-BI123VOIAZZ5S7 -p tcp -m comment --comment "demo/nginx:" \ -m recent --set --name KUBE-SEP-BI123VOIAZZ5S7 --mask 255.255.255.255 \ --rsource -m tcp -j DNAT --to-destination 10.129.1.12:80 ... -A KUBE-SERVICES -d 172.30.13.25/32 -p tcp -m comment \ --comment "demo/nginx: cluster IP" -m tcp --dport 80 -j KUBE-SVC-1T7IBBNZDJ76 -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -m recent --rcheck --seconds 3600 --reap --name KUBE-SEP-BI123VOIAZZ5S7 \ --mask 255.255.255.255 --rsource -j KUBE-SEP-BI123VOIAZZ5S7 ... -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-BI123VOIAZZ5S7 -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CDQIKASRG66RK -A KUBE-SVC-1T7IBBNZDJ76 -m comment --comment "demo/nginx:" \ -j KUBE-SEP-W5HTO42ZVNHJQWBG
分析
iptables 主要使用recent 模块来标记追踪连接状态 -m recent --rcheck --seconds 3600
来完成会话保持。具体recent模块用法可以参考:http://ipset.netfilter.org/iptables-extensions.man.html