垃圾回收
垃圾回收是 Kubernetes 用于清理集群资源的各种机制的统称。它允许清理以下资源:
- 已终止的 Pod
- 已完成的 Job
- 没有属主引用的对象
- 未使用的容器和容器镜像
- StorageClass 回收策略为 Delete 的动态制备 PersistentVolume
- 过期或失效的 CertificateSigningRequest(CSR)
- 在以下场景中删除的节点
- 集群使用云控制器管理器时的云环境
- 集群使用类似于云控制器管理器的附加组件时的本地环境
- 节点租约对象
属主和依赖项
Kubernetes 中的许多对象通过**属主引用**相互关联。属主引用告诉控制平面哪些对象依赖于其他对象。Kubernetes 使用属主引用让控制平面和其他 API 客户端有机会在删除对象之前清理相关资源。在大多数情况下,Kubernetes 会自动管理属主引用。
属主引用与某些资源也使用的标签和选择器机制不同。例如,考虑一个创建 `EndpointSlice` 对象的Service。该 Service 使用**标签**让控制平面确定哪些 `EndpointSlice` 对象用于该 Service。除了标签之外,代表 Service 管理的每个 `EndpointSlice` 都包含一个属主引用。属主引用有助于 Kubernetes 的不同部分避免干扰它们不控制的对象。
注意
跨命名空间属主引用是设计上不允许的。命名空间依赖项可以指定集群范围或命名空间范围的属主。命名空间属主**必须**与依赖项存在于同一命名空间中。如果不存在,则该属主引用被视为不存在,一旦所有属主都被验证为不存在,依赖项就会被删除。
集群范围的依赖项只能指定集群范围的属主。在 v1.20+ 中,如果集群范围的依赖项指定了命名空间种类作为属主,则会被视为具有无法解析的属主引用,并且无法进行垃圾回收。
在 v1.20+ 中,如果垃圾回收器检测到无效的跨命名空间 `ownerReference`,或者集群范围的依赖项的 `ownerReference` 引用了命名空间种类,则会报告一个警告事件,其原因为 `OwnerRefInvalidNamespace`,`involvedObject` 为无效的依赖项。你可以通过运行 `kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace` 来检查此类事件。
级联删除
Kubernetes 会检查并删除不再具有属主引用的对象,例如删除 ReplicaSet 时留下的 Pod。当你删除一个对象时,你可以控制 Kubernetes 是否自动删除该对象的依赖项,这个过程称为**级联删除**。级联删除有两种类型,如下所示:
- 前台级联删除
- 后台级联删除
你还可以使用 Kubernetes 终结器来控制垃圾回收如何以及何时删除具有属主引用的资源。
前台级联删除
在前台级联删除中,你正在删除的属主对象首先进入**删除进行中**状态。在此状态下,属主对象会发生以下情况:
- Kubernetes API 服务器将对象的 `metadata.deletionTimestamp` 字段设置为对象被标记为删除的时间。
- Kubernetes API 服务器还将 `metadata.finalizers` 字段设置为 `foregroundDeletion`。
- 对象在删除过程完成之前通过 Kubernetes API 可见。
在属主对象进入**删除进行中**状态后,控制器会删除它知道的所有依赖项。删除所有它知道的依赖对象后,控制器会删除属主对象。此时,该对象在 Kubernetes API 中不再可见。
在前台级联删除期间,唯一阻止属主删除的依赖项是那些具有 `ownerReference.blockOwnerDeletion=true` 字段且位于垃圾回收控制器缓存中的对象。垃圾回收控制器缓存可能不包含无法成功列出/监视其资源类型的对象,或者与属主对象的删除同时创建的对象。有关更多信息,请参阅使用前台级联删除。
后台级联删除
在后台级联删除中,Kubernetes API 服务器会立即删除属主对象,垃圾回收器控制器(自定义或默认)会在后台清理依赖对象。如果存在终结器,它会确保在所有必要的清理任务完成之前不会删除对象。默认情况下,除非你手动使用前台删除或选择孤立依赖对象,否则 Kubernetes 会使用后台级联删除。
有关更多信息,请参阅使用后台级联删除。
孤立依赖项
当 Kubernetes 删除一个属主对象时,留下的依赖项称为**孤立**对象。默认情况下,Kubernetes 会删除依赖对象。要了解如何覆盖此行为,请参阅删除属主对象并孤立依赖项。
未使用的容器和镜像的垃圾回收
kubelet 每五分钟对未使用的镜像执行一次垃圾回收,每分钟对未使用的容器执行一次垃圾回收。你应该避免使用外部垃圾回收工具,因为这些工具可能会破坏 kubelet 的行为并删除应该存在的容器。
要配置未使用的容器和镜像垃圾回收的选项,请使用配置文件调整 kubelet,并使用 `KubeletConfiguration` 资源类型更改与垃圾回收相关的参数。
容器镜像生命周期
Kubernetes 通过其**镜像管理器**(kubelet 的一部分)与 cadvisor 协作管理所有镜像的生命周期。kubelet 在做出垃圾回收决策时会考虑以下磁盘使用限制:
HighThresholdPercent
LowThresholdPercent
磁盘使用量超过配置的 `HighThresholdPercent` 值会触发垃圾回收,垃圾回收会根据镜像最后使用的时间顺序删除镜像,从最旧的开始。kubelet 会删除镜像,直到磁盘使用量达到 `LowThresholdPercent` 值。
未使用的容器镜像的垃圾回收
作为 Beta 功能,你可以指定本地镜像可以不使用多长时间,无论磁盘使用情况如何。这是一个 kubelet 设置,你可以在每个节点上进行配置。
要配置此设置,你需要为 kubelet 配置文件中的 `imageMaximumGCAge` 字段设置一个值。
该值被指定为 Kubernetes 持续时间。有关详细信息,请参阅词汇表中的持续时间。
例如,你可以将配置字段设置为 `12h45m`,这意味着 12 小时 45 分钟。
注意
此功能不跟踪 kubelet 重启后的镜像使用情况。如果 kubelet 重启,跟踪的镜像年龄会重置,导致 kubelet 在根据镜像年龄进行垃圾回收之前,等待完整的 `imageMaximumGCAge` 持续时间。容器垃圾回收
kubelet 根据你可以定义的以下变量对未使用的容器进行垃圾回收:
- `MinAge`:kubelet 可以垃圾回收容器的最小年龄。通过设置为 `0` 禁用。
- `MaxPerPodContainer`:每个 Pod 最多可以拥有的死容器数量。通过设置为小于 `0` 禁用。
- `MaxContainers`:集群最多可以拥有的死容器数量。通过设置为小于 `0` 禁用。
除了这些变量之外,kubelet 还会垃圾回收未识别和已删除的容器,通常从最旧的开始。
在保留每个 Pod 的最大容器数量 (`MaxPerPodContainer`) 会超出全局死容器的总允许数量 (`MaxContainers`) 的情况下,`MaxPerPodContainer` 和 `MaxContainers` 可能会相互冲突。在这种情况下,kubelet 会调整 `MaxPerPodContainer` 以解决冲突。最坏的情况是将 `MaxPerPodContainer` 降级为 `1` 并驱逐最旧的容器。此外,属于已删除 Pod 的容器在超过 `MinAge` 后也会被删除。
注意
kubelet 只会垃圾回收它管理的容器。配置垃圾回收
你可以通过配置管理这些资源的控制器的特定选项来调整资源的垃圾回收。以下页面向你展示如何配置垃圾回收:
下一步
- 了解更多关于Kubernetes 对象的属主关系。
- 了解更多关于 Kubernetes 终结器。
- 了解清理已完成 Job 的 TTL 控制器。