編排的藝術 K8S 中的容器編排和應用編排

2021-09-19 20:21:58 字數 3951 閱讀 6065

眾所周知,kubernetes 是乙個容器編排平台,它有非常豐富的原始的 api 來支援容器編排,但是對於使用者來說更加關心的是乙個應用的編排,包含多容器和服務的組合,管理它們之間的依賴關係,以及如何管理儲存。

在這個領域,kubernetes 用 helm 的來管理和打包應用,但是 helm 並不是十全十美的,在使用過程中我們發現它並不能完全滿足我們的需求,所以在 helm 的基礎上,我們自己研發了一套編排元件……

什麼是編排?

不知道大家有沒仔細思考過編排到底是什麼意思? 我查閱了 wiki 百科,了解到我們常說的編排的英文單詞為 「orchestration」,它常被解釋為:

計算機領域:引申為描述複雜計算機系統、中介軟體 (middleware) 和業務的自動化的安排、協調和管理。

有趣的是 「orchestration」 的標準翻譯應該為「編配」,而「編排」則是 另外乙個單詞 「choreography」,為了方便大家理解, 符合平時的習慣,我們還是使用編排 (orchestration) 來描述下面的問題。至於「編配 (orchestration)」 和 「編排(choreography)」 之爭,這裡有一篇文章,有興趣可以看一下 。

編配和編排的定義之爭

當我們在說容器編排的時候,我們在說什麼?

在傳統的單體式架構的應用中,我們開發、測試、交付、部署等都是針對單個元件,我們很少聽到編排這個概念。而在雲的時代,微服務和容器大行其道,除了為我們顯示出了它們在敏捷性,可移植性等方面的巨大優勢以外,也為我們的交付和運維帶來了新的挑戰:我們將單體式的架構拆分成越來越多細小的服務,執行在各自的容器中,那麼該如何解決它們之間的依賴管理,服務發現,資源管理,高可用等問題呢?

在容器環境中,編排通常涉及到三個方面:

工作負載編排 - 負責在資源之間共享工作負載,如 kubernetes 通過不同的 controller 將 pod 排程到合適的 node 上,並且負責管理它們的生命週期;

服務編排 - 負責服務發現和高可用等,如 kubernetes 中可用通過 service 來對內暴露服務,通過 ingress 來對外暴露服務。

在 kubernetes 中有 5 種我們經常會用到的控制器來幫助我們進行容器編排,它們分別是 deployment, statefulset, daemonset, cronjob, job。

在這 5 種常見資源中,deployment 經常被作為無狀態例項控制器使用; statefulset 是乙個有狀態例項控制器; daemonset 可以指定在選定的 node 上跑,每個 node 上會跑乙個副本,它有乙個特點是它的 pod 的排程不經過排程器,在 pod 建立的時候就直接繫結 nodename;最後乙個是定時任務,它是乙個上級控制器,和 deployment 有些類似,當乙個定時任務觸發的時候,它會去建立乙個 job ,具體的任務實際上是由 job 來負責執行的。他們之間的關係如下圖:

乙個簡單的例子

我們來考慮這麼乙個簡單的例子,乙個需要使用到資料庫的 api 服務在 kubernetes 中應該如何表示:

客戶端程式通過 ingress 來訪問到內部的 api service, api service 將流量導流到 api server deployment 管理的其中乙個 pod 中,這個 server 還需要訪問資料庫服務,它通過 db service 來訪問 database statefulset 的有狀態副本。由定時任務 cronjob 來定期備份資料庫,通過 daemonset 的 logging 來採集日誌,monitoring 來負責收集監控指標。

kubernetes 為我們帶來了什麼?

通過上面的例子,我們發現 kubernetes 已經為我們對大量常用的基礎資源進行了抽象和封裝,我們可以非常靈活地組合、使用這些資源來解決問題,同時它還提供了一系列自動化運維的機制:如 hpa, vpa, rollback, rolling update 等幫助我們進行彈性伸縮和滾動更新,而且上述所有的功能都可以用 yaml 宣告式進行部署。困境

但是這些抽象還是在容器層面的,對於乙個大型的應用而言,需要組合大量的 kubernetes 原生資源,需要非常多的 services, deployments, statefulsets 等,這裡面用起來就會比較繁瑣,而且其中服務之間的依賴關係需要使用者自己解決,缺乏統一的依賴管理機制。

什麼是應用?

乙個對外提供服務的應用,首先它需要乙個能夠與外部通訊的網路,其次還需要能執行這個服務的載體 (pods),如果這個應用需要儲存資料,這還需要配套的儲存,所以我們可以認為:

應用單元 = 網路 + 服務載體 +儲存

有狀態應用 = services + volumes + statefulset

守護型應用 = services + volumes + daemonset

批處理應用 = services + volumes + cronjob/job

我們來重新審視一下之前的例子:

應用層面的四個問題

通過前面的探索,我們可以引出應用層面的四個問題:

應用依賴管理

包儲存執行時管理

在社群中,這四個方面的問題分別由三個元件或者專案來解決:

helm registry: 解決了包儲存;

helmtiller: 負責將包執行在 kubernetes 集群中。

helm charts

charts 在本質上是乙個 tar 包,包含了一些 yaml 的 template 以及解析 template 需要的 values, 如下圖:templates 是 golang 的 template 模板,values.yaml 裡面包含了這個 charts 需要的值。

helm registry

用來負責儲存和管理使用者的 charts, 並提供簡單的版本管理,與容器領域的映象倉庫類似這個專案是開源的。( github.com/caicloud/he…

)tiller

支援對 release 的更新,刪除,回滾操作;

支援對 release 的資源進行增量更新;

release 的狀態管理;

kubernetes下屬子專案(github.com/kubernetes/…

) 。 tiller 的缺陷

tiller 將 release 安裝到 kubernetes 集群中後並不會繼續追蹤他們的狀態;

helm+tiller的架構並不符合 kubernetes 的設計模式,這就導致它的拓展性比較差;

tiller 建立的 release 是全域性的並不是在某乙個分割槽下,這就導致多使用者/租戶下,不能進行隔離;

tiller 的回滾機制是基於更新的,每次回滾會使版本號增加,這不符合使用者的直覺。

release controller

為了解決上述的問題,我們基於 kubernetes 的 custom resource definition 設計並實現了我們自己的執行時管理系統 – release controller, 為此我們設計了兩個新的 crd – release 和 release history。

release 建立

當 release crd 被建立出來,controller 為它建立乙個新的 release history, 然後將 release 中的 chart 和 configuration 解析成 kubernetes 的資源,然後將這些資源在集群中建立出來,同時會監聽這些資源的變化,將它們的狀態反映在 release crd 的 status 中。

release 更新

當使用者更新 release 的時候,controller 計算出更新後的資源與集群中現有資源的 diff, 然後刪除一部分,更新一部分,建立一部分,來使得集群中的資源與 release 描述的一致,同時為舊的 release 建立乙份 release history。

release 回滾和刪除

使用者希望回滾到某乙個版本的 release, controller 從 release history 中找到對應的版本,然後將 release 的 spec 覆蓋,同時去更新集群中對應的資源。當 release 被刪除後,controller 將它關聯的 release history 刪除,同時將集群中的其他資源一併刪除。

架構圖

容器編排工具k8s

如何實踐 1 搜尋kubunetes online kubernetes playground katacoda pod k8s最小排程單位 docker pause 二個容器 deployments 維持pod一定數量 service 解決deploytemnets內部之間的乙個負載均衡 dns解...

K8S容器編排YAML詳解

k8s 集群中對資源管理和資源物件編排部署都可以通過宣告樣式 yaml 檔案來解決,也就是可以把需要對資源物件操作編輯到yaml格式檔案中,一般使用 yaml 格式的檔案來建立符合我們預期期望的 pod 我們把這種檔案叫做資源清單檔案,通過 kubectl 命令直接使用資源清單檔案就可以實現對大量的...

k8s專欄 資源編排

參考k8s教程由淺入深 編排方法 使用yaml檔案配置資源物件,通過kubectl命令對資源進行編排部署 1.定義 標記性語言,常用語配置檔案 2.書寫格式 3.yaml檔案組成部分 組成 控制器 被控制物件 控制器定義 apiversion extensions v1beta1 api版本 kin...