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