记一次 Kubernetes 网络故障深度追踪

标签: kubernetes 网络 深度 | 发表时间:2021-05-22 14:20 | 作者:aoxiang
出处:http://weekly.dockone.io

某天晚上,客户碰到了 Kubernetes 集群一直扩容失败,所有的节点都无法正常加入集群。在经过多番折腾无解后,反馈到我们这里进行技术支持。这个问题的整个排查过程比较有意思,所以对其中的排查思路和用到的方法进行整理分享。

问题现象

运维同学在对客户的 Kubernetes 集群进行节点扩容时,发现新增的节点一直添加失败。该同学进行了初步的排查如下:
  • 在新增节点上,访问 Kubernetes master service vip 网络不通
  • 在新增节点上,直接访问 Kubernetes master hostIP + 6443 网络正常
  • 在新增节点上,访问其他节点的容器 IP 可以正常 ping 通
  • 在新增节点上,访问 coredns service vip 网络正常


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

问题排查过程

收到该一线同事的反馈,我们已经初步怀疑是 IPVS 的问题。根据以往网络问题排查的经验,先对现场做了些常规排查:
  • 确认内核模块 ip_tables 是否加载(正常)
  • 确认 iptable forward 是否默认 accpet (正常)
  • 确认宿主机网络是否正常(正常)
  • 确认容器网络是否正常(正常)
  • ……


排除了常规的问题之后,基本可以缩小范围,再继续基于 IPVS 相关层面进行排查。

通过 ipvsadm 命令排查

10.96.0.1 是客户集群 Kubernetes master service vip。

可以发现有异常连接,处于 SYN_RECV 的状态,并且可以观察到,启动时 kubelet + kube-proxy 是有正常建连的,说明是在启动之后,Kubernetes service 网络出现异常。

tcpdump 抓包分析

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

结论:发现 SYN 包在本机没有发送出去。

初步总结

通过上面的排查,可以再次缩小范围,问题基本就在 kube-proxy 身上。我们采用了 IPVS 模式,也会依赖了 iptables 配置实现一些网络的转发、SNAT、drop 等等。

根据上面的排查过程,我们又缩小了范围,开始分析怀疑对象 kube-proxy。

查看 kube-proxy 日志


发现异常日志,iptables-restore 命令执行异常。通过 Google、社区查看,确认问题。

相关 issue 链接可以参考下:


继续深入

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

Kubernetes 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  

根因探究

前面我们已经知道了 kube-proxy 1.13.10 版本存在缺陷,在没有创建 KUBE-MARK-DROP 链的情况下,执行 iptables-restore 命令配置规则。但是为何 Kubernetes 1.13.10 版本跑在 CentOS 8.2 4.18 内核的操作系统上会报错,跑在 CentOS 7.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,继续撸下 Kubernetes 代码。

结论:发现确实除了 kube-proxy,还有 kubelet 也会修改 iptables 规则。具体代码可以查看 pkg/kubelet/kubelet_network_linux.go

第二个疑惑,继续凭感觉吧。Google 一发捞一下为何 kube-proxy 容器挂载了宿主机 /run/xtables.lock 文件的情况下,宿主机和容器 iptables 查看的规则不一致。

结论:CentOS 8 在网络方面摒弃 iptables 采用 nftables 框架作为默认的网络包过滤工具。

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

团队完成过大量的客户项目交付,还是有些问题可以再解答下:

问题一:为何这么多客户环境第一次碰到该情况?因为需要 Kubernetes 1.13.10 + centos 8.2 的操作系统,这个组合罕见,且问题是必现。升级 Kubernetes 1.16.0+ 就不会有该问题。

问题二:为何使用 Kubernetes 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+ 版本没有该问题。


原文链接: https://zhuanlan.zhihu.com/p/364382294

相关 [kubernetes 网络 深度] 推荐:

记一次 Kubernetes 网络故障深度追踪

- - DockOne.io
某天晚上,客户碰到了 Kubernetes 集群一直扩容失败,所有的节点都无法正常加入集群. 在经过多番折腾无解后,反馈到我们这里进行技术支持. 这个问题的整个排查过程比较有意思,所以对其中的排查思路和用到的方法进行整理分享. 运维同学在对客户的 Kubernetes 集群进行节点扩容时,发现新增的节点一直添加失败.

Kubernetes Service iptables 网络通信验证

- - 三点水
Kubernetes gives Pods their own IP addresses and a single DNS name for a setof Pods, and can load-balance across them.. K8s Service会为每个 Pod 都设置一个它自己的 IP,并为一组 Pod 提供一个统一的 DNS 域名,还可以提供在它们间做负载均衡的能力.

使用 Cilium 增强 Kubernetes 网络安全

- - IT瘾-dev
在本篇,我们分别使用了 Kubernetes 原生的网络策略和 Cilium 的网络策略实现了 Pod 网络层面的隔离. 不同的是,前者只提供了基于 L3/4 的网络策略;后者支持 L3/4、L7 的网络策略. 通过网络策略来提升网络安全,可以极大降低了实现和维护的成本,同时对系统几乎没有影响. 尤其是基于 eBPF 技术的 Cilium,解决了内核扩展性不足的问题,从内核层面为工作负载提供安全可靠、可观测的网络连接.

在 Kubernetes 上部署一个深度学习模型

- - Linux 中国◆开源社区
了解如何使用 Kubermatic Kubernetes 平台来部署、扩展与管理图像识别预测的深度学习模型. 随着企业增加了对人工智能(AI)、机器学习(ML)与深度学习(DL)的使用,出现了一个关键问题:如何将机器学习的开发进行规模化与产业化. 这些讨论经常聚焦于机器学习模型本身;然而,模型仅仅只是完整解决方案的其中一环.

调试Kubernetes集群中的网络停顿问题

- - DockOne.io
我们曾经在这里中聊起过Kubernetes ( Kubernetes at GitHub : https://github.blog/2017-08-16. ithub/),在过去几年,Kubernetes在Github已经成为标准的部署模式. 目前在Github,我们在Kubernetes上运行着海量的面向内部团队以及面向C端的服务.

kubernetes NodePort网络踩坑 - 三木燕 - 博客园

- -
系统:centos7.6     . IP地址:192.168.1.1. 因为需要跑一个nginx的应用叫做http-proxy做流量转发,公网入口是阿里云的SLB然转发到http-proxy的NodePor 端口上,也就是192.168.1.1:30285. 刚配好一切正常,过了几分钟SLB开始报健康检查错误,手动检查了一下发现3、4请求之后必然会有一次timeout.

Kubernetes容器网络及Flannel插件详解

- - 掘金 后端
这是我参与「掘金日新计划 · 6 月更文挑战」的第2天, 点击查看活动详情. Kubernetes是一个开源容器调度编排引擎,管理大规模容器化应用,采用典型的Master-Worker主从分布式技术架构,由集中式管理节点(Master Node),分布式的工作节点(Worker Node)组成. 向下屏蔽底层差异化的分布式基础设施,以应用为中心构建云计算的基础操作系统能力(即云原生操作系统),面向用户提供云原生时代的云计算的新界面.

Kubernetes网络难懂?快来看这篇文章

- - IT瘾-dev
Kubernetes 是为运行分布式集群而建立的,分布式系统的本质使得网络成为 Kubernetes 的核心和必要组成部分,了解 Kubernetes 网络模型可以使你能够正确运行、监控和排查应用程序故障. 网络是非常复杂的,拥有许多概念,对于不熟悉这个领域的用户来说,这可能会有一定的难度,这里面有很多概念需要理解,并且还需要把这些概念整合起来形成一个连贯的整体,比如网络命名空间、虚拟接口、IP 转发、NAT 等概念.

Kubernetes & Microservice

- - 午夜咖啡
这是前一段时间在一个微服务的 meetup 上的分享,整理成文章发布出来. 谈微服务之前,先澄清一下概念. 微服务这个词的准确定义很难,不同的人有不同的人的看法. 比如一个朋友是『微服务原教旨主义者』,坚持微服务一定是无状态的 http API 服务,其他的都是『邪魔歪道』,它和 SOA,RPC,分布式系统之间有明显的分界.

Kubernetes学习(Kubernetes踩坑记)

- - Z.S.K.'s Records
记录在使用Kubernetes中遇到的各种问题及解决方案, 好记性不如烂笔头. prometheus提示 /metrics/resource/v1alpha1 404. 原因: 这是因为[/metrics/resource/v1alpha1]是在v1.14中才新增的特性,而当前kubelet版本为1.13.