偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

九張圖帶你理解 Kubernetes Controller 工作機制

系統(tǒng) Linux
此文就是通過對代碼的簡單分析,以及一些經(jīng)驗總結(jié),來描述 k8s controller 管理資源的主要流程。

圖片

一、Introduction

起因:工作上要重構(gòu)一個現(xiàn)有的組件管理工具,要求實現(xiàn)全生命周期管理,還有上下游解耦,我心里一想這不就是 k8s controller 嘛!所以決定在動手前先學(xué)習(xí)一下 k8s 的先進理念。

此文就是通過對代碼的簡單分析,以及一些經(jīng)驗總結(jié),來描述 k8s controller 管理資源的主要流程。

二、Concepts

resource: 資源,k8s 中定義的每一個實例都是一個資源,比如一個 rs、一個 deployment。資源有不同的 kind,比如 rs、deployment。資源間存在上下游關(guān)系。

注意:下文中提到的所有“資源”,都是指 k8s 中抽象的資源聲明,而不是指 CPU、存儲等真實的物理資源。

高度抽象 k8s 的話其實就三大件:

  • apiserver: 負(fù)責(zé)存儲資源,并且提供查詢、修改資源的接口
  • controller: 負(fù)責(zé)管理本級和下級資源。比如 deploymentController 就負(fù)責(zé)管理 deployment 資源 和下一級的 rs 資源。
  • kubelet: 安裝在 node 節(jié)點上,負(fù)責(zé)部署資源

controller 和 kubelet 都只和 apiserver 通訊。controller 不斷監(jiān)聽本級資源,然后修改下級資源的聲明。kubelet 查詢當(dāng)前 node 所應(yīng)部署的資源,然后執(zhí)行清理和部署。

圖片

1、術(shù)語

  • ??metadata??: 每一個資源都有的元數(shù)據(jù),包括 label、owner、uid 等
  • ??UID??: 每一個被創(chuàng)建(提交給 apiserver)的資源都有一個全局唯一的 UUID。
  • ??label??: 每個資源都要定義的標(biāo)簽
  • ??selector??: 父資源通過 labelSelector 查詢歸其管理的子資源。不允許指定空 selector(全匹配)。
  • owner: 子資源維護一個 owner UID 的列表??OwnerReferences??, 指向其父級資源。列表中第一個有效的指針會被視為生效的父資源。selector 實際上只是一個 adoption 的機制, 真實起作用的父子級關(guān)系是靠 owner 來維持的, 而且 owner 優(yōu)先級高于 selector。
  • replicas: 副本數(shù),pod 數(shù)
  • 父/子資源的相關(guān):
  • orphan: 沒有 owner 的資源(需要被 adopt 或 GC)
  • adopt: 將 orphan 納入某個資源的管理(成為其 owner)
  • match: 父子資源的 label/selector 匹配
  • release: 子資源的 label 不再匹配父資源的 selector,將其釋放
  • RS 相關(guān):
  • saturated: 飽和,意指某個資源的 replicas 已符合要求
  • surge: rs 的 replicas 不能超過 spec.replicas + surge
  • proportion: 每輪 rolling 時,rs 的變化量(小于 maxSurge)
  • fraction: scale 時 rs 期望的變化量(可能大于 maxSurge)

三、Controller

  • sample-controller@a40ea2c/controller.go
  • kubernetes@59c0523b/pkg/controller/deployment/deployment_controller.go
  • kubernetes@59c0523b/pkg/controller/controller_ref_manager.go

控制器,負(fù)責(zé)管理自己所對應(yīng)的資源(resource),并創(chuàng)建下一級資源,拿 deployment 來說:

  1. 用戶創(chuàng)建 deployment 資源
  2. deploymentController 監(jiān)聽到 deployment 資源,然后創(chuàng)建 rs 資源
  3. rsController 監(jiān)聽到 rs 資源,然后創(chuàng)建 pod 資源
  4. 調(diào)度器(scheduler)監(jiān)聽到 pod 資源,將其與 node 資源建立關(guān)聯(lián)

(node 資源是 kubelet 安裝后上報注冊的)

圖片

理想中,每一層管理器只管理本級和子兩層資源。但因為每一個資源都是被上層創(chuàng)建的, 所以實際上每一層資源都對下層資源的定義有完全的了解,即有一個由下至上的強耦合關(guān)系。

比如 ??A -> B -> C -> D?? 這樣的生成鏈,A 當(dāng)然是知道 D 資源的全部定義的, 所以從理論上說,A 是可以去獲取 D 的。但是需要注意的是,如果出現(xiàn)了跨級的操作,A 也只能只讀的獲取 D,而不要對 D 有任何改動, 因為跨級修改數(shù)據(jù)的話會干擾下游的控制器。

k8s 中所有的控制器都在同一個進程(controller-manager)中啟動, 然后以 goroutine 的形式啟動各個不同的 controller。所有的 contorller 共享同一個 informer,不過可以注冊不同的 filter 和 handler,監(jiān)聽自己負(fù)責(zé)的資源的事件。

(informer 是對 apiserver 的封裝,是 controller 查詢、訂閱資源消息的組件,后文有介紹)注:如果是用戶自定義 controller(CRD)的話,需要以單獨進程的形式啟動,需要自己另行實例化一套 informer, 不過相關(guān)代碼在 client-go 這一項目中都做了封裝,編寫起來并不會很復(fù)雜。

控制器的核心代碼可以概括為:

for {
for {
// 從 informer 中取出訂閱的資源消息
key, empty := queue.Get()
if empty {
break
}

defer queue.Done(key)

// 處理這一消息:更新子資源的聲明,使其匹配父資源的要求。
// 所有的 controller 中,這一函數(shù)都被命名為 `syncHandler`。
syncHandler(key)
}

// 消息隊列被消費殆盡,等待下一輪運行
time.sleep(time.Second)
}
  1. 通過 informer(indexer)監(jiān)聽資源事件,事件的格式是字符串??<namespace>/<name>??
  2. 控制器通過 namespace 和 name 去查詢自己負(fù)責(zé)的資源和下級資源
  3. 比對當(dāng)前資源聲明的狀態(tài)和下級資源可用的狀態(tài)是否匹配,并通過增刪改讓下級資源匹配上級聲明。比如 deployments 控制器就查詢 deployment 資源和 rs 資源,并檢驗其中的 replicas 副本數(shù)是否匹配。

controller 內(nèi)包含幾個核心屬性/方法:

  • informer: sharedIndexer,用于獲取資源的消息,支持注冊 Add/Update/Delete 事件觸發(fā),或者調(diào)用??lister?? 遍歷。
  • clientset: apiserver 的客戶端,用來對資源進行增刪改。
  • syncHandler: 執(zhí)行核心邏輯代碼(更新子資源的聲明,使其匹配父資源的要求)。

1、syncHandler

syncHandler 像是一個約定,所有的 controller 內(nèi)執(zhí)行核心邏輯的函數(shù)都叫這個名字。該函數(shù)負(fù)責(zé)處理收到的資源消息,比如更新子資源的聲明,使其匹配父資源的要求。

以 deploymentController 為例,當(dāng)收到一個事件消息,syncHandler 被調(diào)用后:

注:

  • ??de??: 觸發(fā)事件的某個 deployment 資源
  • ??dc??: deploymentController 控制器自己
  • ??rs??: replicaset,deployment 對應(yīng)的 replicaset 子資源

注:事件是一個字符串,形如 ??namespace/name??,代表觸發(fā)事件的資源的名稱以及所在的 namespace。因為事件只是個名字,所以 syncHandler 需要自己去把當(dāng)前觸發(fā)的資源及其子資源查詢出來。這里面涉及很多查詢和遍歷,不過這些查詢都不會真實的調(diào)用 apiserver,而是在 informer 的內(nèi)存存儲里完成的。

graph TD

A1[將 key 解析為 namespace 和 name] --> A2[查詢 de]
A2 --> A3[查詢關(guān)聯(lián)子資源 rs]
A3 --> A31{de 是否 paused}
A31 --> |yes| A32[調(diào)用 dc.sync 部署 rs]
A31 --> |no| A4{是否設(shè)置了 rollback}
A4 --> |yes| A41[按照 annotation 設(shè)置執(zhí)行 rollback]
A4 --> |no| A5[rs 是否匹配 de 聲明]
A5 --> |no| A32
A5 --> |yes| A6{de.spec.strategy.type}
A6 --> |recreate| A61[dc.rolloutRecreate]
A6 --> |rolling| A62[dc.rolloutRolling]

圖片

查詢關(guān)聯(lián)子資源

  • kubernetes@59c0523b/pkg/controller/deployment/deployment_controller.go:getReplicaSetsForDeployment

k8s 中,資源間可以有上下級(父子)關(guān)系。

理論上 每一個 controller 都負(fù)責(zé)創(chuàng)建當(dāng)前資源和子資源,父資源通過 labelSelector 查詢應(yīng)該匹配的子資源。

一個 deployment 的定義:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

上文中講到 syncHandler 的時候,提到需要“查詢關(guān)聯(lián)子資源”。其實這一步驟很復(fù)雜,不僅僅是查詢,還包含對現(xiàn)有子資源進行同步(修改)的操作。簡而言之,這一步驟實際上做的是通過對 owner、label 的比對,確認(rèn)并更新當(dāng)前真實的父子資源關(guān)系。

對用戶呈現(xiàn)的資源關(guān)聯(lián)是依靠 label/selector。但實際上 k8s 內(nèi)部使用的是 owner 指針。(owner 指針是資源 metadata 內(nèi)用來標(biāo)記其父資源的 OwnerReferences)。

查詢匹配子資源的方法是:

  1. 遍歷 namespace 內(nèi)所有對應(yīng)類型的子資源 (比如 deployment controller 就會遍歷所有的 rs)
  2. 匹配校驗 owner 和 label

(父是當(dāng)前操作的資源,子是查詢出的子資源)

還是用 deployment 舉例,比如此時收到了一個 deployment 事件,需要查詢出該 de 匹配的所有 rs:

graph LR

A(遍歷 namespace 內(nèi)所有 rs) --> A1{子.owner == nil}
A1 --> |false| A2{子.owner == 父.uid}
A2 --> |false| A21[skip]
A2 --> |true| A3{labels matched}
A3 --> |true| A5
A3 --> |false| A31[release]
A1 --> |true| A4{labels matched}
A4 --> |false| A21
A4 --> |true| A41[adopt]
A41 --> A5[標(biāo)記為父子]

圖片

如上圖所示,其實只有兩個 case 下,rs 會被視為是 de 的子資源:

  1. rs owner 指向 de,且 labels 匹配
  2. rs owner 為空,且 labels 匹配

注意:如果 rs owner 指向了其他父資源,即使 label 匹配,也不會被視為當(dāng)前 de 的子資源。

dc.sync

  • kubernetes@59c0523b/pkg/controller/deployment/sync.go:sync

這是 deployment controller 中執(zhí)行“檢查和子資源,令其匹配父資源聲明”的一步。準(zhǔn)確的說:

  1. dc.sync: 檢查子資源是否符合父資源聲明
  2. dc.scale: 操作更新子資源,使其符合父資源聲明
graph TD

A1[查詢 de 下所有舊的 rs] --> A2{當(dāng)前 rs 是否符合 de}
A2 --> |no| A21[newRS = nil]
A2 --> |yes| A22[NewRS = 當(dāng)前 rs]
A22 --> A23[將 de 的 metadata 拷貝給 newRS]
A23 --> A231[newRS.revision=maxOldRevision+1]
A231 --> A3[調(diào)用 dc.scale]
A21 --> A33
A3 --> A31{是否有 active/latest rs}
A31 --> |yes| A311[dc.scaleReplicaSet 擴縮容]
A31 --> |no| A32{newRS 是否已飽和}
A32 --> |yes|A321[把所有 oldRS 清零]
A32 --> |no|A33{de 是否允許 rolling}
A33 --> |no|A331[return]
A33 --> |yes|A34[執(zhí)行滾動更新]

圖片

滾動更新的流程為:

(??if deploymentutil.IsRollingUpdate(deployment) {...}?? 內(nèi)的大量代碼,實際做的事情就是按照 deployment 的要求更新 rs 的 replicas 數(shù)。不過每次變更都涉及到對 rs 和 deployment 的 maxSurge 的檢查,所以代碼較為復(fù)雜。)

  1. 計算所有 RS replicas 總和??allRSsReplicas??。
  2. 計算滾動升級過程中最多允許出現(xiàn)的副本數(shù)??allowedSize???。??allowedSize = de.Spec.Replicas + maxSurge??
  3. ??deploymentReplicasToAdd = allowedSize - allRSsReplicas??
  4. 遍歷所有當(dāng)前 rs,計算每一個 rs 的 replicas 變化量(proportion), 計算的過程中需要做多次檢查,不能溢出 rs 和 deployment 的 maxSurge。
  5. 更新所有 rs 的 replicas,然后調(diào)用??dc.scaleReplicaSet?? 提交更改。

四、Object

  • apimachinery@v0.0.0-20210708014216-0dafcb48b31e/pkg/apis/meta/v1/meta.go
  • apimachinery@v0.0.0-20210708014216-0dafcb48b31e/pkg/apis/meta/v1/types.go

ObjectMeta 定義了 k8s 中資源對象的標(biāo)準(zhǔn)方法。

雖然 resource 定義里是通過 labelSelector 建立從上到下的關(guān)聯(lián), 但其實內(nèi)部實現(xiàn)的引用鏈?zhǔn)菑南碌缴系?。每一個資源都會保存一個 Owner UID 的 slice。

每個資源的 metadata 中都有一個 ??ownerReferences?? 列表,保存了其父資源(遍歷時遇到的第一個有效的資源會被認(rèn)為是其父資源)。

type ObjectMeta struct {
OwnerReferences []OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid" protobuf:"bytes,13,rep,name=ownerReferences"`
}

判斷 owner 靠的是比對資源的 UID

func IsControlledBy(obj Object, owner Object) bool {
ref := GetControllerOfNoCopy(obj)
if ref == nil {
return false
}

// 猜測:UID 是任何資源在 apiserver 注冊的時候,由 k8s 生成的 uuid
return ref.UID == owner.GetUID()
}

五、Informer

  • A deep dive into Kubernetes controllers[1]
  • client-go@v0.0.0-20210708094636-69e00b04ba4c/informers/factory.go

Informer 也經(jīng)歷了兩代演進,從最早各管各的 Informer,到后來統(tǒng)一監(jiān)聽,各自 filter 的 sharedInformer。

所有的 controller 都在一個 controller-manager 進程內(nèi),所以完全可以共享同一個 informer, 不同的 controller 注冊不同的 filter(kind、labelSelector),來訂閱自己需要的消息。

簡而言之,現(xiàn)在的 sharedIndexer,就是一個統(tǒng)一的消息訂閱器,而且內(nèi)部還維護了一個資源存儲,對外提供可過濾的消息分發(fā)和資源查詢功能。

sharedIndexer 和 sharedInformer 的區(qū)別就是多了個 threadsafe 的 map 存儲,用來存 shared resource object。

現(xiàn)在的 informer 中由幾個主要的組件構(gòu)成:

  • reflecter:查詢器,負(fù)責(zé)從 apiserver 定期輪詢資源,更新 informer 的 store。
  • store: informer 內(nèi)部對資源的存儲,用來提供 lister 遍歷等查詢操作。
  • queue:支持 controller 的事件訂閱。

圖片

各個 controller 的訂閱和查詢絕大部分都在 sharedIndexer 的內(nèi)存內(nèi)完成,提高資源利用率和效率。

一般 controller 的消息來源就通過兩種方式:

  1. lister: controller 注冊監(jiān)聽特定類型的資源事件,事件格式是字符串,??<namespace>/<name>??
  2. handler: controller 通過 informer 的??AddEventHandler??? 方法注冊??Add/Update/Delete?? 事件的處理函數(shù)。

這里有個值得注意的地方是,資源事件的格式是字符串,形如 ??<namespace>/<name>??,這其中沒有包含版本信息。

那么某個版本的 controller 拿到這個信息后,并不知道查詢出來的資源是否匹配自己的版本,也許會查出一個很舊版本的資源。

所以 controller 對于資源必須是向后兼容的,新版本的 controller 必須要能夠處理舊版資源。這樣的話,只需要保證運行的是最新版的 controller 就行了。

圖片

1、Queue

controller 內(nèi)有大量的隊列,最重要的就是注冊到 informer 的三個 add/update/delete 隊列。

RateLimitingQueue

  • client-go@v0.0.0-20210708094636-69e00b04ba4c/util/workqueue/rate_limiting_queue.go

實際使用的是隊列類型是 RateLimitingQueue,繼承于 Queue。

Queue

  • client-go@v0.0.0-20210708094636-69e00b04ba4c/util/workqueue/queue.go
type Interface interface {
// Add 增加任務(wù),可能是增加新任務(wù),可能是處理失敗了重新放入
//
// 調(diào)用 Add 時,t 直接插入 dirty。然后會判斷一下 processing,
// 是否存在于 processing ? 返回 : 放入 queue
Add(item interface{})
Len() int
Get() (item interface{}, shutdown bool)
Done(item interface{})
ShutDown()
ShuttingDown() bool
}


type Type struct {
// queue 所有未被處理的任務(wù)
queue []t

// dirty 所有待處理的任務(wù)
//
// 從定義上看和 queue 有點相似,可以理解為 queue 的緩沖區(qū)。
// 比如調(diào)用 Add 時,如果 t 存在于 processing,就只會插入 dirty,不會插入 queue,
// 這種情況表明外部程序處理失敗了,所以再次插入了 t。
dirty set

// processing 正在被處理的任務(wù)
//
// 一個正在被處理的 t 應(yīng)該從 queue 移除,然后添加到 processing。
//
// 如果 t 處理失敗需要重新處理,那么這個 t 會被再次放入 dirty。
// 所以調(diào)用 Done 從 processing 移除 t 的時候需要同步檢查一下 dirty,
// 如果 t 存在于 dirty,則將其再次放入 queue。
processing set

cond *sync.Cond

shuttingDown bool

metrics queueMetrics

unfinishedWorkUpdatePeriod time.Duration
clock clock.Clock
}

隊列傳遞的資源事件是以字符串來表示的,格式形如 ??namespace/name??。

正因為資源是字符串來表示,這導(dǎo)致了很多問題。其中對于隊列的一個問題就是:沒法為事件設(shè)置狀態(tài),標(biāo)記其是否已完成。為了實現(xiàn)這個狀態(tài),queue 中通過 queue、dirty、processing 三個集合來表示。具體實現(xiàn)可以參考上面的注釋和代碼。

另一個問題就是資源中沒有包含版本信息。

那么某個版本的 controller 拿到這個信息后,并不知道查詢出來的資源是否匹配自己的版本,也許會查出一個很舊版本的資源。

所以 controller 對于資源必須是向后兼容的,新版本的 controller 必須要能夠處理舊版資源。這樣的話,只需要保證運行的是最新版的 controller 就行了。

六、GC

  • Garbage Collection[2]
  • Using Finalizers to Control Deletion[3]
  • kubernetes@59c0523b/pkg/controller/garbagecollector/garbagecollector.go

1、Concepts

我看到

GC 的第一印象是一個像語言 runtime 里的回收資源的自動垃圾收集器。但其實 k8s 里的 GC 的工作相對比較簡單,更像是只是一個被動的函數(shù)調(diào)用,當(dāng)用戶試圖刪除一個資源的時候, 就會把這個資源提交給 GC,然后 GC 執(zhí)行一系列既定的刪除流程,一般來說包括:

  1. 刪除子資源
  2. 執(zhí)行刪除前清理工作(finalizer)
  3. 刪除資源

k8s 的資源間存在上下游依賴,當(dāng)你刪除一個上游資源時,其下游資源也需要被刪除,這被稱為??級聯(lián)刪除 cascading deletion??。

刪除一個資源有三種策略(??propagationPolicy/DeletionPropagation??):

  • ??Foreground??(default): Children are deleted before the parent (post-order)
  • ??Background??: Parent is deleted before the children (pre-order)
  • ??Orphan??: 忽略 owner references

可以在運行 ??kubectl delete --cascade=?????? 的時候指定刪除的策略,默認(rèn)為 ??foreground??。

2、Deletion

k8s 中,資源的 metadata 中有幾個對刪除比較重要的屬性:

  • ??ownerRerences??: 指向父資源的 UID
  • ??deletionTimestamp??: 如果不為空,表明該資源正在被刪除中
  • ??finalizers??: 一個字符串?dāng)?shù)組,列舉刪除前必須執(zhí)行的操作
  • ??blockOwnerDeletion??: 布爾,當(dāng)前資源是否會阻塞父資源的刪除流程

每一個資源都有 ??metadata.finalizers???,這是一個 ??[]string??, 內(nèi)含一些預(yù)定義的字符串,表明了在刪除資源前必須要做的操作。每執(zhí)行完一個操作,就從 finalizers 中移除這個字符串。

無論是什么刪除策略,都需要先把所有的 finalizer 逐一執(zhí)行完,每完成一個,就從 finalizers 中移除一個。在 finalizers 為空后,才能正式的刪除資源。

foreground、orphan 刪除就是通過 finalizer 來實現(xiàn)的。

const (
FinalizerOrphanDependents = "orphan"
FinalizerDeleteDependents = "foregroundDeletion"
)

圖片

注:有一種讓資源永不刪除的黑魔法,就是為資源注入一個不存在的 finalizer。因為 GC 無法找到該 finalizer 匹配的函數(shù)來執(zhí)行,就導(dǎo)致這個 finalizer 始終無法被移除, 而 finalizers 為空清空的資源是不允許被刪除的。

3、Foreground cascading deletion

  1. 設(shè)置資源的??deletionTimestamp???,表明該資源的狀態(tài)為正在刪除中(??"deletion in progress"??)。
  2. 設(shè)置資源的??metadata.finalizers??? 為??"foregroundDeletion"??。
  3. 刪除所有??ownerReference.blockOwnerDeletion=true?? 的子資源
  4. 刪除當(dāng)前資源

每一個子資源的 owner 列表的元素里,都有一個屬性 ??ownerReference.blockOwnerDeletion???,這是一個 ??bool??, 表明當(dāng)前資源是否會阻塞父資源的刪除流程。刪除父資源前,應(yīng)該把所有標(biāo)記為阻塞的子資源都刪光。

在當(dāng)前資源被刪除以前,該資源都通過 apiserver 持續(xù)可見。

4、Orphan deletion

觸發(fā) ??FinalizerOrphanDependents??,將所有子資源的 owner 清空,也就是令其成為 orphan。然后再刪除當(dāng)前資源。

5、Background cascading deletion

立刻刪除當(dāng)前資源,然后在后臺任務(wù)中刪除子資源。

graph LR

A1{是否有 finalizers} --> |Yes: pop, execute| A1
A1 --> |No| A2[刪除自己]
A2 --> A3{父資源是否在等待刪除}
A3 --> |No| A4[刪除所有子資源]
A3 --> |Yes| A31[在刪除隊列里提交父資源]
A31 --> A4

圖片

foreground 和 orphan 刪除策略是通過 finalizer 實現(xiàn)的 因為這兩個策略有一些刪除前必須要做的事情:

  • foreground finalizer: 將所有的子資源放入刪除事件隊列
  • orphan finalizer: 將所有的子資源的 owner 設(shè)為空

而 background 則就是走標(biāo)準(zhǔn)刪除流程:刪自己 -> 刪依賴。

這個流程里有一些很有趣(繞)的設(shè)計。比如 foreground 刪除,finalizer 里把所有的子資源都放入了刪除隊列, 然后下一步在刪除當(dāng)前資源的時候,會發(fā)現(xiàn)子資源依然存在,導(dǎo)致當(dāng)前資源無法刪除。實際上真正刪除當(dāng)前資源(父資源),j是在刪除最后一個子資源的時候,每次都會去檢查下父資源的狀態(tài)是否是刪除中, 如果是,就把父資源放入刪除隊列,此時,父資源才會被真正刪除。

6、Owner References

每個資源的 metadata 中都有一個 ??ownerReferences?? 列表,保存了其父資源(遍歷時遇到的第一個有效的資源會被認(rèn)為是其父資源)。

owner 決定了資源會如何被刪除。刪除子資源不會影響到父資源。刪除父資源會導(dǎo)致子資源被聯(lián)動刪除。(默認(rèn) ??kubectl delete --cascade=foreground??)

七、參考資料

關(guān)于本主題的內(nèi)容,我制作了一個 slides,可用于內(nèi)部分享:https://s3.laisky.com/public/slides/k8s-controller.slides.html#/

1、如何閱讀源碼

核心代碼:https://github.com/kubernetes/kubernetes,所有的 controller 代碼都在 ??pkg/controller/?? 中。

所有的 clientset、informer 都被抽象出來在 https://github.com/kubernetes/client-go 庫中,供各個組件復(fù)用。

學(xué)習(xí)用示例項目:https://github.com/kubernetes/sample-controller

2、參考文章

  • Garbage Collection[4]
  • Using Finalizers to Control Deletion[5]
  • A deep dive into Kubernetes controllers[6]
  • kube-controller-manager[7]

引用鏈接

[1]

A deep dive into Kubernetes controllers: https://app.yinxiang.com/shard/s17/nl/2006464/674c3d83-f011-49b8-9135-413588c22c0f/

[2]

Garbage Collection: https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/

[3]

Using Finalizers to Control Deletion: https://kubernetes.io/blog/2021/05/14/using-finalizers-to-control-deletion/

[4]

Garbage Collection: https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/

[5]

Using Finalizers to Control Deletion: https://kubernetes.io/blog/2021/05/14/using-finalizers-to-control-deletion/

[6]

A deep dive into Kubernetes controllers: https://engineering.bitnami.com/articles/a-deep-dive-into-kubernetes-controllers.html

[7]

kube-controller-manager: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/

責(zé)任編輯:龐桂玉 來源: 奇妙的Linux世界
相關(guān)推薦

2024-07-03 08:28:44

HWKafkaLEO

2022-06-13 11:05:35

RocketMQ消費者線程

2020-06-28 07:39:44

Kafka分布式消息

2022-06-27 11:04:24

RocketMQ順序消息

2020-11-16 10:50:27

KubernetesIngressLinux

2022-02-28 11:10:42

ZGCG1收集器

2021-04-25 10:45:59

Docker架構(gòu)Job

2022-07-11 11:06:11

RocketMQ函數(shù).消費端

2023-04-11 08:35:22

RocketMQ云原生

2021-05-18 06:55:07

Java AQS源碼

2022-07-04 11:06:02

RocketMQ事務(wù)消息實現(xiàn)

2022-01-05 14:30:44

容器Linux網(wǎng)絡(luò)

2019-07-24 08:49:36

Docker容器鏡像

2021-11-12 08:38:26

一致性哈希算法數(shù)據(jù)結(jié)構(gòu)

2021-01-28 10:55:47

Kubernetes IPLinux

2022-05-09 11:15:05

RocketMQPULL 模式PUSH 模式

2021-12-06 07:15:47

Pulsar地域復(fù)制

2020-06-03 08:19:00

Kubernetes

2015-07-13 10:23:23

Java圖解

2023-09-28 21:37:41

HashMap多線程
點贊
收藏

51CTO技術(shù)棧公眾號