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