背景
正常操作对象时,通过kubectl create/apply
创建对象,再通过kubectl delete/patch
来删除或修改对象。但是当对象有finalizers 和 ownerReferences 这两个属性时,可能会产生一些影响。
Finalizers
Finalizer 是带有命名空间的键,告诉 Kubernetes 除非特定的条件被满足后, 再完全删除被标记为删除的资源。 Finalizer 用来提醒控制器在删除资源之前执行哪些清理操作。
例如,你可以定义一个 Finalizer,在删除目标资源前清理相关资源或基础设施。
工作原理
- 修改对象,将执行删除的时间添加到
metadata.deletionTimestamp
字段。 - 禁止对象被删除,直到其
metadata.finalizers
字段为空。 - 返回 202 状态码(HTTP "Accepted")。
- 目标对象仍然处于终止中(Terminating)的状态。
- 每当一个 Finalizer 的条件被满足时,控制器就会从资源的 finalizers 字段中删除该键。
- 当
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
用来防止pv和pvc被意外删除。
栗子
- 创建一个带有Finalizers的cm
cat <<EOF | kubectl create -f - apiVersion: v1 kind: ConfigMap metadata: name: mymap finalizers: - kubernetes EOF
myapp带有kubernetes的finalizers,cm controller会不知道如何处理这个键值,因为它通常用在ns上。 - 删除myapp cm
kubectl delete configmap/mymap &
- 查看myapp状态
kubectl get configmap/mymap -o yaml
myapp并没有被删除,而是被更新了,添加了deletionTimestamp。因为Kubernetes看到对象包含finalizers,并阻止从etcd删除对象。 - 删除finalizers,再次查看myapp
kubectl patch configmap/mymap --type json --patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]'
总结
当时在删除一个带有Finalizers的对象时,它将一直处于Terminating 状态,直到控制器删除Finalizers键或使用Kubectl删除Finalizers。Finalizers键为空时,对象就会被加入到一个队列中,进而被删除。
但是在对象卡在删除状态的情况下,要避免手动移除 Finalizers。强行删除它们可能会导致集群出现问题。除非 Finalizers 依赖的应用已经被卸载或者你了解强制删除带来的影响。一般是手动清除其余的依赖对象。
Owner References
Owner References描述了一组对象之间的关系(父辈),通过这个属性可以看到对象的资源树。
Owner References 由name和uid组成,uid指向了父辈对象。
工作原理
在删除一个带有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。