提要
线下集成测试时,尝试更新 Kubelet 的新版本。针对新增功能中支持 NBD,我们遇到 Kubelet 重启会导致宿主机重启的问题。最终问题定位至 rdb-nbd 进程异常退出导致死机。通过修改 KillMode 参数和 storageClass 配置,修复了问题。
问题描述
在新版本 Kubelet 中新增了支持 NBD 的相关功能,我们在线下测试集群中尝试更新 Kubelet 来研究其功能。
在 2018-02-23 15:46:56 时,我们通过发布系统灰度更新 kubelet 时,发现部署超时,最终导致部署失败,再次尝试部署,可以部署成功,登录已部署的宿主机查看,发现宿主机重启了,然后暂停余下部署。
紧接着,我们围绕 NDB 进行排查, 最后发现,只要挂载了 NBD 设备的宿主,只要重启 Kubelet 就会死机,然后经过手动测试该特性发现,如果杀死了 rbd-nbd map 的进程其实也会导致死机。
所以将问题定位至:
- 重启 Kubelet 为什么导致 rbd-nbd map 的进程也被退出了?
- Rbd-nbd map 的进程退出为什么导致死机?
Rbd-nbd 被动退出问题
Kubelet 服务是由 systemd 托管的,而 rbd-nbd map 进程是由 Kubelet 运行的,rbd-nbd map 进程则成为 Kubelet 的控制组内的进程了, 如下:
当停止 Kubelet 服务的时候,systemd 会首先给 Kubelet 发送杀死信号,然后会给其它进程也发杀死信号,导致问题 1 的发生,事后尝试完全把 rbd-nbd map 这个逻辑从 Kubelet 自身脱离出来,由外部服务来执行和托管,这应该也是 CSI 的思想,但是对于我们现在来说管理成本太高了, 那么还是从 systemd 入手查看,看能否做到杀死 Kubelet 时不给其它进程发杀死信号机制,果然有:
KillMode=XXX 可以设置执行 systemctl stop 时的姿势,比如: KillMode=process:If set to process, only the main process itself is killed,默认是 control-group。
其它姿势可以看 systemd.kill 手册:
死机问题
对于死机问题,第一时间是查日志,查日志有两个地方:
- /var/log/messages
- /var/crash
Messages 里没发现什么异常信息,直接查看 crash,发现有几次 crash,根据故障特点,查看重点信息:
从 Oops 信息查看貌似是触发了 ext4 文件系统的底层 BUG, 回想一下 kubelet 通过 storageclass 挂载 ceph 设备的流程,并没有指定 mount 到本地的文件系统类型,那么默认使用的就是 ext4, 所以,更新 storageclass 配置,增加 fsType 参数,并设置为 xfs,比如:
然后再重新测试整个创建容器,重启 Kubelet 服务流程,不存在 rbd-nbd 程序退出和宿主死机重启的问题了。
总结
对于上面的问题的解决方案, 目前看需要弹性云线上集群做如下修改:
- 优化 Kubelet 支持 NBD 的代码,使用最新的 patch;
- 修改 Kubelet 服务配置文件,增加 Killmode=process;
- 修改 storageClass 配置, 增加文件系统类型参数 fsType:xfs。
扩展思考
如果 rbd-nbd 被意外 Kill 掉,结果会怎么样呢?
经过测试发现,如果 rbd-nbd 被 Kill 掉,导致该容器的 ceph 盘读写错误 (IO Error),但是容器还正常运行,暂时没有恢复方案,所以需要加监控;针对 ceph 和 Kubernetes 的集成,需要更加详细的测试。