k8s

Finalizers 和 Owner References 在删除对象时的影响

背景

正常操作对象时,通过kubectl create/apply创建对象,再通过kubectl delete/patch来删除或修改对象。但是当对象有finalizers 和 ownerReferences 这两个属性时,可能会产生一些影响。

Finalizers

Finalizer 是带有命名空间的键,告诉 Kubernetes 除非特定的条件被满足后, 再完全删除被标记为删除的资源。 Finalizer 用来提醒控制器在删除资源之前执行哪些清理操作。

例如,你可以定义一个 Finalizer,在删除目标资源前清理相关资源或基础设施。

工作原理

  1. 修改对象,将执行删除的时间添加到 metadata.deletionTimestamp 字段。
  2. 禁止对象被删除,直到其 metadata.finalizers 字段为空。
  3. 返回 202 状态码(HTTP "Accepted")。
  4. 目标对象仍然处于终止中(Terminating)的状态。
  5. 每当一个 Finalizer 的条件被满足时,控制器就会从资源的 finalizers 字段中删除该键。
  6. metadata.finalizers 字段为空时,Kubernetes 认为删除已完成。

常见的Finalizers

一般在pv,pvc,ns中会有Finalizers键。

- kubernetes.io/pv-protection
- kubernetes.io/pvc-protection
- controller.cattle.io/namespace-auth
- kubernetes
k get pvc harbor-registry -n harbor -o yaml
k get pv pvc-34366c82-58da-4669-b0ae-ba5dc8a13f57 -o yaml
k get ns -o yaml

file
用来防止pv和pvc被意外删除。
file

file

栗子

  1. 创建一个带有Finalizers的cm
    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: mymap
    finalizers:
    - kubernetes
    EOF

    file
    myapp带有kubernetes的finalizers,cm controller会不知道如何处理这个键值,因为它通常用在ns上。

  2. 删除myapp cm
    kubectl delete configmap/mymap &

    file

  3. 查看myapp状态
    kubectl get configmap/mymap -o yaml

    file
    myapp并没有被删除,而是被更新了,添加了deletionTimestamp。因为Kubernetes看到对象包含finalizers,并阻止从etcd删除对象。

  4. 删除finalizers,再次查看myapp
    kubectl patch configmap/mymap --type json --patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]'

    file

总结

当时在删除一个带有Finalizers的对象时,它将一直处于Terminating 状态,直到控制器删除Finalizers键或使用Kubectl删除Finalizers。Finalizers键为空时,对象就会被加入到一个队列中,进而被删除。

但是在对象卡在删除状态的情况下,要避免手动移除 Finalizers。强行删除它们可能会导致集群出现问题。除非 Finalizers 依赖的应用已经被卸载或者你了解强制删除带来的影响。一般是手动清除其余的依赖对象。

Owner References

Owner References描述了一组对象之间的关系(父辈),通过这个属性可以看到对象的资源树。

Owner References 由name和uid组成,uid指向了父辈对象。

file

file

工作原理

在删除一个带有Owner References的对象时,如果是父对象,子对象也会被删除,即级联删除。比如在删除deployment时,replicaSet和pods也会在这个过程中被删除。如果删除子对象,父对象不会被删除,比如删除pod,deployment还在。

但是在k8s 1.20版本之后,可以使用kubectl --cascade=orphan参数来只删除父对象,保留子对象。

propagation policy

cascade选项链接到API中的propagation policy(传播策略),该策略允许您更改资源树中删除对象的顺序。

但是propagation policy不能通过kubectl指定,只能通过api调用。创建一个proxy连接到apiserver,再使用curl命令来删除对象。

策略类型

  • Foreground: 子对象先删除
  • Background: 父对象先删除。
  • Orphan:忽略Owner References

栗子

1.这个栗子就是使用orphan参数只删除父对象。

kubectl get configmap
NAME           DATA   AGE
mymap-child    0      13m8s
mymap-parent   0      13m8s

kubectl delete --cascade=orphan configmap/mymap-parent
configmap "mymap-parent" deleted

kubectl get configmap
NAME          DATA   AGE
mymap-child   0      13m21s

2.使用propagation policy

kubectl proxy --port=8080 &
Starting to serve on 127.0.0.1:8080

curl -X DELETE \
  localhost:8080/api/v1/namespaces/default/configmaps/mymap-parent \
  -d '{ "kind":"DeleteOptions", "apiVersion":"v1", "propagationPolicy":"Background" }' \
  -H "Content-Type: application/json"
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Success",
  "details": { ... }
}

总结

Finalizers可能会妨碍Kubernetes中删除资源,特别是这个对象包含Owner References。所以在删除前需要检查相关资源的所有Owner References和Finalizers。

分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x