乐趣区

关于云原生:一次不负责任的-K8s-网络故障排查经验分享

作者 | 骆冰利
起源 | Erda 公众号

某天早晨,客户碰到了这样的问题:K8s 集群始终扩容失败,所有节点都无奈失常退出集群。在通过多番折腾无解后,客户将问题反馈到咱们这里,心愿失去技术支持。该问题的整个排查过程比拟有意思,本文对其中的排查思路及所用的办法进行了演绎整顿并分享给大家,心愿可能对大家在排查此类问题时有些帮忙和参考。

问题景象

运维同学在对客户的 K8s 集群进行节点扩容时,发现新增的节点始终增加失败。初步排查后果如下:

  • 在新增节点上,拜访 K8s master service vip 网络不通。
  • 在新增节点上,间接拜访 K8s master hostIP + 6443 网络失常。
  • 在新增节点上,拜访其余节点的容器 IP 能够失常 ping 通。
  • 在新增节点上,拜访 coredns service vip 网络失常。

该客户应用的 Kubernetes 版本是 1.13.10,宿主机的内核版本是 4.18(centos 8.2)。

问题排查过程

收到该一线共事的反馈,咱们曾经初步狐疑是 ipvs 的问题。依据以往网络问题排查的教训,咱们先对现场做了些惯例排查:

  • 确认内核模块 ip_tables 是否加载(失常)
  • 确认 iptable forward 是否默认 accpet(失常)
  • 确认宿主机网络是否失常(失常)
  • 确认容器网络是否失常(失常)

排除了惯例问题后,根本能够放大范畴,上面咱们再持续基于 ipvs 相干层面进行排查。

1. 通过 ipvsadm 命令排查

10.96.0.1 是客户集群 K8s master service vip。

如上图所示,咱们能够发现存在异样连贯,处于 SYN_RECV 的状态,并且能够察看到,启动时 kubelet + kube-proxy 是有失常建连的,阐明是在启动之后,K8s service 网络呈现了异样。

2. tcpdump 抓包剖析

两端进行抓包,并通过 telnet 10.96.0.1 443 命令进行确认。

论断:发现 SYN 包在本机没有发送进来。

3. 初步总结

通过下面的排查,咱们能够再次放大范畴:问题根本就在 kube-proxy 身上。咱们采纳了 ipvs 模式,也依赖了 iptables 配置实现一些网络的转发、snat、drop 等。

依据下面的排查过程,咱们又一次放大了范畴,开始剖析怀疑对象 kube-proxy。

4. 查看 kube-proxy 日志


如上图所示:发现异常日志,iptables-restore 命令执行异样。通过 Google、社区查看,确认问题。

相干 issue 链接可参考:

  • https://github.com/kubernetes/kubernetes/issues/73360
  • https://github.com/kubernetes/kubernetes/pull/84422/files
  • https://github.com/kubernetes/kubernetes/pull/82214/files

5. 持续深刻

通过代码查看(1.13.10 版本 pkg/proxy/ipvs/proxier.go:1427),能够发现该版本的确没有判断 KUBE-MARK-DROP 是否存在并创立的逻辑。当呈现该链不存在时,会呈现逻辑缺点,导致 iptable 命令执行失败。

K8s master service vip 不通,理论容器相干的 ip 是通的,这种状况呈现的起因,与上面的 iptable 规定无关:

iptable -t nat -A KUBE-SERVICES ! -s 9.0.0.0/8 -m comment --comment "Kubernetes service cluster ip + port for masquerade purpose" -m set --match-set KUBE-CLUSTER-IP dst,dst -j KUBE-MARK-MASQ

6. 根因探索

后面咱们曾经晓得了 kube-proxy 1.13.10 版本存在缺点,在没有创立 KUBE-MARK-DROP 链的状况下,执行 iptables-restore 命令配置规定。然而为什么 K8s 1.13.10 版本跑在 centos8.2 4.18 内核的操作系统上会报错,跑在 centos7.6 3.10 内核的操作系统上却失常呢?

咱们查看下 kube-proxy 的源码,能够发现 kube-proxy 其实也就是执行 iptables 命令进行规定配置。那既然 kube-proxy 报错 iptables-restore 命令失败,咱们就找一台 4.18 内核的机器,进入 kube-proxy 容器看下状况。

到容器内执行下 iptables-save 命令,能够发现 kube-proxy 容器内的确没有创立 KUBE-MARK-DROP 链(合乎代码预期)。持续在宿主机上执行下 iptables-save 命令,却发现存在 KUBE-MARK-DROP 链。

这里有两个疑难:

  • 为什么 4.18 内核宿主机的 iptables 有 KUBE-MARK-DROP 链?
  • 为什么 4.18 内核宿主机的 iptables 规定和 kube-proxy 容器内的规定不统一?

第一个纳闷,凭感觉狐疑除了 kube-proxy,还会有别的程序在操作 iptables,持续撸下 K8s 代码。
论断:发现的确除了 kube-proxy,还有 kubelet 也会批改 iptables 规定。具体代码能够查看:pkg/kubelet/kubelet_network_linux.go

第二个纳闷,持续凭感觉······Google 一发捞一下为何 kube-proxy 容器挂载了宿主机 /run/xtables.lock 文件的状况下,宿主机和容器 iptables 查看的规定不统一。
​论断:CentOS 8 在网络方面摒弃 iptables,采纳 nftables 框架作为默认的网络包过滤工具。

至此,所有的谜团都解开了。

团队实现过大量的客户我的项目交付,这里有些问题能够再解答下:​

  • 问题一:为什么这么多客户环境第一次碰到该状况?

因为须要 K8s 1.13.10 + centos 8.2 的操作系统,这个组合常见,且问题必现。降级 K8s 1.16.0+ 就不呈现该问题。

  • 问题二:为什么应用 K8s 1.13.10 + 5.5 内核却没有该问题?

因为与 centos 8 操作系统无关,咱们手动降级 5.5 版本后,默认还是应用的 iptables 框架。

能够通过 iptables -v 命令,来确认是否应用 nftables。

题外话:nftables 是何方神圣?比 iptables 好么?这是另一个值得进一步学习的点,这里就不再深刻了。

总结与感悟

针对以上的排查问题,咱们总结下解决办法:

  • 调整内核版本到 3.10(centos 7.6+),或者手动降级内核版本到 5.0 +;
  • 降级 Kubernetes 版本,以后确认 1.16.10+ 版本没有该问题。

以上是咱们在进行 Kubernetes 网络故障排查中的一点教训,心愿可能对大家高效排查,定位起因有所帮忙。

如果对于 Erda 我的项目你有其它想要理解的内容,欢送 增加小助手微信(Erda202106)退出交换群!

欢送参加开源

Erda 作为开源的一站式云原生 PaaS 平台,具备 DevOps、微服务观测治理、多云治理以及快数据治理等平台级能力。点击下方链接即可参加开源 ,和泛滥开发者一起探讨、交换,共建开源社区。 欢送大家关注、奉献代码和 Star!

  • Erda Github 地址:https://github.com/erda-project/erda
  • Erda Cloud 官网:https://www.erda.cloud/
退出移动版