终结器
终结器是命名空间键,它告诉 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
对象。当 PersistentVolume
对象被 Pod 使用时,Kubernetes 会添加 pv-protection
终结器。如果你尝试删除 PersistentVolume
,它会进入 Terminating
状态,但控制器无法删除它,因为存在终结器。当 Pod 停止使用 PersistentVolume
时,Kubernetes 会清除 pv-protection
终结器,然后控制器会删除卷。
注意
当你
DELETE
一个对象时,Kubernetes 会为该对象添加删除时间戳,然后立即开始限制对现在正在等待删除的对象的.metadata.finalizers
字段的更改。你可以删除现有的终结器(从finalizers
列表中删除条目),但不能添加新的终结器。你也不可以在设置对象的时间戳之后修改deletionTimestamp
。请求删除后,你无法恢复此对象。唯一的方法是删除它并创建一个新的类似对象。
所有者引用、标签和终结器
就像 标签,所有者引用 描述了 Kubernetes 中对象之间的关系,但用于不同的目的。当 控制器 管理对象(如 Pod)时,它使用标签来跟踪对相关对象组的更改。例如,当 作业 创建一个或多个 Pod 时,作业控制器会将标签应用于这些 Pod,并跟踪集群中具有相同标签的任何 Pod 的更改。
作业控制器还会将所有者引用添加到这些 Pod,指向创建这些 Pod 的作业。如果你在这些 Pod 正在运行时删除作业,Kubernetes 会使用所有者引用(而不是标签)来确定集群中哪些 Pod 需要清理。
当 Kubernetes 在目标删除资源上识别所有者引用时,它也会处理终结器。
在某些情况下,终结器可能会阻止删除依赖对象,这会导致目标所有者对象比预期保留更长时间而无法完全删除。在这种情况下,你应该检查目标所有者和依赖对象的终结器和所有者引用,以排查原因。
注意
在对象卡在删除状态的情况下,请避免手动删除终结器以允许删除继续。终结器通常是出于某种原因添加到资源的,因此强行删除它们可能会导致集群出现问题。这只有在了解终结器的用途并在其他方式中实现时才应进行(例如,手动清理某些依赖对象)。下一步
- 在 Kubernetes 博客上阅读 使用终结器控制删除。