垃圾回收
垃圾收集是 Kubernetes 用来清理集群资源的各种机制的总称。这可以清理如下资源:
- 已终止的 Pod
- 已完成的 Job
- 没有 Owner 引用(所有者引用)的对象
- 未使用的容器和容器镜像
- 具有 StorageClass
Delete
回收策略的动态制备的 PersistentVolume - 过时或已过期的 CertificateSigningRequest (CSR)
- 在以下场景中被删除的 节点
- 在使用 云控制器管理器 的云环境中
- 在使用类似于云控制器管理器的插件的本地环境中
- Node Lease 对象
所有者和从属对象
Kubernetes 中的许多对象通过Owner 引用相互关联。Owner 引用告诉控制平面哪些对象依赖于其他对象。Kubernetes 使用 Owner 引用为控制平面和其他 API 客户端提供在删除对象之前清理相关资源的机会。在大多数情况下,Kubernetes 会自动管理 Owner 引用。
所有权不同于一些资源也使用的标签(labels)和选择器(selectors)机制。例如,考虑一个创建 EndpointSlice
对象的 Service。该 Service 使用 labels 来让控制平面确定哪些 EndpointSlice
对象是用于该 Service 的。除了 labels,代表 Service 管理的每个 EndpointSlice
都有一个 Owner 引用。Owner 引用有助于 Kubernetes 的不同部分避免干扰它们不控制的对象。
注意
跨命名空间 Owner 引用在设计上是不允许的。命名空间的 Dependent 可以指定集群范围的或命名空间的 Owner。命名空间的 Owner 必须存在于与 Dependent 相同的命名空间中。如果不存在,则 Owner 引用被视为不存在,并且一旦验证所有 Owner 都不存在,Dependent 就会被删除。
集群范围的 Dependent 只能指定集群范围的 Owner。在 v1.20+ 版本中,如果集群范围的 Dependent 将命名空间的对象种类指定为 Owner,则该引用被视为无法解析的 Owner 引用,并且无法被垃圾收集。
在 v1.20+ 版本中,如果垃圾收集器检测到无效的跨命名空间 ownerReference
,或者带有引用命名空间对象种类的 ownerReference
的集群范围 Dependent,则会报告一个警告 Event,其原因为 OwnerRefInvalidNamespace
,涉及对象为该无效的 Dependent。你可以通过运行 kubectl get events -A --field-selector=reason=OwnerRefInvalidNamespace
来检查此类 Event。
级联删除
Kubernetes 检查并删除不再具有 Owner 引用的对象,例如删除 ReplicaSet 时留下的 Pod。删除对象时,你可以控制 Kubernetes 是否自动删除对象的 Dependent,这个过程称为级联删除。级联删除有两种类型,如下所示:
- 前台级联删除
- 后台级联删除
你还可以使用 Kubernetes 的finalizers 来控制垃圾收集如何以及何时删除具有 Owner 引用的资源。
前台级联删除
在前台级联删除中,你正在删除的 Owner 对象首先进入 正在删除 状态。在此状态下,Owner 对象会发生以下情况:
- Kubernetes API 服务器将对象的
metadata.deletionTimestamp
字段设置为标记对象删除的时间。 - Kubernetes API 服务器还会将
metadata.finalizers
字段设置为foregroundDeletion
。 - 对象在 Kubernetes API 中保持可见,直到删除过程完成。
Owner 对象进入 正在删除 状态后,控制器会删除它所知的 Dependent。删除所有已知的 Dependent 对象后,控制器会删除 Owner 对象。此时,该对象在 Kubernetes API 中不再可见。
在前台级联删除期间,唯一阻止 Owner 删除的 Dependent 是那些具有 ownerReference.blockOwnerDeletion=true
字段且存在于垃圾收集控制器缓存中的对象。垃圾收集控制器缓存可能不包含无法成功列出/监视的资源类型对象,或者与 Owner 对象删除同时创建的对象。参阅使用前台级联删除了解更多信息。
后台级联删除
在后台级联删除中,Kubernetes API 服务器会立即删除 Owner 对象,垃圾收集控制器(自定义或默认)会在后台清理 Dependent 对象。如果存在 Finalizer,它会确保对象在所有必需的清理任务完成之前不会被删除。默认情况下,除非你手动使用前台删除或选择使 Dependent 对象成为孤立对象,否则 Kubernetes 使用后台级联删除。
参阅使用后台级联删除了解更多信息。
孤立的 Dependent
当 Kubernetes 删除 Owner 对象时,留下的 Dependent 称为 孤立 对象。默认情况下,Kubernetes 会删除 Dependent 对象。要了解如何覆盖此行为,参阅删除 Owner 对象并孤立 Dependent。
未使用的容器和镜像的垃圾收集
kubelet 每五分钟对未使用的镜像执行垃圾收集,每分钟对未使用的容器执行垃圾收集。应避免使用外部垃圾收集工具,因为这些工具可能会破坏 kubelet 的行为并删除应该存在的容器。
要配置未使用的容器和镜像垃圾收集选项,可以使用配置文件调整 kubelet,并使用 KubeletConfiguration
资源类型更改与垃圾收集相关的参数。
容器镜像生命周期
Kubernetes 通过其 镜像管理器(它是 kubelet 的一部分)并在 cadvisor 的协作下管理所有镜像的生命周期。kubelet 在做出垃圾收集决策时考虑以下磁盘使用限制:
HighThresholdPercent
LowThresholdPercent
磁盘使用率高于配置的 HighThresholdPercent
值时会触发垃圾收集,垃圾收集会根据镜像上次使用的时间顺序删除镜像,从最旧的开始。kubelet 会一直删除镜像直到磁盘使用率达到 LowThresholdPercent
值。
未使用的容器镜像的垃圾收集
Kubernetes v1.30 [beta]
(默认启用:true)作为一个 Beta 功能,你可以指定本地镜像可以未被使用的最长时间,而不管磁盘使用率如何。这是一个 kubelet 设置,你可以为每个节点配置。
要配置此设置,你需要在 kubelet 配置文件中设置 imageMaximumGCAge
字段的值。
该值指定为 Kubernetes duration。参阅术语表中的duration了解更多详情。
例如,你可以将配置字段设置为 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 的 Finalizer。
- 了解清理已完成 Job 的 TTL 控制器。