跳转至

禁用容器镜像垃圾回收并配置磁盘相关容器漂移策略

1. 在无镜像仓库的情况下使用 k8s 的问题

k8s 默认有一个垃圾回收机制,而且容器的临时存储和容器的镜像存储都在/var 目录下,因此只要有/var 目录大于 85%的情况(无论是容器写临时文件还是/var 目录下生成了其它特别大的东西,还是导入容器镜像),k8s 就会把所有的容器赶走,同时会对容器镜像垃圾回收。但是,由于容器已经都被赶走了,垃圾回收会把这些容器镜像删掉,之后如果容器镜像是在节点手动导入而非从镜像仓库拉取,则会导致容器镜像永远丢失,节点/var 目录清理或扩容后,仍旧无法启动容器。因此需要把容器的存储位置单独挂盘,并且禁用容器镜像的垃圾回收。

还是不推荐不搭建一个镜像仓库,因为这种方法一旦容器的目录真的满了,必须人工上去 ctr 命令删除容器

2. 修改 kubelet 配置

/var/lib/kubelet/config.yaml中,配置 k8s 节点在容器临时文件存储低于 10% 时,赶走所有容器到其它节点,且容器镜像不使用 100 年后才清理:

1
2
3
4
5
6
evictionHard:
  imagefs.available: "10%"
  nodefs.available: "5%"
imageGCHighThresholdPercent: 100
imageGCLowThresholdPercent: 99
imageMinimumGCAge: 876000h

重启 kublet:

systemctl restart kubelet.service

3. 将 /var/lib/containerd 单独挂载 lv,防止系统日志挤占容器空间

3.1 腾空一个 k8s 节点

kubectl cordon z10bansk8scp02
kubectl drain z10bansk8scp02 --ignore-daemonsets --delete-emptydir-data

3.2 清理数据

停止 kubelet:

systemctl stop kubelet.service

删除所有容器:

for i in $(ctr -n k8s.io task ls | awk '{print $1}');do ctr -n k8s.io task kill $i;done
for i in $(ctr -n k8s.io container ls | awk '{print $1}');do ctr -n k8s.io container delete $i;done

删除容器镜像:

ctr -n k8s.io image prune --all

停止 containerd 并清理 containerd 目录:

systemctl stop containerd
rm -rf /var/lib/containerd/*

将 containerd 镜像目录单独挂载 lv:

1
2
3
4
lvcreate -n lv_containerd -L 30G rootvg
mkfs.xfs /dev/rootvg/lv_containerd
echo "/dev/rootvg/lv_containerd /var/lib/containerd xfs defaults 0 0" >> /etc/fstab
mount -a

启动 containerd 和 kubelet,并解除隔离状态:

1
2
3
systemctl restart containerd
systemctl restart kubelet.service
kubectl uncordon z10bansk8scp02

3.3 重新导入容器镜像并检查:

for i in *;do ctr -n k8s.io image import $i --platform linux/amd64;done
ctr -n k8s.io images list | grep -v ^sha256 | awk '{print $1}' | nl

4. 参考链接

https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/

https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/

https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/