每当删除namespace或pod 等一些Kubernetes资源时,有时资源状态会卡在terminating,很长时间无法删除,甚至有时增加--force flag(强制删除)之后还是无法正常删除。这时就需要edit该资源,将字段finalizers设置为null,之后Kubernetes资源就正常删除了。
当删除pod时有时会卡住,pod状态变为terminating,无法删除pod
(1)强制删除
kubectl delete pod xxx -n xxx --force --grace-period=0
(2)如果强制删除还不行,设置finalizers为空
(如果一个容器已经在运行,这时需要对一些容器属性进行修改,又不想删除容器,或不方便通过replace的方式进行更新。kubernetes还提供了一种在容器运行时,直接对容器进行修改的方式,就是patch命令。)
kubectl patch pod xxx -n xxx -p '{"metadata":{"finalizers":null}}'
这样pod就可以删除了。
基本的delete命令状态图:
尽管此操作很简单,但其他因素可能会干扰删除,包括finalizers和owner references。
K8s 中对象删除基本流程如下:
(1)客户端提交删除请求到 API Server(可选传递 GracePeriodSeconds 参数)
(2)API Server 做 Graceful Deletion 检查(若对象实现了 RESTGracefulDeleteStrategy 接口,会调用对应的实现并返回是否需要进行 Graceful 删除)
(3)API Server 检查 Finalizers 并结合是否需要进行 graceful 删除,来决定是否立即删除对象(若对象需要进行 graceful 删除,更新 metadata.DeletionGracePeriodSecond 和metadata.DeletionTimestamp 字段,不从存储中删除对象;若对象不需要进行 Graceful 删除时
:metadata.Finalizers 为空,直接删除。metadata.Finalizers 不为空,不删除,只更新 metadata.DeletionTimestamp。
Finalizers 字段属于 Kubernetes GC 垃圾收集器,是一种删除拦截机制,能够让控制器实现异步的删除前(Pre-delete)回调。其存在于任何一个资源对象的 Meta中,在 k8s 源码中声明为 []string
,该 Slice 的内容为需要执行的拦截器名称。
常见用途:
(1)控制器在对象刚创建时,在 metadata.finalizers 写入一个自定义字符串
(2)APIServer 在 metadata.finalizers 数组不为空时,不会删除对象。此逻辑是硬性,对所有对象生效。
(3)当有客户端删除对象时,控制器可以发现对象出于删除状态,然后执行相应的 pre-delete 逻辑。执行完成后,将之前写入的自定义字符串移除。
(4)当所有控制器都将各自写入到 metadata.finalizers 的字符串移除后。API Server 就自动将对象删除。
注:若对象同时实现了 graceful 删除策略,删除请求需要满足 GracefulPeriodSeconds = 0 条件
APIServer 在处理 Pod 删除请求时,会根据 pod 的 pod.Spec.TerminationGracePeriodSeconds 和 deleteOptions.GracefulPeriodSeconds 综合判断,是否进行 Graceful 删除。若是,并判断最终的 GracefulPeriodSeconds 该设置为多少。
(1)当删除请求选项中有设置 GracefulPeriodSeconds,以选项中为准。若没有,使用 pod.Spec.TerminationGracePeriodSeconds 。若 pod.Spec.TerminationGracePeriodSeconds 也没有设置,使用默认值 0 。
(2)当 Pod 没有调度,或者已经结束(无论成功还是失败)。GracePeriodSeconds 都重置为 0.
GracePeriodSeconds 为 0 表示不进行优雅删除。非 0 表示进行优雅删除。Pod 的默认优雅删除时间为 30 s ,在对象创建时配置在 pod.Spec.TerminationGracePeriodSeconds 字段。
优雅删除的目的是给予 Kubelet 一定时间对 Pod 实行优雅退出。在用户对 Pod 执行 Delete 操作时,Pod 对象不会立即从 API Server 删除,而只是进入 Termination 阶段。Kubelet 会对运行中的 Pod 的容器发送 TERM 信号,通知其退出。并执行用户配置的 preStop hooks 逻辑。当优雅时间过了之后,再开始使用 KILL 信号尝试强制杀容器。
当 kubelet 将 Pod 清理干净后,就会使用 GracefulPeriodSeconds==0 的参数执行删除操作。
因为 Pod 实现优雅删除目的是为了给予 Kubelet 时间做资源清理操作,所以这也是为什么在设置 GracePeriodSeconds 阶段,若 Pod 没有被调度或者已经退出,也就可以直接允许立即删除 (GracePeriodSeconds = 0)。
注:
在了解以上机制后,对象无法删除无外乎以下两个原因:
两种机制都有强制跳过的方案:
但应仅当关联清理工作已经不重要或已手动执行时,才可选择。不然容易照成数据、状态不一致等。
参考自(http://cache.baiducontent.com/c?m=0xZGNnAjSzsVUWz26c6ab6_xOZAVpF9kIAa06vEoIPs5q2EdFL8vYpWPCdzecF_UtC-022Xad3qrPTvPURmF3vdMwmhIVA8_oAiZVHhP5zdPvUBc6kxLNsvFKbYAdbyj&p=906cc54ad3c717be499fc7710f56&newp=8b2a9715d9c645f20abfca22584092695d0fc20e38dcd601298ffe0cc4241a1a1a3aecbf2c281706d6c27d6c07af4b5cebf230743d0034f1f689df08d2ecce7e&s=cfcd208495d565ef&user=baidu&fm=sc&query=k8s+finalizers&qid=c7766d2b00019dc6&p1=10)
(https://www.stackovercloud.com/2021/05/14/blog-using-finalizers-to-control-deletion/)