K8S 集群无法通过 Service Name 访问的故障
一、前言
微服务环境下,服务发现、负载均衡、健康检查以及必要的服务治理措施都依赖于注册中心,如果将整套环境迁移到 k8s 上,那么注册中心的存留就值得一番思考了。
如果我们像一线大厂那种单元化架构搞异地多活,那么注册中心是必须是单独的存在,注册中心是指哪打哪,灾备、单元化负载均衡,动态单元化切流,一旦脱离了注册中心,整个体系是玩不转的;
但是如果你只是用注册中心做服务发现和负载均衡的话,那么注册中心真的是可有可无。
因此中小系统的架构下,将服务迁移到 k8s 里,用 service name 去做服务间的调用就是一种低成本的服务发现策略。
通过 service name,其实背后的体系还是 k8s 的 dns(kube dns/core dns)总之 service name 就是 k8s 内的一套名字服务。假如 kp-id 命名空间内存在一个 service 名为 user-info-svc 的 service,那么其在集群中的完整 A 记录为:
如果是在同一个命名空间则可以直接以 user-info-svc 访问其背后的 pod。
此处 user-info-svc 起到了服务发现和负载均衡的作用,而且是高可用的,其背后的机制是 kube-proxy 来维系 iptables 或者 ipvs 来实现,是由内核直接支持的。
因此服务可以使用该 service name,将其当成域名来使用。这套机制和阿里的 vipserver 是类似的。
二、故障
有个线下集群,存在很多命名空间部署了很多服务,但是发现某些服务调用其他服务的时候报无法解析 service name:
注意,该种提示和以下的错误提示的原因是完全不同的:
“Unknown host ruleengine-for-admin”代表查询 dns 但是 dns 没有查到,说明 dns 的链路是正常的,但是图 1 的提示则完全不是,代表没有 dns 服务。
由于是代表没有 dns 服务,那么去排查 dns 的问题,找到 dns 的 ClusterIP,ping 一下:
同时检查端口是否有 listen:
看来服务是正常的。那么就需要全链路的排查一下从 pod 到 kube-dns 整个过程中有什么问题。
三、DNS 解析链路排查
首先创建一个 DNS 诊断工具的 pod:
使用该 pod 检测:
发现没有问题,排除。
然后检查本地 dns 配置文件:
发现 search 域也没有问题。排除。
然后再检查 dns 的 pod 有无问题:
Dns 正常 ready 状态。排除
DNS 的 Endpoints:
代表 dns 的 service name 的 pod,有时候 service 创建成功,但是其背后的 pod 并未和 service 关联上,也就是 service 并没有 Endpoints,describe 一下 dns service 同样可以检查:
同样没有问题,排除掉。
下面就要看 dns 服务具体是怎么回事了,修改 dns 的配置,调整日志开关,打印日志:
观察了一会,并且重建 service 和 pod,未发现明显的报错信息:
四、焦虑
排查到此,发现 DNS 是正常的,而且意外发现,有些 service 是可以解析,有些却不能解析,这个很奇怪,集中看了下不能解析 service 的 pod,发现这些 pod 都在某一台 worker 上:
这个 worker 是几天前新加入的节点,集群的资源不够了,临时扩容了一下,难道是这个节点有问题吗?可是刚扩容之后是好的,经询问得知,该节点刚刚死机了一次重启过。回顾了下时间点,恰好是重启之后就出现了该问题。
检查了一下 kube-proxy 等相关进程都没有问题,此时陷入了沉思。
又将 proxy mode 从 iptables 和 ipvs 间切换了几次,将 worker 驱逐重建等,依然不好使。
查阅了很多资料,有指出是 ipv6 的问题,也有指出是 1.18 版本对 ipv6 支持不好,需要升级 linux 内核等措施,但是分析下来,依然觉得不像是,首先这个 worker 内核的版本是和其他节点相同的,没理由只是这个节点不兼容。
五、解决
又分析了一下,dns 没有问题,会不会是网络的问题呢?是否是在链路层面?于是将关注点意向了网络插件,于是扫了一下 calico,发现 41 节点上的 calico 重启的次数毕竟多,而且若干次之后偶尔就绪偶尔没有就绪:
之前其实检查过 calico,但是由于习惯的看是否 是 Running,忽略了是否就绪,而且有时候就绪的状态瞬间就没了,印象中没有发现它的问题就直接略过了,因此一直没有注意 calico,而且最开始就尝试在 pod 内是可以 ping 通 dns service 的 IP 的,因此没有考虑是网络问题。
看了下 Caliao 的日志:
原来是 Calico 并没有在本地网卡上绑定成功,没有 ready,从而没有构建起 BGP 网络。
这个的原因没有深入分析,大致分析下有可能是 41 这个机器上启动了一个 docker,以单机及 compose 的方式运行了一些中间件。导致 Calico 在初始化的时候错误的绑定了网卡,没有构建起正常的三层路由网络。
于是,将 Calico 的配置改一下,使用静态网卡绑定,强制绑定到 eth3 这个网卡上:
然后将 kube-rpxy 删除,calico 删除重建,发现依然不行:
提示 eth3 处于 down 的状态,查看了下 41 的网卡设备,发现并无 eth3 的网卡,原来该机器和其他机器的网卡名称不同。
将网卡名称更改为 eth3 解决:
Calico 顺利启动:
六、总结
该问题的原因是 Calico 的三层路由网络构架失败导致,因此也表现为被调度到该 node 上的 pod 无法解析 service,失败的原因可能是该节点上本来就存在的 docker 构建的 bridge 网络对 Calico 产生了干扰,导致 Calico 初始化失败,最后通过静态绑定到固定的网卡来解决。
关于领创集团(Advance Intelligence Group)
领创集团成立于 2016 年,致力于通过科技创新的本地化应用,改造和重塑金融和零售行业,以多元化的业务布局打造一个服务于消费者、企业和商户的生态圈。集团旗下包含企业业务和消费者业务两大板块,企业业务包含 ADVANCE.AI 和 Ginee,分别为银行、金融、金融科技、零售和电商行业客户提供基于 AI 技术的数字身份验证、风险管理产品和全渠道电商服务解决方案;消费者业务 Atome Financial 包括亚洲领先的先享后付平台 Atome 和数字金融服务。2021 年 9 月,领创集团宣布完成超 4 亿美元 D 轮融资,融资完成后领创集团估值已超 20 亿美元,成为新加坡最大的独立科技创业公司之一。
往期回顾 BREAK AWAY
▼ 如果觉得这篇内容对你有所帮助,有所启发,欢迎点赞收藏:
1、点赞、关注领创集团,获取最新技术分享和公司动态。
2、关注我们的公众号 & 知乎号「领创集团 Advance Group」或访问官方网站,了解更多企业动态。
版权声明: 本文为 InfoQ 作者【领创集团Advance Intelligence Group】的原创文章。
原文链接:【http://xie.infoq.cn/article/e077e0b1bc8df3fb3e64f2250】。文章转载请联系作者。
评论