终结器

终结器(Finalizers)是带有命名空间的键,用于告知 Kubernetes 在完全删除被标记为删除的 资源 之前,必须满足特定的条件。终结器会提醒 控制器 清理被删除对象所拥有的资源。

当你指示 Kubernetes 删除一个指定了终结器的对象时,Kubernetes API 会通过填充 .metadata.deletionTimestamp 来将该对象标记为删除,并返回一个 202 状态码(HTTP “已接受”)。在控制平面或其他组件执行终结器所定义的动作时,目标对象会保持在终止(Terminating)状态。这些动作完成后,控制器会从目标对象中移除相关的终结器。当 metadata.finalizers 字段为空时,Kubernetes 会认为删除已完成并删除该对象。

你可以使用终结器来控制资源的 垃圾回收。例如,你可以定义一个终结器,以便在控制器删除正在被终结的对象之前,清理相关的 API 资源 或基础设施。

你可以使用终结器来控制 垃圾回收 对象,方法是提醒 控制器 在删除目标资源之前执行特定的清理任务。

终结器通常不指定要执行的代码。相反,它们通常是特定资源上的一组键,类似于注解(annotations)。Kubernetes 会自动指定一些终结器,但你也可以指定自己的终结器。

终结器(Finalizers)工作原理

当你使用清单文件创建资源时,可以在 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,你也无法修改它。

  • 一旦请求了删除,你就无法恢复该对象。唯一的方法是将其删除并创建一个新的类似对象。

说明

自定义终结器名称必须是公有的全限定终结器名称,例如 example.com/finalizer-name。Kubernetes 会强制执行此格式;如果对于任何自定义终结器,修改操作未采用全限定终结器名称,API 服务器会拒绝写入该对象。

属主引用、标签和终结器

标签(labels) 一样,属主引用(owner references) 描述了 Kubernetes 中对象之间的关系,但用途不同。当 控制器 管理 Pod 等对象时,它使用标签来跟踪相关对象组的变更。例如,当 Job 创建一个或多个 Pod 时,Job 控制器会将标签应用于这些 Pod,并跟踪集群中具有相同标签的任何 Pod 的变更。

Job 控制器还会向这些 Pod 添加 属主引用,指向创建这些 Pod 的 Job。如果你在这些 Pod 运行时删除 Job,Kubernetes 会使用属主引用(而非标签)来确定集群中哪些 Pod 需要清理。

当 Kubernetes 在被标记为删除的资源上识别出属主引用时,也会处理终结器。

在某些情况下,终结器可能会阻塞从属对象的删除,这可能导致目标属主对象保持的时间比预期长,且无法被完全删除。在这种情况下,你应该检查目标属主对象和从属对象上的终结器和属主引用,以排查原因。

说明

如果对象卡在删除状态,请避免手动移除终结器以强制进行删除。添加终结器到资源通常是有原因的,因此强制移除它们可能会导致集群出现问题。只有在理解了终结器的目的,并且该目的已通过其他方式(例如,手动清理某些从属对象)达成时,才应执行此操作。

接下来