垃圾收集是 Kubernetes 用于清理集群资源的各种机制的统称。
自动回收机制可以避免随着时间推移,系统中的镜像等越来越多,导致硬盘等资源不足。
垃圾收集允许系统自动清理如下资源:
- 失败的 Pod
- 已完成的 Job
- 不再存在属主引用的对象
- 未使用的容器和容器镜像
- 动态制备的、StorageClass 回收策略为 Delete 的 PV 卷
- 阻滞或者过期的 CertificateSigningRequest (CSRs)
- 在以下情形中删除了的节点对象:
– 当集群使用云控制器管理器运行于云端时;
– 当集群使用类似于云控制器管理器的插件运行在本地环境中时。 - 节点租约对象
失败的 Pod
对于已失败的 Pod 而言,对应的 API 对象仍然会保留在集群的 API 服务器上, 直到用户或者控制器进程显式地将其删除。
Pod 的垃圾收集器(PodGC)是控制平面的控制器,它会在 Pod 个数超出所配置的阈值 (根据 kube-controller-manager 的 terminated-pod-gc-threshold 设置)时删除已终止的 Pod(阶段值为 Succeeded 或 Failed)。 这一行为会避免随着时间演进不断创建和终止 Pod 而引起的资源泄露问题。
此外,PodGC 会清理满足以下任一条件的所有 Pod:
- 孤儿 Pod - 绑定到不再存在的节点,
- 计划外终止的 Pod
- 终止过程中的 Pod,当启用 NodeOutOfServiceVolumeDetach 特性门控时, 绑定到有 node.kubernetes.io/out-of-service 污点的未就绪节点。
若启用 PodDisruptionConditions 特性门控,在清理 Pod 的同时, 如果它们处于非终止状态阶段,PodGC 也会将它们标记为失败。 此外,PodGC 在清理孤儿 Pod 时会添加 Pod 干扰状况。
已完成的 Job
当你的 Job 已结束时,将 Job 保留在 API 中(而不是立即删除 Job)很有用, 这样你就可以判断 Job 是成功还是失败。
Kubernetes TTL-after-finished 控制器提供了一种 TTL 机制来限制已完成执行的 Job 对象的生命期。
TTL-after-finished 控制器只支持 Job。你可以通过指定 Job 的 .spec.ttlSecondsAfterFinished 字段来自动清理已结束的 Job(Complete 或 Failed).
TTL-after-finished 控制器假设 Job 能在执行完成后的 TTL 秒内被清理。一旦 Job 的状态条件发生变化表明该 Job 是 Complete 或 Failed,计时器就会启动;一旦 TTL 已过期,该 Job 就能被级联删除。 当 TTL 控制器清理作业时,它将做级联删除操作,即删除 Job 的同时也删除其依赖对象。
Kubernetes 尊重 Job 对象的生命周期保证,例如等待 Finalizer。
你可以随时设置 TTL 秒。以下是设置 Job 的 .spec.ttlSecondsAfterFinished 字段的一些示例:
- 在 Job 清单(manifest)中指定此字段,以便 Job 在完成后的某个时间被自动清理。
- 手动设置现有的、已完成的 Job 的此字段,以便这些 Job 可被清理。
- 在创建 Job 时使用修改性质的准入 Webhook 动态设置该字段。集群管理员可以使用它对已完成的作业强制执行 TTL 策略。
- 使用修改性质的准入 Webhook 在 Job 完成后动态设置该字段,并根据 Job 状态、标签等选择不同的 TTL 值。 对于这种情况,Webhook 需要检测 Job 的 .status 变化,并且仅在 Job 被标记为已完成时设置 TTL。
- 编写你自己的控制器来管理与特定选择算符匹配的 Job 的清理 TTL。
不再存在属主引用的对象
Kubernetes 中很多对象通过属主引用 链接到彼此。属主引用(Owner Reference)可以告诉控制面哪些对象依赖于其他对象。 Kubernetes 使用属主引用来为控制面以及其他 API 客户端在删除某对象时提供一个清理关联资源的机会。 在大多数场合,Kubernetes 都是自动管理属主引用的。
根据设计,系统不允许出现跨名字空间的属主引用。名字空间作用域的依赖对象可以指定集群作用域或者名字空间作用域的属主。 名字空间作用域的属主必须存在于依赖对象所在的同一名字空间。 如果属主位于不同名字空间,则属主引用被视为不存在,而当检查发现所有属主都已不存在时,依赖对象会被删除。
集群作用域的依赖对象只能指定集群作用域的属主。 在 1.20 及更高版本中,如果一个集群作用域的依赖对象指定了某个名字空间作用域的类别作为其属主, 则该对象被视为拥有一个无法解析的属主引用,因而无法被垃圾收集处理。
在 1.20 及更高版本中,如果垃圾收集器检测到非法的跨名字空间 ownerReference, 或者某集群作用域的依赖对象的 ownerReference 引用某名字空间作用域的类别, 系统会生成一个警告事件,其原因为 OwnerRefInvalidNamespace,involvedObject 设置为非法的依赖对象。你可以通过运行 kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace 来检查是否存在这类事件。
未使用的容器和容器镜像
kubelet 会每两分钟对未使用的镜像执行一次垃圾收集, 每分钟对未使用的容器执行一次垃圾收集。 你应该避免使用外部的垃圾收集工具,因为外部工具可能会破坏 kubelet 的行为,移除应该保留的容器。
要配置对未使用容器和镜像的垃圾收集选项,可以使用一个 配置文件,基于 KubeletConfiguration 资源类型来调整与垃圾收集相关的 kubelet 行为。
Kubernetes 通过其镜像管理器(Image Manager) 来管理所有镜像的生命周期, 该管理器是 kubelet 的一部分,工作时与 cadvisor 协同。 kubelet 在作出垃圾收集决定时会考虑如下磁盘用量约束:
- HighThresholdPercent
- LowThresholdPercent
磁盘用量超出所配置的 HighThresholdPercent 值时会触发垃圾收集, 垃圾收集器会基于镜像上次被使用的时间来按顺序删除它们,首先删除的是最近未使用的镜像。 kubelet 会持续删除镜像,直到磁盘用量到达 LowThresholdPercent 值为止。