记一个 k8s 中 service 的 clusterIP 配置错误的排查过程2020年4月30日
先讲讲项目的性质和部署方式,项目是前后端分离的,都用的 gitlab 的 CI/CD 去打镜像,build stage 过了后发到 k8s(前后端并发 apply 自己的 k8s yml),即git tag -> lint + test -> build -> build docker image -> k8s apply yml -> notify
k8s 集群的部署环境简化一下是这样的 阿里云 SLB -> k8s ingress -> fe service -> be service -> DB
阿里云 SLB -> k8s ingress -> be service -> DB
也是比较典型的配置方式,其中前端是用 openresty
在 docker image
中带起来的
有几次发现部署不稳定,现象是前端 502
,报的 cannot find route to xx.xx.xx.xx
,检查了一下配置,确认没问题,在 fe pod
中重启 openresty
,发现 fe
可以正常工作了,但过了一段时间后又挂了。看了一下这段时间的操作,有一次发版行为,不能确定是发版导致的还是 be
挂掉重启(被 k8s 重新配了一个 IP 地址)导致的 IP 失效。于是找了一套环境发版来尝试复现,发版前记录 pod/service
的 IP,发版,发现前端 502
了,报错信息中的 upstream IP
是发版前的 be pod
地址。等发版完成后去看了一下 be pod
的地址,果真已经变了。
yoxi 问题应该就在这里了,解析是没问题的,只是 openresty
部署的时候比后端先启动,缓存了老的 be IP
。那么解法可以是
- 禁用
dns
,影响性能 dns
配置超时,一定程度的可用性降低,一定程度影响性能- 监听
k8s be service
启动、重启事件,收到后在openresty
刷新dns
,需要开发,开发团队自己确保基础设施的可靠性 - 保证
k8s be deployment
完成后再做k8s fe deployment
,用确保时序的方式避免部署问题,但不能解决后续可能出现的重启问题
想了一想好像这个需求应该是很常见的,社区一定有解法,搜了一溜发现并没有,奇怪的是提这个问题的人都少之又少,那他们是怎么解决的呢?然后就去翻了 k8s
文档,应该属于服务发现范畴,看到了VIP,这不是之前做数据库热切用到的么,看起来是能解决问题的,但看着有点重,看到这里发现 service
有个 ClusterIP
的概念,在 service
的生命周期里是不会变的,就是用来做 service
解耦的,外部不需要知道 service
里面有什么。那么问题来了,这个行为是默认的,为什么 fe openresty dns
会解析出 be pod
的 IP
呢?应该是一个 service ClusterIP
才对。检查了一下运维同学的 yml
才发现 clusterIP
都设置了 none
。。。忽然想起很多性能调优不稳定的往事。。。真的是。。
架构级的东西比代码更需要 review 啊