Kubernetes 的垃圾回收
首先
在这篇文章中,我们将概述Kubernetes的垃圾回收机制。
垃圾收集是什么?
一般的的垃圾收集(GC)是指程序自动释放动态分配的不再需要的内存空间的功能(来源于维基百科),而在Kubernetes中所称的GC包括以下内容。
オブジェクトの GC
API Server (etcd) に保持されている Kubernetes のオブジェクトのうち、かつてオーナーがいたが、現時点でもはやオーナーがいないようなオブジェクトの削除を行う GC
Pod の GC
存在しない Node に配置されている Pod とスケジュールされずに Terminating になった Pod を削除する GC
Image GC
Node に保持されているコンテナイメージのうち、かつて起動したが現時点ではもはや利用されなくなったコンテナイメージの削除を行うGC
这次我们将详细研究这些对象中的垃圾回收。其他的内容我会在有兴趣的时候写调查文章。
对象的垃圾回收
在Kubernetes中,当删除对象时,有时需要删除作为其父级的子对象。在这种情况下,子对象的删除是通过垃圾回收(GC)来进行的。(例如,在使用kubectl删除部署时,预计会删除副本集和Pod,这是一种情况)Kubernetes 1.8之前,kubectl和控制器直接进行子对象的删除,但现在已经通过GC进行删除。有关详细信息,请参考KEP。
另外,由于Kubernetes是一个分布式系统,它无法原子更新各种处理,因此在处理过程中如果发生失败,可能会导致已经不存在的孤儿对象出现。对于这些孤儿(orphan)对象,系统会定期进行垃圾回收(删除)。
现在让我们来看看GC是如何进行回收的,但在此之前,我们先来看看GC使用的一些领域。
所有者引用
当执行诸如 `kubectl get pod -o yaml` 的命令时,metadata 中可能会创建一个名为 ownerReferences 的字段。以下是一个示例。
apiVersion: v1
kind: Pod
metadata:
...
ownerReferences:
- apiVersion: apps/v1
controller: true
blockOwnerDeletion: true
kind: ReplicaSet
name: my-repset
uid: d9607e19-f88f-11e6-a518-42010a800195
...
这个 ownerReferences 用于GC判断对象的所有者,主要在控制器自动创建对象时自动设置。
终结器
Finalizers是CRD(Custom Resource Definition)使用者非常熟悉的功能,简单来说,它是为了阻止删除操作而执行的预处理功能。这样可以轻松地包含由该对象创建的子对象的删除以及对Kubernetes外部资源的清理处理。
Finalizers信息也保存在metadata的finalizers字段中,如果该字段有值,那么对象将不会被删除。管理该值需要单独准备一个控制器来管理,每个Finalizer都有相应的控制器负责执行清理处理。
详细信息可以参考相关资源。
与 GC 相关的 Finalizers 包括以下内容。
-
- FinalizerOrphanDependents: “orphan”
propagationPolicy Orphan で削除したときに設定される
FinalizerDeleteDependents: “foregroundDeletion”
propagationPolicy Foreground で削除したときに設定される
如果设置了这些 Finalizers,将通过以下GC进行删除,并在完成后从metadata.finalizers中删除。
GC的行动
根据读取的源代码,似乎有以下组件,并且可以粗略地描述如下。
-
- Scanner: APIが現在提供しているリソースの一覧を取得して、Monitor を生成し(①)各リソースの変更を検知する(②)
-
- DependencyGraphBuilder
Scanner から提供された検知のイベントを元に DAG(Directed acyclic graph) を作成し、Delete や Orphan にするオブジェクトがあれば workqueue に入れる(③)
ここのグラフの作成時に OwnerReferences を利用してオーナーを判断しています
Finalizers は DELETE API の呼び出したときに Option に指定によって API Server が設定し、GC はそれを見て各 worker に処理を渡し子オブジェクトの処理を行います
Worker
DeleteWorker: workqueue からオブジェクトを取得して依存関係を整理してオブジェクトを削除する④
OrphanWorker: 依存関係を整理して Orphan Finalizer を削除する④

收回对象
寻找可回收的对象时,我尝试找到文件等相关文档,但具体记录的来源未能找到,因此我从源代码中读取了信息。
基本上,根据我所理解的范围,GetDeletableResources函数获取的资源中未被指定为Ignore的资源将成为回收的对象。
/api と /apis の API から取得できる APIGroup に所属するリソース
delete, list, watch の verb をサポートするリソース
https://github.com/kubernetes/kubernetes/blob/v1.17.0/pkg/controller/garbagecollector/garbagecollector.go#L650
Innore に指定されていない
https://github.com/kubernetes/kubernetes/blob/v1.17.0/pkg/controller/garbagecollector/graph_builder.go#L192
免费赠品
动态共享通知者
我记得当DynamicSharedInformer被添加时,我听说是为了垃圾回收机制,但实际查看源代码(https://github.com/kubernetes/kubernetes/blob/v1.17.0/pkg/controller/garbagecollector/graph_builder.go#L127)发现它似乎是通过单独的Informer进行监视的。根据我初步的搜索结果,好像k/k并没有使用DynamicSharedInformer,所以我想知道它是不是还没有实现,或者有其他的原因。
文献引用
-
- https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/garbage-collection.md
-
- https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/synchronous-garbage-collection.md
-
- https://thenewstack.io/deletion-garbage-collection-kubernetes-objects/
- https://www.firehydrant.io/blog/dynamic-kubernetes-informers/