从一次IPVS故障开始的Kubernetes容器网络排障

TL; DR:

问题现象是集群运行一段时间后kube-proxy停止更新IPVS规则,这个问题是由一个存在于1.11.5/1.12.2/1.13.0版本中的bug造成的。并在以下版本中得到了修复,可以查看kubernetes/kubernetes#71071了解更多信息。

  • 1.11.7
  • 1.12.5
  • 1.13.2

另一方面,也可以通过将未修复版本的kube-proxy设置为iptables模式来规避这个问题。

开始讲故事

最近有两个新平台部署,第一次在线上启用了很多新方案。包括Master高可用,LVS,持久化存储,Prometheus监控。本以为在测试环境已经正常跑了一个月的方案理当顺风顺水,结果PoC的第二天就出了一些问题。

问题最初的现象是局部网络不通,一些模块之间的连接出现了问题,exec到容器上,nmap扫描对端端口,发现竟然是filtered的,然而在对端容器里扫描自身却是Open的。显然是容器器网络出现了一些问题。

回想一下K8s中容器通信都会经过什么,在我的方案中,CNI插件采用了Calico,而kube-proxy则是开启了IPVS模式。在容器网络的构建中,CNI和kube-proxy两者都有参与。

CNI插件的任务是在容器开启时为容器分配IP,并为这个IP构建虚拟设备,另外,CNI插件也负责将容器间通信的协议包(如TCP/UDP等)从K8s集群中的任意一台机器转发到指定容器所在的机器上,再转发到指定容器上,在Calico方案中,这是通过N条主机路由(N=cali虚拟网卡数量)和M条tunl0上的直接路由(M=该K8s集群节点数量)实现的。

首先尝试了排除CNI的问题,CNI很好排查,只需要记录各个节点上容器的IP(每个节点记一个IP即可)然后在各个节点上Ping这些IP,如果都能Ping通,那CNI插件的工作就是完全正常的。

运行的结果是排除了CNI的问题。

随后,由于第一次使用nmap扫描对端端口时, 使用的是Cluster IP,也即是Service的IP,而ClusterIP到Pod IP之间只夹着一条LVS负载均衡规则(或者如果kube-proxy使用默认配置,则是iptables规则),既然Pod IP的连通性没有问题,那大概率是IPVS规则出现了问题。查询现有的IPVS规则,就发现了只有virtual server endpoint而没有real server的IPVS规则:

至此可以确定是由于缺少IPVS规则来将到达service的流量负载均衡到Pod上导致了这个问题。而IPVS规则是由kube-proxy维护的,打开kube-proxy的日志,发现了报错:

参考修复该问题的PR中的解释,原因是 kube-proxy中两个goroutine同时调用libipvs产生了死锁,新版本在对libipvs的调用上加了锁。

至于为什么直到在线上PoC部署的时候才遇到这个问题,主要原因还是在线下测试的不够多,使用量大的集群只更新了1.13.0,但从没有开启过IPVS,而同时升级了1.13.0并且开启IPVS的测试集群都非常的短命,也就没有机会等到这个问题出现。

文章已创建 8

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部