专注于大数据及容器云核心技术解密,可提供全栈的大数据+云原生平台咨询方案,请持续关注本套博客。如有任何学术交流,可随时联系。更多内容请关注《数据云技术社区》公众号。

1 何为Iptables
1.1 基本功能
- 流量转发:DNAT 实现 IP 地址和端口的映射;
- 负载均衡:statistic 模块为每个后端设置权重;
- 会话保持:recent 模块设置会话保持时间;
1.2 五条链
- iptables 有五张表和五条链,五条链分别对应为:
- PREROUTING 链:数据包进入路由之前,可以在此处进行 DNAT;
- INPUT 链:一般处理本地进程的数据包,目的地址为本机;
- FORWARD 链:一般处理转发到其他机器或者 network namespace 的数据包;
- OUTPUT 链:原地址为本机,向外发送,一般处理本地进程的输出数据包;
- POSTROUTING 链:发送到网卡之前,可以在此处进行 SNAT;
1.3 五张表:
这五张表是对 iptables 所有规则的逻辑集群且是有顺序的,当数据包到达某一条链时会按表的顺序进行处理,表的优先级为:raw、mangle、nat、filter、security。
- filter 表:用于控制到达某条链上的数据包是继续放行、直接丢弃(drop)还是拒绝(reject);
- nat 表:network address translation 网络地址转换,用于修改数据包的源地址和目的地址;
- mangle 表:用于修改数据包的 IP 头信息;
- raw 表:iptables 是有状态的,其对数据包有链接追踪机制,连接追踪信息在 /proc/net/nf_conntrack 中可以看到记录,而 raw 是用来去除链接追踪机制的;
- security 表:最不常用的表,用在 SELinux 上;
2 kube-proxy 的 iptables 模式
2.1 kube-proxy
- kube-proxy 组件负责维护 node 节点上的防火墙规则和路由规则。
- 在 iptables 模式下,会根据 service 以及 endpoints 对象的改变来实时刷新规则,kube-proxy 使用了 iptables 的 filter 表和 nat 表,并对 iptables 的链进行了扩充,自定义了 KUBE-SERVICES、KUBE-EXTERNAL-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING、KUBE-MARK-MASQ、KUBE-MARK-DROP、KUBE-FORWARD 七条链。
- 另外还新增了以“KUBE-SVC-xxx”和“KUBE-SEP-xxx”开头的数个链,除了创建自定义的链以外还将自定义链插入到已有链的后面以便劫持数据包。
2.2 clusterIP 访问方式
2.2.1 非本机访问
PREROUTING --> KUBE-SERVICE --> KUBE-SVC-XXX --> KUBE-SEP-XXX
2.2.2 本机访问
OUTPUT --> KUBE-SERVICE --> KUBE-SVC-XXX --> KUBE-SEP-XXX
2.2.3 访问流程:
- 1.对于进入 PREROUTING 链的都转到 KUBE-SERVICES 链进行处理;
- 2.在 KUBE-SERVICES 链,对于访问 clusterIP 为 10.110.243.155 的转发到 KUBE-SVC-5SB6FTEHND4GTL2W;
- 3.访问 KUBE-SVC-5SB6FTEHND4GTL2W 的使用随机数负载均衡,并转发到 KUBE-SEP-CI5ZO3FTK7KBNRMG 和 KUBE-SEP-OVNLTDWFHTHII4SC 上;
- 4.KUBE-SEP-CI5ZO3FTK7KBNRMG 和 KUBE-SEP-OVNLTDWFHTHII4SC 对应 endpoint 中的 pod 192.168.137.147 和 192.168.98.213,设置 mark 标记,进行 DNAT 并转发到具体的 pod 上,如果某个 service 的 endpoints 中没有 pod,那么针对此 service 的请求将会被 drop 掉;
// 1.对于进入 PREROUTING 链的都转到 KUBE-SERVICES 链进行处理;
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
// 2.在 KUBE-SERVICES 链,对于访问 clusterIP 为 10.110.243.155 的转发到 KUBE-SVC-5SB6FTEHND4GTL2W;
-A KUBE-SERVICES -d 10.110.243.155/32 -p tcp -m comment --comment "pks-system/tenant-service: cluster IP" -m tcp --dport 7000 -j KUBE-SVC-5SB6FTEHND4GTL2W
// 3.访问 KUBE-SVC-5SB6FTEHND4GTL2W 的使用随机数负载均衡,并转发到 KUBE-SEP-CI5ZO3FTK7KBNRMG 和 KUBE-SEP-OVNLTDWFHTHII4SC 上;
-A KUBE-SVC-5SB6FTEHND4GTL2W -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CI5ZO3FTK7KBNRMG
-A KUBE-SVC-5SB6FTEHND4GTL2W -j KUBE-SEP-OVNLTDWFHTHII4SC
// 4.KUBE-SEP-CI5ZO3FTK7KBNRMG 和 KUBE-SEP-OVNLTDWFHTHII4SC 对应 endpoint 中的 pod 192.168.137.147 和 192.168.98.213,
设置 mark 标记,进行 DNAT 并转发到具体的 pod 上,如果某个 service 的 endpoints 中没有 pod,那么针对此 service 的请求将会被 drop 掉;
-A KUBE-SEP-CI5ZO3FTK7KBNRMG -s 192.168.137.147/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-CI5ZO3FTK7KBNRMG -p tcp -m tcp -j DNAT --to-destination 192.168.137.147:7000
-A KUBE-SEP-OVNLTDWFHTHII4SC -s 192.168.98.213/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-OVNLTDWFHTHII4SC -p tcp -m tcp -j DNAT --to-destination 192.168.98.213:7000
2.3 nodePort 访问方式
- 在 nodePort 方式下,会用到 KUBE-NODEPORTS 规则链,通过 iptables -t nat -L -n 可以看到 KUBE-NODEPORTS 位于 KUBE-SERVICE 链的最后一个,iptables 在处理报文时会优先处理目的 IP 为clusterIP 的报文,在前面的 KUBE-SVC-XXX 都匹配失败之后再去使用 nodePort 方式进行匹配。
- 创建一个 nodePort 访问方式的 service 以及带有两个副本,访问 nodeport 的 iptables 规则流向为:
2.3.1 非本机访问
PREROUTING --> KUBE-SERVICE --> KUBE-NODEPORTS --> KUBE-SVC-XXX --> KUBE-SEP-XXX
2.3.2 本机访问
OUTPUT --> KUBE-SERVICE --> KUBE-NODEPORTS --> KUBE-SVC-XXX --> KUBE-SEP-XXX
2.2.4 访问流程:
该服务的 nodePort 端口为 30070,其 iptables 访问规则和使用 clusterIP 方式访问有点类似,不过 nodePort 方式会比 clusterIP 的方式多走一条链 KUBE-NODEPORTS,其会在 KUBE-NODEPORTS 链设置 mark 标记并转发到 KUBE-SVC-5SB6FTEHND4GTL2W,nodeport 与 clusterIP 访问方式最后都是转发到了 KUBE-SVC-xxx 链。
- 1、经过 PREROUTING 转到 KUBE-SERVICES
- 2、经过 KUBE-SERVICES 转到 KUBE-NODEPORTS
- 3、经过 KUBE-NODEPORTS 转到 KUBE-SVC-5SB6FTEHND4GTL2W
- 4、经过KUBE-SVC-5SB6FTEHND4GTL2W 转到 KUBE-SEP-CI5ZO3FTK7KBNRMG 和 KUBE-SEP-VR562QDKF524UNPV
- 5、经过 KUBE-SEP-CI5ZO3FTK7KBNRMG 和 KUBE-SEP-VR562QDKF524UNPV 分别转到 192.168.137.147:7000 和 192.168.89.11:7000
// 1.
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
// 2.
......
-A KUBE-SERVICES xxx
......
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
// 3.
-A KUBE-NODEPORTS -p tcp -m comment --comment "pks-system/tenant-service:" -m tcp --dport 30070 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "pks-system/tenant-service:" -m tcp --dport 30070 -j KUBE-SVC-5SB6FTEHND4GTL2W
// 4、
-A KUBE-SVC-5SB6FTEHND4GTL2W -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-CI5ZO3FTK7KBNRMG
-A KUBE-SVC-5SB6FTEHND4GTL2W -j KUBE-SEP-VR562QDKF524UNPV
// 5、
-A KUBE-SEP-CI5ZO3FTK7KBNRMG -s 192.168.137.147/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-CI5ZO3FTK7KBNRMG -p tcp -m tcp -j DNAT --to-destination 192.168.137.147:7000
-A KUBE-SEP-VR562QDKF524UNPV -s 192.168.89.11/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-VR562QDKF524UNPV -p tcp -m tcp -j DNAT --to-destination 192.168.89.11:7000
2.3 iptables 模式问题分析
- iptables规则复杂零乱,真要出现什么问题,排查iptables规则必然得掉层皮。LOG+TRACE大法也不好使。
- iptables规则多了之后性能下降,这是因为iptables规则是基于链表实现,查找复杂度为O(n),当规模非常大时,查找和处理的开销就特别大。据官方说法,当节点到达5000个时,假设有2000个NodePort Service,每个Service有10个Pod,那么在每个Node节点中至少有20000条规则,内核根本支撑不住,iptables将成为最主要的性能瓶颈。
- iptables主要是专门用来做主机防火墙的,而不是专长做负载均衡的。虽然通过iptables的 statistic模块以及DNAT能够实现最简单的只支持概率轮询的负载均衡,但是往往我们还需要更多更灵活的算法,比如基于最少连接算法、源地址HASH算法等。而同样基于netfilter的ipvs却是专门做负载均衡的,配置简单,基于散列查找O(1)复杂度性能好,支持数十种调度算法。因此显然IPVS比iptables更适合做kube-proxy的后端,毕竟专业的人做专业的事,物尽其美。
2.4 最后
专注于大数据及容器云核心技术解密,可提供全栈的大数据+云原生平台咨询方案,请持续关注本套博客。如有任何学术交流,可随时联系。更多内容请关注《数据云技术社区》公众号。
