Kubernetes中的垃圾回收
考慮一個場景; 您在Kubernetes中創(chuàng)建了一個部署對象; 因此,它根據(jù)提供的清單生成副本集和pod。 后來,您意識到您錯過了一個容器的屬性,并且為了快速修復(fù),您編輯了部署。 版本的部署會產(chǎn)生新的副本集對象和更新的Pod。 知道舊的會怎樣嗎? 同樣,如果刪除部署,副本集或Pod將會發(fā)生什么。 答案是顯而易見的。 刪除部署將刪除副本集和Pod; 否則,將會變得一團糟。

上面的陳述引出了一個更大的問題:在Kubernetes中如何實現(xiàn)級聯(lián)刪除,是否有多種級聯(lián)刪除策略,在K8中是否可能存在孤立對象? 看起來這是典型的垃圾回收問題。 這篇文章將討論Kubernetes中垃圾收集的概念和實現(xiàn)。 首先,讓我們快速探索垃圾收集。
什么是垃圾收集(GC)?
簡而言之,垃圾回收就是從系統(tǒng)中刪除未使用的對象,并釋放分配給它們的計算資源。 GC出現(xiàn)在所有高級編程語言中,而低級編程語言通過系統(tǒng)庫具有GC。
GC的最常見算法之一是標記掃描。 我沒有介紹算法的詳細信息,但是我們可以從標題有兩個階段的角度來解釋它,在第一階段中標記了在清除階段刪除的對象。

> From Wikipedia
這是對GC的非常簡短的說明,如果需要,請按照參考部分中發(fā)布的鏈接進行詳細說明。 現(xiàn)在,我們將探討在K8s中實現(xiàn)GC的方法。
業(yè)主擁有; OwnerReference元數(shù)據(jù)
像面向?qū)ο蟮恼Z言一樣,某些對象引用其他對象/由其他對象組成,在Kubernetes中以類似的方式,某些對象擁有其他對象。 例如,副本集是一組Pod的所有者,而部署是副本集的所有者。
與面向?qū)ο蟮恼Z言不同,在K8s對象清單定義中,我們從來沒有明確定義或編寫與所有者相關(guān)的關(guān)系,而是系統(tǒng)如何確定該關(guān)系? 在K8s中,每個從屬對象都有一個唯一的元數(shù)據(jù)字段名稱metas.ownerReferences用于關(guān)系表示。
- 從Kubernetes 1.8開始,K8為由特定控制器(例如ReplicaSet,StatefulSet,DaemonSet,Deployment,Job和CronJob)創(chuàng)建或采用的對象設(shè)置ownerReferences的值。
- 如果需要,還可以手動設(shè)置ownerReferences。
- 一個對象可以有多個ownerReferences,例如在名稱空間中。
下面顯示了Kind K8s獨立群集上core-dns部署的metadata.ownerReferences值
如果仔細看一下以上命令的輸出,您會發(fā)現(xiàn)與其他GC實現(xiàn)的細微差別。 對象關(guān)聯(lián)參考金字塔是顛倒的,而不是常規(guī)的顛倒的。 下圖將為您提供幫助。

> Downside Up association of the objects in K8s
Kubernetes中的垃圾回收策略
如前所述,在Kubernetes 1.8之前,依賴對象刪除邏輯的實現(xiàn)是在客戶端,對于一些資源也是在控制器端。 客戶端不是原子操作,有時中途失敗會導致群集狀態(tài)混亂,需要手動清理。 后來,為解決此問題,K8s社區(qū)引入并實現(xiàn)了垃圾收集器控制器,以更好,更簡單的方式處理GC。
在用于未使用對象GC的K8中,有兩大類:
- 級聯(lián):在級聯(lián)之一中,所有者的刪除導致從群集中刪除從屬對象。
- 孤兒:顧名思義,對所有者對象的刪除操作只會將其從集群中刪除,并使所有從屬對象處于"孤兒"狀態(tài)。
讓我們深入了解上述策略。
在級聯(lián)刪除策略中,從屬對象與所有者對象一起被刪除。 在級聯(lián)內(nèi),有兩種模式:前景和背景。
前景級聯(lián)刪除:在前景策略中,所有者對象刪除將一直等待,直到所有從屬對象都被刪除為止。 當前臺刪除是所有者對象狀態(tài)更改為進行中的刪除時,將發(fā)生第一個更改。 處于"正在刪除"狀態(tài)的對象的屬性如下:
- 通過REST API,該對象仍然可見
- 設(shè)置了對象的deleteTimestamp
- 對象的元數(shù)據(jù).finalizers包含值" foregroundDeletion"。
一旦狀態(tài)發(fā)生變化,垃圾收集器將刪除所有"阻塞"依賴項(擁有者參考.blockOwnerDeletion = true的對象),最后刪除擁有者對象。
背景級聯(lián)刪除:這要簡單得多,在這種情況下,它將直接刪除所有者對象。 稍后,GC確定相關(guān)對象并將其從后臺刪除。 它比前臺快得多,因為沒有等待時間來刪除從屬對象。
在孤立策略中,將刪除所有者對象,并將從屬對象中的ownerReferences元數(shù)據(jù)設(shè)置為默認值。 之后,GC控制器確定孤立對象并將其刪除。
Kubernetes垃圾收集器控制器如何工作?
如果對象的OwnerReferences元數(shù)據(jù)中沒有任何所有者對象,則GC控制器負責刪除該對象。 GC控制器由掃描儀,垃圾處理器和傳播器組成。
掃描程序:使用發(fā)現(xiàn)API,它會檢測K8s集群中支持的所有資源,并通過控制循環(huán)定期檢測它,掃描系統(tǒng)中的所有資源,并將每個對象添加到"臟隊列"中。
垃圾處理器:由在"臟隊列"上工作的工人組成。 每個工作人員都會從"臟隊列"中取出一個項目,并檢查該項目的OwnerReferences是否為空。 如果為空,則僅從Dirty隊列中取出下一個條目進行處理; 否則,檢查OwnerReferences元數(shù)據(jù)中的每個條目。 如果OwnerReferences中列出的所有所有者均不存在,則工作程序會請求API服務(wù)器刪除該對象。
傳播器:傳播器用于優(yōu)化GC控制器,包含三個組件。 事件隊列,單個工作程序以及與所有者相關(guān)的關(guān)系的DAG。 以下是繁殖器的特性
- DAG僅存儲名稱/ uid /孤立三元組,而不存儲每個項目的整個主體。
- 監(jiān)視所有資源的創(chuàng)建/更新/刪除事件,并將事件排入事件隊列。
- 工作者從事件隊列中使項目出隊。
- K8s對象的創(chuàng)建或更新會相應(yīng)地更新DAG。 如果資源具有所有者,但該所有者在DAG中尚不存在,則除了將對象添加到DAG之外,它還將對象排隊到"臟隊列"中。
- 刪除K8s對象會將其從DAG中刪除,并將其所有從屬對象排隊到"臟隊列"中。
- 傳播者不需要執(zhí)行任何RPC,因此只需一個工作線程就足夠了,并且鎖定起來也更容易。
- 使用傳播器,我們僅需在啟動GC時運行掃描程序以填充DAG和臟隊列。
總體而言,Kubernetes中GC的實現(xiàn)是非常通用和復(fù)雜的,并且非常有效。 我希望這篇文章可以幫助您了解K8s中GC的見解。 感謝您的閱讀和期待反饋或贊賞。




























