驱逐导致服务中断

TODO 优化

案例

TKE 一客户的某个节点有问题,无法挂载nfs,通过新加节点,驱逐故障节点的 pod 来规避,但导致了业务 10min 服务不可用,排查发现其它节点 pod 很多集体出现了重启,主要是连不上 kube-dns 无法解析 service,业务调用不成功,从而对外表现为服务不可用。

为什么会中断?驱逐的原理是先封锁节点,然后将旧的 node 上的 pod 删除,replicaset 控制器检测到 pod 减少,会重新创建一个 pod,调度到新的 node上,这个过程是先删除,再创建,并非是滚动更新,因此更新过程中,如果一个deployment的所有 pod 都在被驱逐的节点上,则可能导致该服务不可用。

那为什么会影响其它 pod?分析kubelet日志,kube-dns 有两个副本,都在这个被驱逐的节点上,所以驱逐的时候 kube-dns 不通,影响了其它 pod 解析 service,导致服务集体不可用。

那为什么会中断这么久?通常在新的节点应该很会快才是,通过进一步分析新节点的 kubelet 日志,发现 kube-dns 从拉镜像到容器启动之间花了很长时间,检查节点上的镜像发现有很多大镜像(1~2GB),猜测是拉取镜像有并发限制,kube-dns 的镜像虽小,但在排队等大镜像下载完,检查 kubelet 启动参数,确实有 --registry-burst 这个参数控制镜像下载并发数限制。但最终发现其实应该是 --serialize-image-pulls 这个参数导致的,kubelet 启动参数没有指定该参数,而该参数默认值为 true,即默认串行下载镜像,不并发下载,所以导致镜像下载排队,是的 kube-dns 延迟了很长时间才启动。

解决方案

  • 避免服务单点故障,多副本,并加反亲和性
  • 设置 preStop hook 与 readinessProbe,更新路由规则