Cilium Masquerading podIP 问题记录
背景
在版本升级 cilium v1.8.1 到 v1.11.1 时,导致业务 pod 报错连接 mysql 授权错误,经过排查发现连接 mysql server 的 clientIP 是 业务 pod 所在的 nodeIP,而不是默认的 podIP,因为 mysql server 只授权了当前 K8s 集群的 pod cidr,所以报错授权问题。
矛盾点在于使用 cilium v1.8.1 时,出机器时的 IP 还是 podIP,但是 v1.11.1 却是 nodeIP,进一步发现 v1.8.2 版本也是 nodeIP。 K8s 网络这块采用的是 Cilium BGP 模式,podIP 在公司内网可达,所以希望的也是业务 pod 从当前节点出去 IP 应该是 podIP 才对,cilium 估计是做了 SNAT,把 podIP SNAT 成 nodeIP。
原因
原因在于 cilium 默认会做 podIP masq,可以参考官网文档 v1.8 :masquerading
我们部署的 cilium 配置里也配置了 masquerade: true
,实际上 cilium 会默认配置值为 true
:
masquerade: 'true'
enable-bpf-masquerade: 'true'
native-routing-cidr: 10.20.30.0/24
升级 cilium v1.11.1 时我们还是用的以上配置, cilium 新版本这个老配置 masquerade: true
已经废弃,改用 enable-ipv4-masquerade: true
, cilium 默认开启 podIP masquerade,见代码:daemon_main.go#L679-L680
所以升级 cilium v1.11.1 时需要改下配置就解决问题了:
enable-ipv4-masquerade: 'false'
enable-bpf-masquerade: 'false'
ipv4-native-routing-cidr: 10.20.30.0/24 # 新版本废弃 native-routing-cidr 配置,使用该配置,默认也是使用集群 pod cidr,和配置值 cluster-pool-ipv4-cidr 相同
为何 cilium v1.8.1 没有报这个问题? 尽管 cilium v1.8.1 我们使用的配置是 masquerade: true
,但是这个版本有个 bug,导致配置了也不起作用,podIP Masq 也不会走对应的 ebpf SNAT 规则, 在版本 v1.8.2 里修复了这个 bug,所以 cilium v1.8.2 之后默认都是开启 podIP Masq,尽管这个不是我们想要的。 bug 修复代码见:pull/12456
如果 pod 访问的目标 ip 在 ipv4-native-routing-cidr 网段内,也不会走 podIP Masq,ebpf c 代码里会判断如果在该网段内就跳过不走 masq 逻辑。 这样 pod 相互访问不会走 podIP Masq,只有访问集群外网络时才会这样。 ebpf c 代码跳过 ipv4-native-routing-cidr 网段逻辑见:
然后,包从容器出来,会经过 node 上 eth0 网卡,该网卡上下发了 ebpf SNAT 逻辑,会把 podIP SNAT 成 nodeIP,SNAT 逻辑代码函数见:
这里难点主要是如何使用 ebpf 代码去做 SNAT, cilium 这块代码值得学习,这里也是 cilium 核心逻辑之一。
最后,cilium 会把该 ebpf c 程序下发到 eth0 网卡 egress 出口侧(默认是 eth0 网卡,可以在 cilium daemon 里配置出口网卡), 可以在然后一台 K8s node 上执行以下命令看到 to-netdev
ebpf 程序,这里 to-netdev
可以理解为这块 ebpf c 程序的名字:
tc filter show dev eth0 egress
#filter protocol all pref 1 bpf chain 0
#filter protocol all pref 1 bpf chain 0 handle 0x1 bpf_netdev_eth0.o:[to-netdev] direct-action not_in_hw tag aed7375159f1f3a4
to-netdev ebpf c 程序可见,这是包从 eth0 网卡 egress 侧出去时走的逻辑:
同理,from-netdev ebpf c 程序是包进入 eth0 网卡 ingress 侧走的逻辑: bpf_host.c#L962-L987 , 这里主要是防火墙或者 BPF NodePort 才有用,比如我们这里的 podIP Masq 时 BPF NodePort 是开启的。
iptables snat masquerading
cilium 除了使用 ebpf 来实现 snat masq,也可以使用下发 iptables 规则来实现,可以见代码: iptables.go#L1097-L1137
可以修改 cilium 配置,然后使用命令 iptables -t nat -S CILIUM_POST_nat
查看:
enable-ipv4-masquerade: 'true'
enable-bpf-masquerade: 'false'
ipv4-native-routing-cidr: 10.20.30.0/24 # 新版本废弃 native-routing-cidr 配置,使用该配置,默认也是使用集群 pod cidr,和配置值 cluster-pool-ipv4-cidr 相同
下发的 iptables 规则类似如下:
iptables -t nat -S POSTROUTING
#-P POSTROUTING ACCEPT
#-A POSTROUTING -m comment --comment "cilium-feeder: CILIUM_POST_nat" -j CILIUM_POST_nat
#-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
#-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
iptables -t nat -S CILIUM_POST_nat
#-N CILIUM_POST_nat
#-A CILIUM_POST_nat -s 20.30.137.0/25 -m set --match-set cilium_node_set_v4 dst -m comment --comment "exclude traffic to cluster nodes from masquerade" -j ACCEPT
#-A CILIUM_POST_nat -s 20.30.137.0/25 ! -d 10.216.136.0/21 ! -o cilium_ -m comment --comment "cilium masquerade non-cluster" -j MASQUERADE
#-A CILIUM_POST_nat -m mark --mark 0xa00/0xe00 -m comment --comment "exclude proxy return traffic from masquerade" -j ACCEPT
#-A CILIUM_POST_nat -s 127.0.0.1/32 -o cilium_host -m comment --comment "cilium host->cluster from 127.0.0.1 masquerade" -j SNAT --to-source 20.30.137.116
#-A CILIUM_POST_nat -o cilium_host -m mark --mark 0xf00/0xf00 -m conntrack --ctstate DNAT -m comment --comment "hairpin traffic that originated from a local pod" -j SNAT --to-source 20.30.137.116
包走 netfilter POSTROUTING chain 时会首先跳到 CILIUM_POST_nat chain 走完该 chain 的所有 rules,再跳转到 KUBE-POSTROUTING chain 的所有 rules。 CILIUM_POST_nat chain 包含的 rules 如上,podIP Masq 的 rule 主要是这条,通过 iptables 很简单就能实现 podIP SNAT 成 nodeIP:
-A CILIUM_POST_nat -s 20.30.137.0/25 ! -d 10.216.136.0/21 ! -o cilium_ -m comment --comment "cilium masquerade non-cluster" -j MASQUERADE
当然,eBPF 因为会跳过 netfilter,包不必再去拷贝到内核里走 netfilter,性能相比 iptables 更高,所以还是使用 eBPF 来实现 podIP Masq,如果需要的话。 不过,eBPF 虽然性能高,但实现复杂。
与 calico 对比
calico 也有 podIP masq 成 nodeIP 的功能,见 Configure outgoing NAT , 可以通过参数 natOutgoing
配置:
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
cidr: 192.168.0.0/16
natOutgoing: true
我们生产 K8s 有少量的集群,容器网络插件用的是 calico,配置都是关闭的 natOutgoing: false
。calico 默认应该是下发 iptables 规则实现的 SNAT。
总结
cilium 默认使用 podIP Masq,这样当 pod 不是访问其他 pod 时,会把 podIP SNAT 为 nodeIP,尤其在 podIP 是私网不可达且访问集群外部资源时有用。 但是,由于我们采用 cilium BGP 模式,podIP 在公司内网可达,不需要这个功能,所以需要配置关闭。
另外,一个坑是我们配置一直没有关闭这个功能,所以配置一直都是错的,只是因为 cilium v1.8.1 自己的 bug,导致 podIP Masq 没有开启而已。
待调研
cilium podIP Masq ebpf 逻辑共用的 NodePort service 实现,可以调研下 cilium 如何实现 NodePort service?
参考文献
datapath: Enable BPF MASQ for veth mode in IPv4
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanffhgc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24