1 级联和非级联删除
- k8s资源默认使用级联删除,当执行了删除一个Deployment的操作时,与其关联的ReplicaSet和Pod也会被删除。
- 日常场景中可以指定删除操作为非级联删除,则之后保留下来的资源被称为孤儿对象。
参考:ReplicaSet是Pod的owner,Deployment是ReplicaSet的owner,当ReplicaSet被级联删除时,那么从属于它的Pod也会被删除;同理,当Deployment被级联删除时,从属于它的ReplicaSet、Pod都会被删除。
2 级联删除模式
级联删除有两种模式:
- 前台(Foreground)
- 后台(Background)
2.1 Foreground
整个删除过程完成之前,被删除对象一直是可见的
-
api server将对象的metadata.deletionTimestamp字段设置为该对象被标记为要删除的时间点
-
api server将metadata.finalizers字段设置为foregroundDeletion
-
对象依赖项全部清理完成之后再清理对象自身,在依赖项被清理完成之前该对象会一直可见。
2.2 Background
对象会被立即删除,controller会负责继续在后台清理其依赖项,对外不可见。
3 Finalizers
3.1 介绍
Finalizers 字段属于 Kubernetes GC 垃圾收集器,是一种删除拦截机制,能够让控制器实现异步的删除前(Pre-delete)回调。其存在于任何一个资源对象的 Meta[1] 中,在 k8s 源码中声明为 []string
,该 Slice 的内容为需要执行的拦截器名称。
3.2 实现原理
对带有 Finalizer 的对象的第一个删除请求会为其 metadata.deletionTimestamp
设置一个值,但不会真的删除对象。一旦此值被设置,finalizers 列表中的值就只能被移除。
当 metadata.deletionTimestamp
字段被设置时,负责监测该对象的各个控制器会通过轮询对该对象的更新请求来执行它们所要处理的所有 Finalizer。当所有 Finalizer 都被执行过,资源被删除。
metadata.deletionGracePeriodSeconds
的取值控制对更新的轮询周期。
每个控制器要负责将其 Finalizer 从列表中去除。
每执行完一个就从 finalizers
中移除一个,直到 finalizers
为空,之后其宿主资源才会被真正的删除。
3.3 删除过程
配置了Finalizers的对象的删除被分为三个步骤:
- 将被删除对象的metadata.deletionTimestamp更新为当前时间。
- 禁止对象被删除,直到metadata.finalizers字段为空。
- 返回状态码202
简言之,添加了Finalizers的对象被执行删除操作后将删除时间戳更新为当前发生删除请求的时间来表示该资源已请求删除,但是在拿掉Finalizers配置之前etcd并不会真正删除该对象。
3.4 使用场景
当资源被删除时,虽然能 get 到这个事件,但是本地 cache 里面已经查不到资源的任何信息了,不利于做一些资源回收的工作,通过添加 finalizers ,资源被删除时候我们还可以查询到资源(只读),此时可以处理一系列 pre-hook 的任务,任务都处理完后将 finalizers 更新为空,此时 kubernetes 的 GC 就会自动帮我们完全删除资源了。
以下命令可以移除资源的Finalizers,之后对象会自动进入删除队列,从注册表中最终删除:
kubectl patch configmap configmapName -n namespace --type json -p '[ { "op": "remove", "path": "/metadata/finalizers" } ]'
3.5 案例
一个常见的 Finalizer 的例子是 kubernetes.io/pv-protection: