前几天在做一个需求的时候,突然发现某个节点上的集群无法访问了,在此记录一下出现的现象以及处理方式。
环境
一套 k8s 环境,其中有 4 个节点,其中一个节点属于 ci 专用。
现象
- 前端页面访问失败,无响应
- 访问 Jenkins 页面,无响应
回顾事件
当时是在晚上九点,我在调试一个流水线的 Jenkinsfile 脚本,点了一次运行以后,就去处理别的事情,等 ci 了,过了一段时间,我回来看的时候,发现页面访问不了了,无论是 k8s 集群的前端页面,还是 Jenkins 的前端页面都无法访问。
由于当时已经离开公司了,是在家里远程处理的,所以那天晚上就先搁置了,等到第二天上午再去处理的。第二天在公司里的时候,我登录到 master 节点去看,首先我使用 curl 测试了一下 apiserver,发现是有响应的,那么大概率就是前端的那个 deployment 有问题了;于是我用 describe 看了下前端 deployment 的状态,发现报了一个错误,拉取不到镜像;这个问题人给我看傻了,我们的 harbor 仓库更换过了,所以拉取不到是正常的,但是那台机器以前是有本地镜像的,莫名其妙的本地镜像被删了 :rofl:;这个问题处理起立简单,我换了个新的地址就解决了,登录进去以后,发现 ci 的那个节点还是处于无法调度的状态,不可用,于是又去检查另一个节点。
首先我去看了一下 kubelet 的状态,具体的错误记不清了,可能是类似这样的:
1 | Warning FailedCreatePodSandBox 53m kubelet, 172.22.0.44 Failed create pod sandbox: rpc error: code = DeadlineExceeded desc = context deadline exceeded |
我拿着信息在网上搜索了一圈,第一条结果就是说可能是磁盘满了,于是我看了一眼磁盘,果然,/var/lib/docker
和 /var/lib/kubelet
是挂载到 /
下面的,总共就只有 100 G,磁盘满了,所以 pod 也启动不起来,但是 /home
目录下还有十几个 T 的空间没有使用,于是我就准备把这两目录都迁移到 /home
目录。
迁移步骤
- **驱逐节点上的 pod
1 | kubectl drain <node-name> |
- 停止 docker、kubelet
1 | systemctl stop docker && systemctl stop kubelet |
- 迁移目录
注意:迁移目录时,使用 cp 或者 rsync 命令时,记得使用 “-p”参数,保持文件权限,曾经我就在迁移目录没注意这个问题,导致线上的服务给干崩了,还好这只是我们部门内部的服务,影响比较小。
创建新的目录:
我直接在 home 目录在建了个 var
目录,这种方式不推荐,假如有人需要创建一个名为 var
的用户,可能会产生冲突(这个没试过)
1 | mkdir -pv /home/var/lib/docker |
拷贝旧文件:
1 | cp -p /var/lib/docker /home/var/lib/docker |
拷贝的过程可能会要等很久,安心等待…
- 修改配置
kubelet 和 docker,都需要修改配置文件,将修改后的存储地址挂载进去。有关 docker 不同版本修改配置的一些区别,请看 两种方法迁移 Docker 的默认安装(存储)目录
Docker 配置
1
vim /etc/docker/daemon.json
增加如下配置:
1
"data-root": "/store/software/docker",
kubelet 配置
主要是修改
root-dit
参数,参见 官方文档