cilium-chain和ipip包
概述
公司测试环境的集群部署 cilium-chain 之后,会导致配置了 ipip tunnel 的容器,无法响应办公网客户端经过 vgw 访问容器的请求。表现为虽然已经将容器 IP 负载均衡的 vip,但办公网环境先通过 vip 无法 curl 通注册的端口。
问题分析
经过运维同事排查,在 Pod 内部无法抓到包,在 Pod 的宿主机上可以抓到经过负载均衡发送的 ipip 协议封装的网络包。
|
|
经过推断是因为 cilium-agent 通过 chain 方式,会将 ebpf 程序绑定到容器网卡,通过卸载 cilium 的方式验证发现,确实可以访问成功,说明是 cilium 创建的 ebpf 影响了容器网卡正常处理经过 vgw 过来的网络包。cilium-agent 加载 ebpf 程序以及客户端、vgw、Pod之前的访问路径见下图。其中 cil_from_container-vvport959 主要会在外部的网络包到达容器网卡 vvport959 之后的 hook 点进行处理,cil_to_container-vvport959 是在容器将网络包从 vvport959 往外发送的时候的 hook 点。
源码分析
先分析 cil_from_container-vvport959 的代码逻辑,简单来说,正常情况下,cilium 在 cil_from_container-vvport959 处理包的时候,会打开网络包的协议层直到 tcp 层之后,获取 ip 和 port 信息,创建 cilium 内部维护的 conntrack 表,详见下面的代码调用关系。
|
|
正常情况下 cilium 的处理罗就是,查看一个 ip 包的下一层协议,除开代码里写好的相关协议,其他协议默认会丢弃,在我们的 case 下,cilium 打开查看 ip 层之后的协议头还是 ip 协议,这样 cilium 会直接 Drop 处理,这个也可以在 cilium monitor 上看到 DROP_CT_UNKNOWN_PROTO 这样的信息。
|
|
正常情况下从 cilium monitor 可以看到正常的 IP 包再到 TCP 包的过程,然后 conntrack 表记录创建成功,状态转为 new。
|
|
为了解决上面的情况,目前的方案是在创建 conntrack 表记录之前,判断如果是 IPIP 协议的包,直接 return CTX_ACK_OK,这样就跳过了创建 conntrack 表的过程,直接回到内核,这样容器网卡就可以接到 vgw 的 IPIP 包了。解决了网络包进入容器之后,再进行测试,发现又遇到了网络包从容器网卡出去的问题。通过 cilium monitor 可以看到下面的信息。
|
|
reason Invalid source ip,这次还是被 Drop 了,但是是另外的理由,大概就是 source ip 不是有效的容器 ip,或者是 cilium 不认识的 ip。从代码里跟踪这个错误代码的产生,简单梳理了容器网络包经过 cil_to_container-vvport959 发出的过程。
|
|
简单来说,is_valid_lxc_src_ipv4 是用来判断 IP 包的 src ip 是否为 cilium 记录下来的 LXC_IPV4 也就是容器 ip,很显然,在我们的场景里,肯定不是,因为此时我们的 src ip 为 vgw 的 vip,cilium 并不认识这个 vip,于是在 cilium 就把整个包丢弃了。为了解决这个问题,我们查看代码之后,发现 ENABLE_SIP_VERIFICATION 这个参数在当前的版本中被写死成 true,那么改成 false 之后,跳过这个检查,这种包就能发出去了。
问题总结
通过修改 cilium 的源码,可以让 cilium 支持 vgw 的 ipip 协议头的网络包,以上的改动都比较小,至少应该不影响正常的容器网络,但是以上的改动,导致 vgw ip 是可以跳过 cilium 的网络的安全策略,这样会影响我们在生产环境中,关于数据库相关的访问策略的配置,如何更既能让 cilium 支持 vgw 的 ipip 协议的处理,又能让 vgw 的 ip 也能够被 cilium 的网络策略覆盖还需要更多的工作。