一次“不负责任”的 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/
一次“不负责任”的 K8s 网络故障排查经验分享的更多相关文章
- golang 服务诡异499、504网络故障排查
事故经过 排查 总结 事故经过 11-01 12:00 中午午饭期间,手机突然收到业务网关非200异常报警,平时也会有一些少量499或者网络抖动问题触发报警,但是很快就会恢复(目前配置的报警阈值是5% ...
- Linux 网络故障排查
1.第一步是要确认网卡本身是否工作正常?利用ping工具可以确认这点.输入ping 127.0.0.1 ,然后看是否正常ping 通? 这里的127.0.0.1 被称作主机的回环接口,是TCP/IP协 ...
- Linux网络故障排查
1.先排查网络配置信息 IP地址->子网掩码->网关->DNS 2.查看到达的网关是否连通 ping IP地址. 3.查看DNS解析是否正常.
- Linux 学习之网络故障排查
1.ping www.baidu.com 查看高速有没有修通,如果通,但还不能上网:可能是浏览器.中毒等问题2.ping 网关(10.0.0.254),目的是排除物理链路(网线,网卡,驱动,IP设置等 ...
- NO31 配置网卡--主机名--网络故障排查面试题--DNS
修改网卡配置信息: 修改主机名规范的三个步骤: 配置默认网关: DNS解析过程,用命令看: DNS相关命令: 口述DNS解析过程: 客户端(电脑)通过浏览器输入域名,先找hosts文件及本地dns缓 ...
- 通过Microsoft Azure服务设计网络架构的经验分享(转)
原文:http://www.infoq.com/cn/articles/azure-networking-tips 本文从产品设计和架构角度分享了 Microsoft Azure 网络服务方面的使用经 ...
- 通过Microsoft Azure服务设计网络架构的经验分享
作者 王枫 发布于 2014年4月8日 本文从产品设计和架构角度分享了Microsoft Azure网络服务方面的使用经验,希望你在阅读本文之后能够了解这些服务之间,从而更好地设计你的架构. Mic ...
- [ASP.NET]大文件无法上传排查经验分享
最近我们标桥下载模块,在经过正常更新后,发现软件包无法上传. 临时解决方案 因为问题结点在于文件无法上传到服务器,所以我们临时手动将文件丢到服务器,通过测试服务器将数据造出来,然后再更新到正式数据库, ...
- 1个工具,助你提升K8S故障排查效率!
Kubernetes的故障排查一直困扰众多运维团队或DevOps,除了Kubernetes本身的复杂性之外,还有Kubernetes的工作负载是动态的原因.本文将介绍1个工具可以帮助你可视化K8S的网 ...
随机推荐
- dhcpd:bad subnet number/mask combination. subnet
今天在调试wifi热点启动hdcpd服务时出现报错"bad subnet number/mask combination. subnet 192.168.1.1", Interne ...
- 二叉树中和为某一值的路径 牛客网 程序员面试金典 C++ Python
二叉树中和为某一值的路径 牛客网 程序员面试金典 题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一 ...
- Python 字符串的encode与decode
python的str,unicode对象的encode和decode方法 python中的str对象其实就是"8-bit string" ,字节字符串,本质上类似java中的byt ...
- 如何选择普通索引和唯一索引《死磕MySQL系列 五》
系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...
- Oracle 相关命令
http://www.mamicode.com/info-detail-2481866.html sql语句 system用户登陆 查看表空间和存放位置 select t1.name,t2.name ...
- HttpClient用法--这一篇全了解(内含例子)
HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅使客户端发送Http请求变得容易,而且也方便开发人员测试接口(基于Http协议的),提高了开发的效率,也 ...
- js中function (res) {}与(res) =>{}的区别
这里是引用function (res) {} 中 打印this时是undefined 打印that时是有内容的 let that = this; ...
- 动态代理中newProxyInstance中三个参数
JDK Proxy(代理对象): Proxy.newProxyInstance 方法的三个参数创建代理对象 增强 person对象 使用代理对象代替person 去执行 doCourt方法参数1 类 ...
- Flask搭建弹幕视频网站(1)
说在前面 也不知道最后能不能完成网站,所以就想把这十多天来学习到的点点滴滴记录下来.学的越来越多,所谓全栈也是需要前端基础,越来越感受到压力,但是遇到一个问题就解决一个问题,慢慢习惯之后感觉也还行.说 ...
- 菜鸡的Java笔记 图书馆
图书大厦 开发要求 现在要求模拟一个图书大厦图书管理的程序结构,可以在图书大厦实现某一类图书的上架操作,下架操作,以及关键字模糊查询的操作 注 ...