09-K8S Basic-kubernetes垃圾回收器 Garbage Collection(GC)
阿新 • • 發佈:2021-06-14
一、Kubernetes之Garbage Collection
- 在以前的博文中介紹過如何配置kubelet,按策略刪除無用image、正常或者異常終止不會再啟動的container,以節省資源。kubelet回收的物件在容器層面。那麼kubernetes層面的物件,比如podReplicaSet、Replication Controller、Deployment、StatefulSet、DaemonSet等型別的物件,垃圾回收又是如何呢?
- 實際上,按理說以上的kubernetes物件並不會產生垃圾,物件一直都存在,除非使用者或者某種控制器將物件刪除。這裡稱為"Garbage Collection"不太準確,實際上它想講的是在執行刪除操作時如何控制物件之間的依賴關係。比如,Deployment物件建立ReplicaSet物件,ReplicaSet物件又建立pod物件,那麼在刪除Deployment時,是否需要刪除與之相依賴的ReplicaSet與pod呢?
1.1、從物件與根物件(Owners and dependents)
- 某些kubernetes物件是其它物件的owner。比如ReplicaSet物件就是其所管理的pod物件的owner,本文稱這類物件為“根物件”。而被管理的pod對ReplicaSet存在dependent,pod物件通過metadata.ownerReferences欄位指向其依賴的物件,本文稱這類物件為“從物件”。在kubernetes1.8中,ReplicationController, ReplicaSet, StatefulSet, DaemonSet, Deployment, Job and CronJob自動向其建立、收養的物件新增metadata.ownerReferences欄位的值,當然也可以手動設定。以下是擁有3個pod的ReplicaSet設定檔案:
apiVersion: apps/v1 kind: ReplicaSet metadata: name: my-repset spec: replicas: 3 selector: matchLabels: pod-is-for: garbage-collection-example template: metadata: labels: pod-is-for: garbage-collection-example spec: containers: - name: nginx 建立此ReplicaSet: kubectl create -f https://k8s.io/examples/controllers/replicaset.yaml 檢視: kubectl get pods --output=yaml 結果如下:確認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
1.2、如何控制垃圾回收刪除從物件?
- 當刪除一個物件時,可以控制以何種方式刪除其從物件,自動刪除從物件稱為級聯刪除(cascading deletion)。有background與foreground兩種方式。也可以不只刪除根物件不刪除從物件。
1.2.1、前臺級聯刪除
- 前臺級聯刪除時,根物件首先進入"deletion in progress"狀態,在"deletion in progress"狀態下,存在如下事實:
- 如果通過REST API訪問根物件,仍然可見。
- 根物件的deletionTimestamp被設定。
- 根物件元資料metadata.finalizers包含"foregroundDeletion"。
- 一旦根物件的狀態被設定成"deletion in progress",垃圾回收器開始啟動對從物件的刪除。如果從物件的object有“ownerReference.blockOwnerDeletion=true”屬性,那麼垃圾回收器必需等到此類從物件被刪除完成以後,才可以刪除根物件。否則垃圾回收器啟動對從物件的刪除後立即刪除根物件。
- “ownerReference.blockOwnerDeletion=true”會延遲根物件的刪除。在kubernetes1.7版本中增加了一個admission controller,它根據根物件訪問許可權,對將ownerReference.blockOwnerDeletion設定成true的操作進行訪問控制,防止未經授權的使用者將ownerReference.blockOwnerDeletion的值設定成true,從而延遲根物件的刪除。
- 如果從物件的ownerReferences由某種控制器設定,那麼使用者最好不要手動修改其值。
1.2.2、後臺級聯刪除
- 後臺級聯刪除時,kubernetes立即刪除根物件並返回。垃圾回收器在後臺刪除其從物件。
1.2.3、不刪除從物件
- 只刪除根物件不刪除從物件,這種方式稱為“Orphan”,保留下來的從物件變成了“孤兒”。
1.3、在具體操作時設定刪除策略
-
在執行具體的操作請求時,通過設定刪除請求中的"propagationPolicy"欄位為 “Orphan”, “Foreground”, or “Background”中的一種,選擇上述三種刪除策略中的一種。
-
在kubernetes1.9以前,對大部分控制器的刪除,預設策略是"Orphan"(注意本段中說的預設值指REST API的預設行為,不是kubectl命令),包含ReplicationController, ReplicaSet, StatefulSet, DaemonSet, and Deployment,也就是在刪除根物件時不刪除從物件。並且當apiVersion是extensions/v1beta1, apps/v1beta1, and apps/v1beta2時,除非特別指定,預設刪除策略仍然是"Orphan"。在kubernetes1.9版本中,所有型別的物件,在app/v1版本的apiVersion中,預設從物件刪除。
-
後臺級聯刪除示例:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
- 注意上例中kubectl充當的是proxy角色,直接呼叫REST API執行刪除操作,注意其propagationPolicy的取值。
- 前臺級聯刪除示例:
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
- 不刪除從物件示例
kubectl proxy --port=8080
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-repset \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
- kubectl命令也支援級聯刪除操作。在執行kubectl命令時指定"--cascade"選項,其值為true時刪除從物件,為false不刪除從物件,預設值為true。 示例如下:
kubectl delete replicaset my-repset --cascade=false
# 當--cascade為true時,kubectl採用的是前臺級聯刪除還是後臺級聯刪除,文件中沒有講。
1.4、級聯刪除Deployment時的注意點
- 當級聯刪除Deployment時,其刪除請求中的propagationPolicy必需設定成Foreground。否則Deployment建立的ReplicaSet會被級聯刪除,但是ReplicaSet建立的pod不會被級聯刪除,會成為孤兒。