终结器
Finalizer 是命名空间键,它告诉 Kubernetes 在完全删除标记为删除的资源之前,等待满足特定条件。Finalizer 通知控制器清理被删除对象拥有的资源。
当你告诉 Kubernetes 删除一个为其指定了 finalizer 的对象时,Kubernetes API 通过填充 .metadata.deletionTimestamp
来标记该对象为待删除,并返回 202
状态码(HTTP“已接受”)。目标对象在控制平面或其他组件执行 finalizer 定义的操作时保持在终止状态。这些操作完成后,控制器会从目标对象中删除相关的 finalizer。当 metadata.finalizers
字段为空时,Kubernetes 认为删除已完成并删除该对象。
你可以使用 finalizer 来控制资源的垃圾收集。例如,你可以定义一个 finalizer,以便在控制器删除目标资源之前清理相关的资源或基础设施。
你可以使用 finalizer 来控制垃圾收集对象,方式是通知控制器在删除目标资源之前执行特定的清理任务。
Finalizer 通常不指定要执行的代码。相反,它们通常是特定资源上类似于注解的键列表。Kubernetes 会自动指定一些 finalizer,但你也可以指定自己的 finalizer。
Finalizer 的工作原理
当你使用清单文件创建资源时,你可以在 metadata.finalizers
字段中指定 finalizer。当你尝试删除资源时,处理删除请求的 API 服务器会注意到 finalizers
字段中的值,并执行以下操作:
- 修改对象,添加一个
metadata.deletionTimestamp
字段,其中包含你开始删除的时间。 - 阻止删除该对象,直到其
metadata.finalizers
字段中的所有项都被移除。 - 返回
202
状态码(HTTP“已接受”)。
管理该 finalizer 的控制器会注意到对对象的更新,其中设置了 metadata.deletionTimestamp
,表明已请求删除该对象。然后,控制器会尝试满足为该资源指定的 finalizer 的要求。每次满足一个 finalizer 条件时,控制器都会从资源的 finalizers
字段中删除该键。当 finalizers
字段为空时,具有 deletionTimestamp
字段设置的对象会自动删除。你还可以使用 finalizer 来阻止删除非托管资源。
一个常见的 finalizer 示例是 kubernetes.io/pv-protection
,它可以防止意外删除 PersistentVolume
对象。当一个 PersistentVolume
对象被 Pod 使用时,Kubernetes 会添加 pv-protection
finalizer。如果你尝试删除 PersistentVolume
,它会进入 Terminating
状态,但控制器无法删除它,因为 finalizer 存在。当 Pod 停止使用 PersistentVolume
时,Kubernetes 会清除 pv-protection
finalizer,然后控制器会删除该卷。
注意
当你
DELETE
一个对象时,Kubernetes 会为该对象添加删除时间戳,然后立即开始限制对该现在处于待删除状态的对象的.metadata.finalizers
字段的更改。你可以删除现有的 finalizer(从finalizers
列表中删除一个条目),但你不能添加新的 finalizer。一旦设置,你也不能修改对象的deletionTimestamp
。请求删除后,你无法复活此对象。唯一的方法是删除它并创建一个新的类似对象。
所有者引用、标签和 finalizer
像标签一样,所有者引用描述了 Kubernetes 中对象之间的关系,但用途不同。当一个控制器管理诸如 Pod 之类的对象时,它会使用标签来跟踪相关对象组的更改。例如,当Job 创建一个或多个 Pod 时,Job 控制器会将标签应用于这些 Pod,并跟踪集群中具有相同标签的任何 Pod 的更改。
Job 控制器还会将所有者引用添加到这些 Pod,指向创建 Pod 的 Job。如果在这些 Pod 运行时删除 Job,Kubernetes 会使用所有者引用(而不是标签)来确定集群中哪些 Pod 需要清理。
当 Kubernetes 识别出要删除的资源上的所有者引用时,也会处理 finalizer。
在某些情况下,finalizer 可能会阻止删除依赖对象,这可能会导致目标所有者对象在未被完全删除的情况下保留的时间比预期的长。在这些情况下,你应该检查目标所有者对象和依赖对象上的 finalizer 和所有者引用,以找出原因。
注意
如果对象卡在删除状态,请避免手动删除 finalizer 以允许继续删除。通常出于某种原因将 finalizer 添加到资源中,因此强制删除它们可能会导致集群出现问题。只有在了解 finalizer 的目的并且通过其他方式完成 finalizer 的目的时(例如,手动清理一些依赖对象)才应执行此操作。下一步
- 阅读 Kubernetes 博客上的使用 Finalizer 控制删除。