背景:
早些时候kubernetes集群的cri还使用docker的时候经历过这样的状况: 集群运行很久后硬盘跑的快满了......,大文件主要集中在:/var/lib/docker/overlay2 下文件有快70G,/var/log/journal/日志也有4-5G。当时的操作是手工的在work节点进行了一下的操作:
- journalctl --vacuum-size=20M #设置journal 日志最大为20M不保留不必要日志。
- docker image prune -a --filter "until=24h" # 清除超过创建时间超过24小时的镜像
- docker container prune --filter "until=24h" #清除掉所有停掉的容器,但24内创建的除外
- docker volume prune --filter "label!=keep" #除lable=keep外的volume外都清理掉(没有引用的volume)
- docker system prune #清理everything:images ,containers,networks一次性清理操作可以通过docker system prune来搞定
注: 以上摘自个人博客2019年的一篇:https://duiniwukenaihe.github.io/2019/11/25/k8s-question2/。
当然了类似的还有inotify watch 耗尽 cgroup 泄露。可参照:https://www.bookstack.cn/read/kubernetes-practice-guide/troubleshooting-problems-errors-no-space-left-on-device.md
那么问题来了:我现在的集群是kubernetes1.21集群。cri是containerd 我改如何清理除了系统日志外的 关于cri的资源呢?正常的来说kubelet是有此功能的?反正我tke集群的work节点最近频繁收到了磁盘大于百分之九十的报警了......,强迫症犯了!
关于Kubernetes image垃圾镜像容器的回收
关于kubelet:
节点管理
节点通过设置kubelet的启动参数“--register-node”,来决定是否向API Server注册自己,默认为true.[kubelet --help]
Pod管理
kubelet通过API Server Client使用Watch/List的方式监听etcd中/registry/nodes/${当前节点名称}和/registry/pods的 目录,将获取的信息同步到本地缓存中。kubelet监听etcd,执行对Pod的操作,对容器的操作则是通过Docker Client 执行,常见的操作包含:增,删,该,查。
容器健康检查
探针是kubelet对容器执行定期的诊断,主要通过调用容器配置的三类Handler实现,如果存活探测失败,则
kubelet 会杀死容器,并且容器将受到其 重启策略的影响。
资源监控
kubelet通过cAdvisor获取本节点信息及容器的数据。cAdvisor为谷歌开源的容器资源分析工具,默认集成到
kubernetes中。
kubelet-garbage-collection
垃圾回收是 kubelet 的一个有用功能,它将清理未使用的镜像和容器。Kubelet 将每分钟对容器执行一次垃圾回收, 每五分钟对镜像执行一次垃圾回收。 不建议使用外部垃圾收集工具,因为这些工具可能会删除原本期望存在的容器进而破坏 kubelet 的行为。
镜像回收
Kubernetes 借助于 cadvisor 通过 imageManager 来管理所有镜像的生命周期。
镜像垃圾回收策略只考虑两个因素:HighThresholdPercent 和 LowThresholdPercent。 磁盘使用率超过上限
阈值(HighThresholdPercent)将触发垃圾回收。 垃圾回收将删除最近最少使用的镜像,直到磁盘使用率满足下
限阈值(LowThresholdPercent)。
容器回收
容器垃圾回收策略考虑三个用户定义变量。MinAge 是容器可以被执行垃圾回收的最小生命周期 。
MaxPerPodContainer 是每个 pod 内允许存在的死亡容器的最大数量。 MaxContainers 是全部死亡容器的最大数
量。可以分别独立地通过将 MinAge 设置为 0,以及将 MaxPerPodContainer 和 MaxContainers 设置为小于 0 来
禁用这些变量。 Kubelet 将处理无法辨识的、已删除的以及超出前面提到的参数所设置范围的容器。最老的容器通常会先被移除。 MaxPerPodContainer 和 MaxContainer 在某些场景下可能会存在冲突,例如在保证每个 pod 内死亡容器的最大数 量(MaxPerPodContainer)的条件下可能会超过允许存在的全部死亡容器的最大数量(MaxContainer)。 MaxPerPodContainer 在这种情况下会被进行调整:最坏的情况是将 MaxPerPodContainer 降级为 1,并驱逐最老 的容器。 此外,pod 内已经被删除的容器一旦年龄超过 MinAge 就会被清理。
不被 kubelet 管理的容器不受容器垃圾回收的约束。
用户配置
用户可以使用以下 kubelet 参数调整相关阈值来优化镜像垃圾回收:
- image-gc-high-threshold,触发镜像垃圾回收的磁盘使用率百分比。默认值为 85%。
- image-gc-low-threshold,镜像垃圾回收试图释放资源后达到的磁盘使用率百分比。默认值为 80%。
我们还允许用户通过以下 kubelet 参数自定义垃圾收集策略:
- minimum-container-ttl-duration,完成的容器在被垃圾回收之前的最小年龄,默认是 0 分钟。 这意味着每个完成的容器都会被执行垃圾回收。
- maximum-dead-containers-per-container,每个容器要保留的旧实例的最大数量。默认值为 1。
- maximum-dead-containers,要全局保留的旧容器实例的最大数量。 默认值是 -1,意味着没有全局限制。
容器可能会在其效用过期之前被垃圾回收。这些容器可能包含日志和其他对故障诊断有用的数据。 强烈建议为 maximum-dead-containers-per-container 设置一个足够大的值,以便每个预期容器至少保留一个死亡容器。 由于同样的原因,maximum-dead-containers 也建议使用一个足够大的值。
参照一下我的tke集群
cat /etc/kubernetes/kubelet
看了一眼没有找到kubelet-garbage-collection上面的参数?只有一个--eviction-hard。仔细看一眼文档的弃用部分:
嗯 1.21版本启用了--eviction-hard参数,至于nodefs.inodesFree可参照:
自建集群中的配置:
嗯配置文件中未作任何设置只有一个imageMinimumGCAge!
可参照:
可参照:https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/。中文如下:
总结一下:
Kubelet 支持 gc 和驱逐机制,可通过 --image-gc-high-threshold、--image-gc-low-threshold、--eviction-hard、--eviction-soft 及 --eviction-minimum-reclaim 等参数进行控制以实现磁盘空间的释放。当配置不正确,或者节点上有其它非 K8S 管理的进程在不断写数据到磁盘,将会占用大量空间时将导致磁盘爆满。tke集群设置的是--eviction-hard=nodefs.available<10%,这个值我可能会修改为20%。因为cvm的报警阀值我都设置的90%。后续个人准备参照tke的--eviction-hard=nodefs.available<10%,nodefs.inodesFree<5%,memory.available<100Mi参数修改一下这三个了......(image-gc-high-threshold默认85%,image-gc-low-threshold默认80%自建的集群应该是 忽略了)。个人的集群还没有报警。关键是tke集群的报警这个值还的调整一下了!
关于tke磁盘爆满的文档:
https://cloud.tencent.com/document/product/457/43126#.E5.8F.AF.E8.83.BD.E5.8E.9F.E5.9B.A0
另外ubelet的配置还要深入研究一下!