今後之後運維與開發過上了沒羞沒臊的性福生活

原文連接:Kubernetes 控制器的進化之旅html

我是一堆 Kubernetes 控制器。緩存

你可能會疑惑爲何是一堆,由於我不是一我的,我只是衆多控制器中的一員,你也能夠把我當作是衆多控制器的集合。個人職責就是監控集羣內資源的實際狀態,一旦發現其與指望的狀態不相符,就採起行動使其符合指望狀態。微信

想當初,Kubernetes 老大哥創造我時,只是打算讓我用控制循環簡單維護下資源的狀態。但我後來的發展,遠遠超出了他的想象。網絡

1. 控制循環

所謂控制循環就是一個用來調節系統狀態的週期性操做,在 Kubernetes 中也叫調諧循環(Reconcile Loop)。個人手下控制着不少種不一樣類型的資源,好比 Pod,Deployment,Service 等等。就拿 Deployment 來講吧,個人控制循環主要分爲三步:app

  1. API Server 中獲取到全部屬於該 Deployment 的 Pod,而後統計一下它們的數量,即它們的實際狀態。
  2. 檢查 Deployment 的 Replicas 字段,看看指望狀態是多少個 Pod。
  3. 將這兩個狀態作比較,若是指望狀態的 Pod 數量比實際狀態多,就建立新 Pod,多幾個就建立幾個新的;若是指望狀態的 Pod 數量比實際狀態少,就刪除舊 Pod,少幾個就刪除幾個舊的。

然而好景不長,我收到了 Kubernetes 掌門人(看大門的) API Server 的抱怨:「你訪問個人次數太頻繁了,很是消耗個人資源,我連上廁所的時間都沒有了!」運維

我仔細一想,當前的控制循環模式確實有這個缺陷——訪問 API Server 的次數太頻繁了,容易被老大反感。工具

因此我決定,找一個小弟。oop

2. Informer

此次我招的小弟叫 Informer,它分擔一部分個人任務,具體的作法是這樣的:由 Informer 代替我去訪問 API Server,而我無論是查狀態仍是對資源進行伸縮都和 Informer 進行交接。並且 Informer 不須要每次都去訪問 API Server,它只要在初始化的時候經過 LIST API 獲取全部資源的最新狀態,而後再經過 WATCH API 去監聽這些資源狀態的變化,整個過程被稱做 ListAndWatchpost

而 Informer 也不傻,它也有一個助手叫 Reflector,上面所說的 ListAndWatch 事實上是由 Reflector 一手操辦的。編碼

這一次,API Server 的壓力大大減輕了,由於 Reflector 大部分時間都在 WATCH,並無經過 LIST 獲取全部狀態,這使 API Server 的壓力大大減小。我想此次掌門人應該不會再批評我了吧。

然而沒過幾天,掌門人又找我談話了:「你的手下每次來 WATCH 我,都要 WATCH 全部兄弟的狀態,依然很消耗個人資源啊!我就納悶了,你一次搞這麼多兄弟,你虎啊?」

我一想有道理啊,不必每次都 WATCH 全部兄弟的狀態,因而告訴 Informer:「之後再去 API Server 那裏 WATCH 狀態的時候,只查 WATCH 特定資源的狀態,不要一古腦兒全 WATCH。「

Informer 再把這個決策告訴 Reflector,事情就這麼愉快地決定了。

本覺得此次我會獲得掌門人的誇獎,可沒過幾天安穩日子,它又來找我訴苦了:「兄弟,雖然你減輕了個人精神壓力,但個人財力有限啊,若是每一個控制器都招一個小弟,那我得多發多少人的工資啊,你想一想辦法。」

3. SharedInformer

通過和其餘控制器的討論,咱們決定這麼作:全部控制器聯合起來做爲一個總體來分配 Informer,針對每一個(受多個控制器管理的)資源招一個 Informer 小弟,咱們稱之爲 SharedInformer。大家能夠理解爲共享 Informer,由於有不少資源是受多個控制器管理的,好比 Pod 同時受 DeploymentStatefulSet 管理。這樣當多個控制器同時想查 Pod 的狀態時,只須要訪問一個 Informer 就好了。

但這又引來了新的問題,SharedInformer 沒法同時給多個控制器提供信息,這就須要每一個控制器本身排隊和重試。

爲了配合控制器更好地實現排隊和重試,SharedInformer 搞了一個 Delta FIFO Queue(增量先進先出隊列),每當資源被修改時,它的助手 Reflector 就會收到事件通知,並將對應的事件放入 Delta FIFO Queue 中。與此同時,SharedInformer 會不斷從 Delta FIFO Queue 中讀取事件,而後更新本地緩存的狀態。

這還不行,SharedInformer 除了更新本地緩存以外,還要想辦法將數據同步給各個控制器,爲了解決這個問題,它又搞了個工做隊列(Workqueue),一旦有資源被添加、修改或刪除,就會將相應的事件加入到工做隊列中。全部的控制器排隊進行讀取,一旦某個控制器發現這個事件與本身相關,就執行相應的操做。若是操做失敗,就將該事件放回隊列,等下次排到本身再試一次。若是操做成功,就將該事件從隊列中刪除。(圖片來自網絡)

如今這個工做模式獲得了你們的一致好評。雖然單個 SharedInformer 的工做量增長了,但 Informer 的數量大大減小了,老大能夠把省下來的資金拿出一小部分給 SharedInformer 漲工資啊,這樣你們都很開心。

4. CRD

全民 Kubernetes 時代到了。

隨着容器及其編排技術的普及,使用 Kubernetes 的用戶大量增加,用戶已經不知足 Kubernetes 自帶的那些資源(Pod,Node,Service)了,你們都但願能根據具體的業務建立特定的資源,而且對這些資源的狀態維護還要遵循上面所說的那一套控制循環機制。

幸虧最近掌門人作了一次升級,新增了一個插件叫 CRD(Custom Resource Definition),建立一個全新的資源實例,只須要通過如下兩步:

  1. 建立一個 CRD 資源(沒錯,CRD 也是一種資源類型),其中定義」自定義資源「的 API 組API 版本資源類型。這樣就會向 API Server 註冊該資源類型的 API。
  2. 指定上面定義的 API 組 和 API 版本,建立自定義資源。

固然,中間還要加入一些代碼讓 Kubernetes 認識自定義資源的各類參數。

到這一步就基本上完成了自定義資源的建立,但 Kubernetes 並不知道該資源所對應的業務邏輯,好比你的自定義資源是宿主機,那麼對應的業務邏輯就是建立一臺真正的宿主機出來。那麼怎樣實現它的業務邏輯呢?

5. 自定義控制器

Controller Manager 見多識廣,說:」這裏的每一個控制器都是個人一部分,當初創造大家是由於大家都屬於通用的控制器,你們都能用得上。而自定義資源須要根據具體的業務來實現,咱們不可能知道每一個用戶的具體業務是啥,本身一拍腦殼想出來的自定義資源,用戶也不必定用得上。咱們可讓用戶本身編寫自定義控制器,大家把以前使用的控制循環和 Informer 這些編碼模式總結一下,而後提供給用戶,讓他們按照一樣的方法編寫本身的控制器。「

Deployment 控制器一驚,要把本身的祕密告訴別人?那別人把本身取代了咋辦?趕緊問道:」那未來我豈不是很危險,沒有存在的餘地了?「

Controller Manager 趕緊解釋道:」不用擔憂,雖然用戶能夠編寫自定義控制器,但不管他們玩出什麼花樣,只要他們的業務跑在 Kubernetes 平臺上,就免不了要跑容器,最後仍是會來求大家幫忙的,你要知道,控制器是能夠層層遞進的,他們只不過是在你外面套了一層,最後仍是要回到你這裏,請求你幫忙控制 Pod。「

這下你們都不慌了,決定就把自定義控制器這件事情交給用戶本身去處理,將選擇權留給用戶。

6. Operator

用戶自從得到了編寫自定義控制器的權力以後,很是開心,有的用戶(CoreOS)爲了方便你們控制有狀態應用,開發出了一種特定的控制器模型叫 Operator,並開始在社區內推廣,獲得了你們的一致好評。不能否認,Operator 這種模式是很聰明的,它把須要特定領域知識的應用單獨寫一個 Operator 控制器,將這種應用特定的操做知識編寫到軟件中,使其能夠利用 Kubernetes 強大的抽象能力,達到正確運行和管理應用的目的。

ETCD Operator 爲例,假如你想手動擴展一個 ETCD 集羣,通常的作法是:

  1. 使用 ETCD 管理工具添加一個新成員。
  2. 爲這個成員所在的節點生成對應的啓動參數,並啓動它。

而 ETCD Operator 將這些特定於 etcd 的操做手法編寫到了它的控制循環中,你只須要經過修改自定義資源聲明集羣指望的成員數量,剩下的事情交給 Operator 就行了。(圖片來自網絡)

本覺得這是一個皆大歡喜的方案,但沒過多久,就有開發 Operator 的小哥來抱怨了:」咱們有不少開發的小夥伴都是不懂運維那一套的,什麼高可用、容災根本不懂啊,如今讓咱們將運維的操做知識編寫到軟件中,臣妾作不到啊。。「

這確實是個問題,這樣一來就把開發和運維的工做都塞到了開發手裏,既懂開發又懂運維的可很少啊,爲了照顧你們,還得繼續想辦法把開發和運維的工做拆分開來。

7. OAM

這時候阿里和微軟發力了,他們聯合發佈了一個開放應用模型,叫 Open Application Model (OAM)。這個模型就是爲了解決上面提到的問題,將開發和運維的職責解耦,不一樣的角色履行不一樣的職責,並造成一個統一的規範,以下圖所示(圖片來自網絡):

這個規範告訴咱們:

  • 開發人員負責描述組件的功能,如何配置組件,以及運行須要多少資源
  • 運維人員負責將相關組件組合成一個應用,並配置運行時參數和運維支撐能力,好比是否須要監控,是否須要彈性伸縮。
  • 基礎設施工程師負責創建和維護應用的運行時環境(如底層系統)。

其中每個團隊負責的事情都用對應的 CRD 來配置。

這樣一來,開發和運維人員的職責就被區分開來了,簡化了應用的組合和運維。它將應用的配置和運維特徵(如自動伸縮、流量監控)進行解耦,而後經過建模構成一個總體,避免了 Operator 這種模型帶來的大量冗餘。

自從用上了這個模型以後,運維和開發小哥表示如今他們的關係很融洽,沒事還能一塊兒出去喝兩杯。

微信公衆號

掃一掃下面的二維碼關注微信公衆號,在公衆號中回覆◉加羣◉便可加入咱們的雲原生交流羣,和孫宏亮、張館長、陽明等大佬一塊兒探討雲原生技術

原文出處:https://www.cnblogs.com/ryanyangcs/p/12367293.html

相關文章
相關標籤/搜索