当前国内的信息技术的核心和标准大多数都由国外公司掌握和制定,因此存在诸多的安全风险。随着我国加快推进信息网络等新型基础设施建设、网络主权概念的逐步明确,信息技术应用创新产业已经成为当前信息化部署的关键词。我国正在大力推动*、国防、金融、交通等关键领域的信息化产品尽快实现国产化替代,并发布了多个重要政策来保障国产化的实施,加速实现信息核心技术的自主可控。
中国农业银行作为国有银行,是中国金融体系重要的组成部分,也是信创国产化布局的关键领域,在IT建设方面发展十分迅速,其中引入云计算平台基础设施来承载新建应用系统已经作为行内的一条刚性原则。信创国产化云的建设也是当下的重要任务,在云计算平台软件与国芯物理服务器、国产操作系统的适配方面也遇到不少的问题与挑战,下面就这个话题举几个典型的案例和大家分享一下。
农行信创云是采用容器及容器调度为核心技术栈的PaaS平台。容器引擎Docker、容器编排调度组件kubernetes和容器网络插件等整体运行于银河麒麟或者CentOS8操作系统之上。服务器方面采用基于海光x86和鲲鹏arm处理器的国产服务器。
案例1 基于国芯海光x86服务器安装Centos8操作系统,部署并运行Kubernetes网络插件flannel时出现跨服务器容器网络不通的现象。
现象:当我们完成基于海光服务器和CentOS8操作系统的kubernetes集群搭建时意外发现从集群外无法访问发布到集群的应用程序,使用同样的发布方式将应用程序发布到非国产化kubernetes集群上可以从集群外进行访问。环境信息如下:
操作系统:CentOSLinux 8
内核版本:4.18.0-147.el8.x86_64
kubernetes版本:1.17.4
flannel版本:0.11.0(vxlan模式)
分析:我们从集群外访问到应用程序的流量路径上逐步进行排查,最后发现跨服务器节点访问应用容器IP和服务端口不可达。集群采用flannel的vxlan模式提供容器网络服务,flannel会在每个集群节点上分配一个私有子网来分配该节点的容器IP,当跨节点容器互访时,源容器的数据包会通过vxlan隧道封装技术进行封装后再通过节点UDP4789端口发送到目标节点,完成解封装后送至目标容器。使用tcpdump对flannel的UDP4789端口抓包发现,每个UDP数据包都会出现下图所示的bad udp cksum并且该数据包被丢弃。
措施:查阅网上相关技术资料发现这个现象是由服务器网卡Checksum offloading引起的。这项功能旨在如果内核想通过物理网卡向外发送数据包时可以让硬件网卡代替CPU来完成checksum计算,以节省CPU资源。如果网卡支持,可以设置对发送Tx或接收Rx有效,或者两者都有效。临时的解决方案是关闭flannel网络接口的Tx checksum功能,通过sudo ethtool -K flannel.1 tx-checksum-ip-generic off命令关闭。可以通过sudo ethtool -k flannel.1查询当前checksum是否有效,如下图所示,可以看到tx-checksumming状态是off。
当然这并没有根本解决问题,从kubernetes社区上反馈的情况来看是由于kernel packetchecksum 的bug以及kubernetes的kube-proxy组件设置Iptables策略时引发的内核double-NAT进而设置了错误的checksum值的问题碰到一起就会出现vxlan跨节点网络丢包的现象,两者解决一个都可以解决此问题,详细内容可以具体参考以下链接:
https://github.com/coreos/flannel/issues/1279
https://github.com/kubernetes/kubernetes/pull/92035
一方面对于kernel的bug尚未查到明确的fixed版本,对于海光芯片的服务器来说我们是通过升级网卡驱动程序来解决的,服务器网卡为网讯的Ethernet Controller RP2000,升级驱动程序及版本为kmod-ngbe-1.0.4-1.el8.x86_64和kmod-txgbe-1.1.12-1.el8.x86_64,这个解决方法只针对网讯的这款网卡,另一方面在kubernetes(v1.16.13、v1.17.9、v1.18.6)版本中对进行了修复。请参考以下链接中针对PR#92035修复的说明:
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.18.md#changelog-since-v1185
案例2 基于国芯海光x86和鲲鹏arm服务器安装银河麒麟V10操作系统,部署并运行Kubernetes网络插件flannel时出现跨服务器容器网络不通的现象。
现象:当我们完成基于海光、鲲鹏服务器和银河麒麟V10操作系统的kubernetes集群搭建时,跨节点容器网络测试不通。环境信息如下:
操作系统:KylinLinux Advanced Server V10 (Tercel)
内核版本:4.19.90-17.ky10.x86_64
kubernetes版本:1.17.4
flannel版本:0.11.0(vxlan模式)
分析:参考案例1中的经验使用tcpdump对flannel的UDP4789端口抓包发现每个UDP数据包并没有出现bad udp cksum并且该数据包没有被丢弃,目标节点可以收到UDP包,但是只能接收到TCP连接第一次握手包,没有返回ACK,抓包信息如下:
UDP包进入目标节点后会通过路由表路由至cni0的网桥上,进而进入目标容器,对cni0设备抓包没有发现数据包流入,查询主机路由表,其中存在至cni0的路由条目,查询iptables表、ipvs表和非麒麟操作系统相比也未发现异常。排查方向转向flannel,开启flannel debug级别日志,启动过程中发现flannel会创建一个flannel.1的网卡,同时会将该卡的MAC地址以注释方式写入k8s节点信息中和主机FDB中,排查要点如下:
1.flannel将生成的flannel.1的MAC地址注释在节点信息中。
2.其他节点的flannel将此MAC地址写入本机的FDB中。
3.在操作系统层查询flannel.1的MAC地址。
复盘整个flannel启动过程发现银河麒麟节点信息中的MAC地址与FDB中的MAC地址一致,和服务器上观察flannel.1的网卡MAC不一致,这样就可以解释为什么无法正常建立跨节点的TCP链接。通过ip monitor观察flannel.1网卡的启动过程发现该网卡被赋了两次MAC地址,第一次为flannel进程赋值,第二次是操作系统赋值。复现方法可以手动删除flannel.1网卡后重新启动flannel容器,同时用ip monitor捕捉事件:
相应的flannel组件写入节点注释信息和FDB的MAC地址:
操作系统层观察到的flannel网卡MAC地址:
措施:解决方法为创建/usr/lib/systemd/network/10-flannel.link文件,在文件内设置flannel*网卡的MACAddressPolicy=none,也就是对flannel.1设置例外不进行MAC生成并赋值,这样在flannel启动时保证flannel.1网卡、FDB、节点信息中的MAC地址的一致,通过测试容器网络跨节点通信恢复正常。以下为10-flannel.link文件内容: