在 kubernetes v1.7 之前,集群内相关联的对象级联删除是在 client 做的,比如 client 需要先把 ReplicaSet 关联的 Pods 都级联删除了,再删除 ReplicaSet。在 v1.7 的时候,garbage collector design proposal 被提出,为所有的对象提供了 service-side 通用的垃圾回收机制来简化流程,同时还提供了 finalizer framework 来为删除添加自定义的流程

OwnerReference

Kubernetes 中在不同的 Objects 中通过 OwnerReference 维护它们之间的『从属关系』,比如一个 ReplicaSet 会在它的 OwnerReference 中指向一个 Deployment,Deployment 就是它的父对象 "owner",而 ReplicaSet 是 Deployment 的子对象 "dependent"

type ObjectMeta struct {
	...
	OwnerReferences []OwnerReference
}

type OwnerReference struct {
	// Version of the referent.
	APIVersion string
	// Kind of the referent.
	Kind string
	// Name of the referent.
	Name string
	// UID of the referent.
	UID types.UID
}

Finalizer framework

Finalizers framework 在 ObjectMeta 中添加了新的 Finalizers 字段,并在 APIServer 中,于 Object 的 delete 和 update 的流程中插入了 finalizer 的逻辑,用来 block 对象删除,从而引入自定义的清理逻辑。

type ObjectMeta struct {
	…
	Finalizers []string
}

GracefulDelete

GracefulDelete 会优先于 Finalizer Delete Process,目前在 k8s 中只有 pod 支持 gracefulDelete 的流程,这个流程是为了保证正在 Running 的 pod 在被删除之前有足够的时间能退出程序

在首次发起删除 pod 时,如果 pod 正在 Running,则会进入 GracefulDelete 的流程,只会把 pod 标记删除,即设置 pod.ObjectMeta.DelationTimestamp ,然后由 kubelet 来发起下次的删除请求

Finalizer Delete Process

实际上的删除流程除了 Finalizer 外还需要考虑其他的配置比如 options.GracePeriod 等,为了方便理解,简化的流程如下

  1. APIServer 收到删除 Object 的请求,ObjectMeta.Finalizers 如果 Finalizers 不为空,则只把 Object 标记删除(设置 ObjectMeta.DeletionTimestamp),视为 Update 事件
  2. Finalizer Controller 监听到事件之后,知道 Object 进入的删除的流程,则对 Object 做删除前的清理逻辑,处理成功之后,更新 ObjectMeta.Finalizers 将自己的 Finalizer identifier 字符串删除掉
  3. APIServer 收到更新 Object Finalizers 的请求,发现这个 Object 已经处于删除的流程中,且 Finalizer 已经被清空,则把它从本地缓存和 ETCD 中删除掉

Deletion Propagation Policy

在 k8s 内有三种 Object 删除传播的策略