kubelet 清理资源以缓解磁盘压力
kubelet 资源清理缓解磁盘压力指南
在 Kubernetes 集群中,当节点磁盘压力过大时,可通过以下几种方式利用 kubelet 清理资源,从而缓解磁盘压力。
一、镜像垃圾回收
自动回收
kubelet 内置了镜像垃圾回收机制,其行为由配置参数控制。编辑 /var/lib/kubelet/config.yaml
文件,添加或修改如下参数:
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
imageGCHighThresholdPercent
表示当磁盘使用率达到 85% 时触发镜像回收;imageGCLowThresholdPercent
表示回收操作将持续进行,直到磁盘使用率降至 80%。修改后,重启 kubelet 服务:
sudo systemctl restart kubelet
手动回收
根据不同的容器运行时,使用对应命令手动清理镜像:
- Docker:
docker image prune -a -f
- containerd:
crictl rmi $(crictl images -q)
触发条件与过程
- 触发条件:当节点的磁盘使用率超过设定的阈值时,kubelet 会触发镜像垃圾回收。正常情况下会定时执行,以保证节点资源充足;在节点资源不足时,Kubelet 在驱逐 Pod 前会先强制执行一次垃圾回收,如果清理后资源充足则不会驱逐 Pod。
- 清理过程:kubelet 会识别不再被任何容器引用的镜像(未使用镜像),并按照最近使用时间排序,优先删除最旧的镜像。对于新拉取的镜像,会存活一定时间(默认 2 分钟)后才执行清理,以防止刚拉取的镜像就被清理掉。
关键参数
--image-gc-high-threshold
:磁盘使用率的上限阈值,默认为 85%。--image-gc-low-threshold
:磁盘使用率的下限阈值,默认为 80%。--minimum-image-ttl-duration
:镜像最短生存时间,默认 2 分钟。
回收频率与流程
- 回收频率:Kubelet 默认每 5 分钟执行一次镜像垃圾回收。
- 回收流程:Kubelet 会识别不再被任何 Pod 引用的镜像,并按照最近使用时间(LRU)策略逐个清理,直到磁盘使用率降到设定的下限或没有空闲镜像可以清理。
二、容器垃圾回收
自动回收
kubelet 可以根据配置自动清理已停止的容器。编辑 /var/lib/kubelet/config.yaml
文件,添加或修改如下参数:
containerRuntimeOptions:containerGC:maxPerPodContainer: 1minAge: 2m
maxPerPodContainer
限制每个 Pod 最多保留的已停止容器数量为 1;minAge
表示只有停止时间超过 2 分钟的容器才会被清理。修改后,重启 kubelet 服务。
手动回收
- Docker:
docker container prune -f
- containerd:
crictl rm $(crictl ps -a -q)
触发条件与过程
- 触发条件:kubelet 定期执行容器垃圾回收,以清理不再需要的容器,主要针对普通容器、sandbox 容器以及容器日志目录。对于普通容器,Kubelet 会根据
MaxPerPodContainer
与MaxContainers
的设置,按照 LRU 策略,从 Pod 的死亡容器列表删除一定数量的容器,直到满足配置需求;对于 sandbox 容器,Kubelet 按照每个 Pod 保留一个的原则清理多余的死亡 sandbox;对于日志目录,只要没有 Pod 与之关联了就将其删除。 - 清理过程:kubelet 会删除已经终止的容器,特别是那些已经超出保留时间的容器。
关键参数
--maximum-dead-containers-per-container
:每个 Pod 可以保留的死亡容器的最大数量,默认为 1。--maximum-dead-containers
:节点上可以保留的死亡容器的最大数量,默认为 -1,表示没有限制。--minimum-container-ttl-duration
:容器可被回收的最小生存时间,默认为 0 分钟,即死亡容器可以立即被回收。
回收频率与流程
- 回收频率:Kubelet 默认每分钟执行一次容器垃圾回收。
- 回收流程:Kubelet 会清理可以驱逐的容器,包括那些状态不是
RUNNING
且在本轮 GC 前创建的容器。Kubelet 在到达 GC 时间点时,会遍历所有 Pod,使其满足--maximum-dead-containers-per-container
的设置,如果不满足--maximum-dead-containers
,则计算值X = (--maximum-dead-containers)/(Pod 总数)
,再遍历所有 Pod,使其满足已停止运行的容器集个数不大于X
且至少为 1,如果还不满足--maximum-dead-containers
,则对所有已停止的容器(普通容器 + sandbox 容器)排序,优先删除创建时间最早的容器直到满足--maximum-dead-containers
为止。执行清理直到满足以下条件之一:- 每个 Pod 中存在的已挂掉的容器数满足阈值。
- 所有 Pod 中存在的已挂掉的容器数满足阈值。
三、未使用的 Volume 清理
手动清理
定期清理不再使用的持久卷声明(PVC)和挂载的 Volume 能释放大量磁盘空间。使用以下命令删除所有处于 Released
状态的 PVC:
kubectl get pvc --field-selector status.phase=Released -o name | xargs kubectl delete
此外,若使用的是动态存储卷,确保存储类(StorageClass)配置了正确的回收策略。
触发条件与过程
- 触发条件:当节点磁盘空间不足时,kubelet 会尝试清理未使用的 Volumes。
- 清理过程:kubelet 会识别并删除那些不再被任何 Pod 引用的 Volumes。
自动清理涉及方面
- PersistentVolumeClaim (PVC) 和 PersistentVolume (PV) 的回收策略:Kubernetes 中的 PVC 对象可以设置
reclaimPolicy
属性,该属性有两个值:Retain
和Delete
。当 PVC 与 PV 绑定后,如果 Pod 被删除,根据reclaimPolicy
的设置,Volume 可以被保留或自动删除。 - StorageClass 的 reclaimPolicy:在 StorageClass 对象中,可以设置
reclaimPolicy
,这将决定 PV 的默认回收策略。当设置为Delete
时,PV 和绑定的存储资源在 PVC 删除时将被自动清理。 - Kubelet 垃圾回收机制:Kubelet 定期进行垃圾收集,包括容器和镜像。Kubelet 每分钟对未使用的容器执行一次垃圾收集,每五分钟对未使用的镜像执行一次垃圾收集。
- Volume 插件目录清理:Kubelet 可以通过配置
--volume-plugin-dir
参数来指定卷插件目录,并定期清理其中的数据。 - 日志文件管理:Kubelet 会定期清理旧的日志文件,或者配置日志轮转工具(如 logrotate)来管理日志文件的大小和生命周期,以释放磁盘空间。
- 手动清理命令:可以使用
kubectl
命令清理未使用的 PV 和 PVC,例如查找未被使用的 PVC 并删除它们,进而可能触发关联 Volume 的清理。 - 定期审计和清理:定期检查集群中的 Volume 使用情况,手动清理未被自动回收的 Volume。
四、驱逐机制(Eviction)
配置参数
kubelet 可以基于磁盘压力等条件驱逐 Pod,释放节点资源。编辑 /var/lib/kubelet/config.yaml
文件,添加或修改如下参数:
evictionHard:imagefs.available: 10%nodefs.available: 10%
evictionSoft:imagefs.available: 15%nodefs.available: 15%
evictionSoftGracePeriod:imagefs.available: 5mnodefs.available: 5m
evictionMinimumReclaim:imagefs.available: 5%nodefs.available: 5%
上述配置中,当镜像文件系统或节点文件系统的可用空间低于 10% 时,触发硬驱逐;低于 15% 时触发软驱逐,软驱逐会在 5 分钟后执行,每次驱逐操作至少回收 5% 的可用空间。修改后,重启 kubelet 服务。
触发条件与过程
- 触发条件:当节点资源(如内存、磁盘空间)低于硬驱逐阈值时,kubelet 会触发驱逐机制。
- 驱逐过程:kubelet 会根据配置的驱逐策略,选择并终止某些 Pod 以释放资源。例如,当节点的可用内存低于 100Mi 时,kubelet 可能会开始驱逐 Pod。
五、日志文件管理
自动轮转
使用 logrotate
工具配置日志轮转,编辑 /etc/logrotate.d/kubelet
文件:
/var/log/kubelet.log {dailymissingokrotate 7compressdelaycompressnotifemptycreate 0640 root admsharedscriptspostrotateif [ -f /var/run/kubelet.pid ]; thenkill -HUP `cat /var/run/kubelet.pid`fiendscript
}
上述配置表示每天轮转一次 kubelet 日志文件,保留最近 7 天的日志,压缩旧日志文件。
手动清理
手动删除不再需要的日志文件:
sudo rm -rf /var/log/pods/*
需注意,此操作会清除所有 Pod 的日志,操作前请备份重要日志。
触发条件与管理过程
- 触发条件:日志文件占用大量磁盘空间时。
- 管理过程:kubelet 会定期清理旧的日志文件,或者配置日志轮转工具(如 logrotate)来管理日志文件的大小和生命周期。
日志管理涉及方面
- 日志文件路径规则:Kubelet 将容器日志默认写入
/var/log/pods
目录下,每个 Pod 的日志存放在以其命名空间、名称和 UID 为名的子目录中。容器日志文件以容器重启次数命名,格式为<容器重启次数>.log
。 - 日志文件软链接规则:容器日志目录下的日志文件实际上是软链接类型文件,指向实际的日志文件。
- 日志文件清理:Kubelet 每 1 分钟执行一次容器清理,包括清理死亡容器的日志目录。如果一个 Pod 已经不再占用其日志目录,Kubelet 会清理这些日志目录。
- 日志文件大小和文件数限制:Kubelet 配置选项
containerLogMaxSize
和containerLogMaxFiles
分别允许配置每个日志文件大小的最大值和每个容器允许的最大文件数,默认分别为 10Mi 和 5。 - 日志轮换机制:Kubelet 提供了基于可以执行多少并发日志轮换以及监控和轮换日志所需要的间隔来调整日志的轮换方式的机制。可以通过配置
containerLogMaxWorkers
和containerLogMonitorInterval
来调整。 - 系统组件日志位置:在使用 systemd 的 Linux 节点上,kubelet 和容器运行时默认写入 journald。如果 systemd 不存在,kubelet 和容器运行时将写入到
/var/log
目录中的.log
文件。 - 自定义日志目录:Kubelet 允许将 Pod 日志目录从默认的
/var/log/pods
更改为自定义路径,通过在 kubelet 的配置文件中配置podLogsDir
参数来进行此调整。
六、配置参数调整
减少日志级别
编辑 kubelet 服务的启动参数文件 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
,添加或修改 --v
参数来降低日志级别:
Environment="KUBELET_EXTRA_ARGS=--v=2"
日志级别范围从 0 到 10,数值越小,日志输出越少。修改后,重新加载 systemd 配置并重启 kubelet 服务:
sudo systemctl daemon-reload
sudo systemctl restart kubelet
减少缓存
减少 kubelet 的缓存数据,如临时文件和下载的镜像等。编辑 /var/lib/kubelet/config.yaml
文件,添加或修改如下参数:
cacheDir: /var/lib/kubelet/cache
cacheMaxSize: 1024Mi
上述配置将 kubelet 的缓存目录设置为 /var/lib/kubelet/cache
,并限制缓存最大为 1024MB。修改后,重启 kubelet 服务。
通用参数调整
管理员可以通过调整 kubelet 的配置参数来优化资源清理行为,例如调整垃圾回收的阈值和频率。