深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路

螞蟻金服分散式架構發表於2019-03-04

導讀

此文章分享了螞蟻金服如何自動化運維大規模 Kubernetes 叢集的實踐乾貨。

"大規模 Kubernetes 叢集"主要體現在幾十個 Kubernetes 叢集,十萬級別的 Kubernetes Worker 節點。

螞蟻金服使用 Operator 的模式去運維 Kubernetes 叢集,能便捷、自動化的管理 Kubernetes 叢集生命週期,做到 " Kubernetes as a Service " 。

此文適合 Kubernetes 愛好者,Kubernetes 架構師,以及 PE/SRE 閱讀。

前序知識

Kubernetes 架構介紹

此章節簡單介紹 Kubernetes 叢集的架構。主要是為了面向剛學習 Kubernetes 的同學,對於熟悉 Kubernetes 的同學,此章節可以跳過。

深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路


如上圖,一個 Kubernetes 叢集由 Master 節點和 Worker 節點組成。

在一個高可用 Kubernetes 叢集下面,Master 節點一般為3臺,在它們上面需要執行Kubernetes Master 元件。Kubernetes Master 元件包括 etcd, Apsierver, Scheduler 和 Controller-Manager。每個 Master 元件一般都是 3 個例項,以保證它們的高可用。Master 節點使用 Static Pod 方式啟動 Master 元件,即將每個元件的 Pod 描述檔案放入 Master 節點的指定目錄,Kubelet 會在啟動時將他們讀取,並以 Static Pod 方式啟動。

Kubernetes Worker 節點為 Kubernetes 叢集提供排程資源和應用執行環境。即所有的 Pod(可以理解為應用的一個個最小化部署單元)都執行在 Worker 節點上。一個Worker 節點需要將 Pod 執行上去,需要一些 on-host 軟體,這些軟體包括: kubelet, Runtime Service(docker, pouch 等實現方案), CNI 外掛等。

Operator 介紹

我們在這裡將花很少的篇幅向剛學習 Kubernetes 的同學介紹 Operator。如果期望獲得更詳細的解讀請參考 coreos 上關於 Operator 的介紹。

一個 Operator 實際上是為了解決某個複雜應用在 Kubernetes 的自動化部署、恢復。有了Operator,使用者只需要向Kubernetes Apiserver提交一個CRD Resource(yaml或者JSON,一個CRD Resource其實就是對應一個應用例項,CRD Resource用於描述這個應用例項的配置),Operator 就會根據使用者的需求去完成這個應用例項的初始化,在應用某個模組發生故障時,Operator 也會做出自動恢復功能。Operator 是用程式碼運維應用最好的實踐之一。

深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路

比如我們有一個etcd-operator,我們只需要使用者根據需求向 Kubernetes Apiserer 提交如下的 CRD Resource,etcd-operator 就能初始化完成一個 etcd 叢集:

apiVersion: etcd.database.coreos.com/v1beta2
kind: EtcdCluster
metadata:
  name: xxx-etcd-cluster
spec:
  size: 5複製程式碼

其中,上面的Spec.Size=5 代表了我們需要一個由 5 個 etcd 節點組成的 etcd 叢集。etcd-operator 會根據上面的配置,初始化完成 etcd 叢集。相應的,如果你又需要另一個 3 節點的etcd 叢集,你只需要提交新的一個Spec.Size=3的 CRD Resource 即可。

背景

在螞蟻金服,我們面臨著需要運維幾十個 Kubernetes 叢集,以及十萬級別以上的Kubernetes Worker 節點的難題。

我們將運維 Kubernetes 的工作拆分兩部分,一部分是運維 Kubernetes 叢集的 Master 元件(etcd, Apiserver, controller-manager, scheduler等),一部分是運維 Kubernetes Worker 節點。我們總結了這兩部分運維的難點。

難點1:運維 Kubernetes 叢集 Master 角色

  1. 如何快速新建、下線一個 Kubernetes 叢集 (初始化、刪除 Master 角色)。由於螞蟻業務的快速增長,我們隨時面臨著需要在新機房新建、下線一個 Kubernetes叢集;CI 和測試也有快速新建、刪除一個 Kubernetes 叢集的需求。

  2. 如何管理幾十個 Kubernetes 叢集 Master 元件版本。比如我們需要升級某幾個Kubernetes 叢集的 Apiserver,Scheduler 等元件。

  3. 如何自動化處理幾十個 Kubernetes 叢集 Master 元件發生的故障。

  4. 如何能獲取幾十個 Kubernetes 叢集 Master 元件的統一檢視。我們希望有一個統一的介面,一下就能獲取每個 Kubernetes 叢集 Master 角色的版本、狀態等資訊。

難點2:運維 Kubernetes Worker 節點

  1. 如何快速上線、下線 Kubernetes Worker 節點。上線時,我們需要保證 Kubernetes Worker 節點所需要的on-host軟體版本、配置正確。

  2. 如何升級十萬級別的 Kubernetes Worker 節點上的 on-host 軟體。如我們需要將所有Work節點的 docker、cni 版本升級到某個版本。

  3. 如何優雅的執行灰度釋出 Kubernetes Worker 節點上的軟體包。在 on-host 軟體新版本上線前,我們需要對它做小範圍的灰度釋出,即挑選 N 臺 Worker 節點發布新版本軟體包,執行驗證,最後根據驗證結果決定是否全規模的釋出新版本,或者回滾這個灰度釋出。

  4. 如果自動化處理十萬級別的 Kubernetes Worker 節點可能出現的 on-host 軟體故障。比如 docker\kubelet 發生 panic,我們是否能自動化得處理。

實現方案

在螞蟻,我們使用 Kube-on-Kube-Operator 和 Node-Operator 組合使用解決上述的難題。

  1. 首先,我們需要藉助工具,使用Kubernetes官方提供的方案( Static Pod 方式)部署“ Kubernetes 元叢集”(後面簡稱元叢集)到 “元叢集”的 Master 節點上。

  2. 然後,我們將 Kube-on-Kube-Operator 部署到 “ Kubernetes 元叢集”。我們將一個 Kubernetes 叢集所需的一系列 Master 元件當成一個複雜的應用。當我們需要一個“ Kubernetes 業務叢集”(後面簡稱業務叢集),我們只需要向元叢集 Apiserver 提交用於描述“ Kubernetes 業務叢集”的 Cluster CRD Resource (下文會介紹我們如何設計 CRD 結構),Kube-on-Kube-Operator 就為我們準備好了一個可以工作的“Kubernetes 業務叢集”("業務叢集" Master 元件都已經Ready,需要擴容 Worker 節點)。

  3. 之後我們在“ Kubernetes 業務叢集”上,部署上 Node-Operator。Node-Operator 負責 Worker 節點的生命週期。當我們需要擴容一個 Worker 節點,我們只需要提交描述 Worker 節點的後設資料( IP, Hostname, 機器運維登入方式等)的 Machine CRD Resource (下文會介紹我們如何設計 CRD 結構),Node-Operator 就會將 Worker 節點初始化完成,併成功加入到 “ Kubernetes 業務叢集” 中。


深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路

“元叢集” 只用於管理所有“業務叢集”所需的 Master 元件。“業務叢集”是真正提供給業務方執行 Pod 的 Kubernetes 叢集。也就說,在螞蟻金服,我們只有一個 “元叢集”, 在這個 “元叢集”中,我們使用 Kube-on-Kube-Operator 自動化管理了螞蟻金服所有的 “ Kubernetes 業務叢集” 的 Master 元件。

當然,“元叢集”也會部署 Node-Operator,用於“元叢集” Worker 節點的上下線,“元叢集”的 Worker 節點也是各個 “業務叢集” 的 Master 節點。

Kube-on-Kube-Operator

Kube-on-Kube-Operator 用於 Watch Cluster CRD Resource的變更,將"Cluster"所描述表示的 Kubernetes 業務叢集的所有 Master 元件 達到最終狀態。如下圖,是“元叢集”和它所管理的兩個“Kubernetes 業務叢集”的最終狀態:

深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路

Cluster CRD 的定義包含如下一些資訊:

  1. 業務叢集名。

  2. 業務叢集部署模式: 分為標準生產和最小化。標準生產提供Master元件都是3副本的部署,最小化則都是1個副本的部署。

  3. 業務叢集 Master 節點 NodeSelector,即表示如何在元叢集內如何選擇業務叢集Master 節點。

  4. 業務叢集各 Master 元件版本,自定義引數等

  5. 業務叢集所使用的 etcd 啟動配置,主要涉及 etcd data volume 的設定。有ClaimTemplate 和 VolumeSource 兩種模式,即使用 ClaimTemplate 模式就使用PVC 來初始化 etcd volume,而使用 VolumeSource 模式,即使用 VolumeSource 所表示的 volume 來掛載 etcd volume。

  6. 業務叢集 Master 元件證照過期時間: Master 元件所使用 kubeconfig 中的證照都有過期時間,以保證安全性。而 Kube-on-Kube-Operator 會在證照過期時自動完成滾動證照、Master 元件重新載入證照等操作。

  7. 業務叢集額外使用者 kubeconfig:即為 “額外使用者”提供的使用者名稱和組名,簽出證照,並生成 kubeconfig 儲存在元叢集 Secret 中供讀取。

  8. 業務叢集狀態: 這部分資訊不需要使用者提交,而是由 Kube-on-Kube-Operator 自動生成,使用者反饋這個業務叢集的狀態,參考 Pod.Status 。

一個業務叢集的 Master元件 部署 實際是元叢集中的一系列 Resource 組成,即包括Deployment,Secret,Pod,PVC 等組合使用。各 Master 元件 所需要的部署 Resource 如下:

  1. Apiserver: 一個 Deployment 即可,因為 Apiserver 是無狀態應用,副本數和Cluster CRD 描述的一致即可。除此之外,需要為Apiserver建立兩個 Service:

    1. 向同個業務叢集的其它 Master 元件提供服務的 Service: 建議使用元叢集內的 Headless Service。

    2. 向 Kubelet、外部元件提供服務的 Service: 建議使用機房 DNS RR Service (需要自己實現 Service Controller )。

  2. etcd: 每個 etcd 例項(標準化部署是 3 個例項,最小化是 1 個例項)都建議單獨使用 Pod + PV + PVC + Headless Service 部署。每個etcd 例項的 peer id 為對應的Headless Service 域名。當某個 etcd 例項發生故障時,需要手動刪除掉故障對應例項的 Pod,Kube-on-Kube-Operator watch 到 etcd Pod 的減少,會重新建立 Pod,並執行 Remove old member (被刪除的 Pod ), Add new member(新建的Pod)操作,但是他們的peer id還是保持一致的。

  3. Controller-Manager: 一個 Deployment 即可,因為 Controller-Manager 是無狀態應用。副本數和 Cluster CRD 描述的一致即可。

  4. Scheduler: 一個 Deployment 即可,因為 Scheduler 是無狀態應用。副本數和Cluster CRD 描述的一致即可。

Kube-on-Kube-Operator 除了能夠部署上述的 Master 元件之外,還能維護任何擴充套件元件,如 kube-proxy,kube-dns 等。只需要使用者提供 擴充套件元件部署模板 和 擴充套件外掛版本,Kube-on-Kube-Operator 能渲染出部署 Resource,並保持這些部署 Resource 到最終態。由於篇幅原因,我們這裡不再贅述。

Node-Operator

Node-Operator 用於 Watch Machine CRD Resource 的變更,將"Machine"所描述表示的 Worker 節點上的 on-host 軟體(docker, kubelet, cni)達到最終態,最終能讓 "Machine"所對應的"Node" 在 Kubernetes 叢集中達到"Ready"狀態。架構圖如下:

深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路

Machine CRD 的定義包含如下一些資訊:

  1. 機器後設資料: IP, Hostname, IDC 等

  2. 機器運維 ssh 登入方式和登入祕鑰: 如最常見的 SSH Key;如果 Machine 是阿里雲的 ECS, 那麼登入方式和登入祕鑰是阿里雲提供的 SSH 介面和對應的鑑權資訊等。

  3. 各個on-host 軟體版本和自定義引數

  4. Machine 狀態: 這部分資訊不需要使用者提交,而是由 Node-Operator 生成,表示這個機器的當前狀態,參考 Pod.Status 。

Node-Operator 還用 Watch Machine 對應 Node 的狀態,當發生一些能處理的 Condition(比如 kubelet 執行中程式消失了)時,Node-Operator 會做出恢復處理。

Node-Operator 還會 Watch ClusterPackageVersion CRD 的變更,這個 CRD 表示整個Kubernetes 叢集 kubelet、docker 等元件的預設版本,Node-Operator 會根據 ClusterPackageVersion 描述的資訊,控制各個節點的 kubelet、docker 等元件的版本。

Node-Operator 還支援控制某些元件灰度釋出到某些節點中。使用者只要提交描述這個灰度釋出的 CRD 到 Apiserver,Node-Operator 會有序的執行灰度釋出,並將釋出狀態反饋到 CRD 中。由於篇幅原因,我們不再贅述。

結束語

螞蟻金服在運維大規模 Kubernetes 叢集實踐中,我們擯棄了傳統的模式,使用了Operator 模式和麵向 Apiserver 程式設計。

Kubernetes 叢集的上下線、升級實現了 "Kubernetes as a Service" ,就像向雲廠商買一個服務一樣簡單。而 Worker 節點的運維,使用 Operator 模式能夠讓我們統一管理後設資料,自動化初始化、恢復 Worker 節點所需的元件。

此文作者是供職於 “螞蟻金服-資源排程” 部門的陳俊,微信聯絡方式: answer1991chen 。“螞蟻金服-資源排程” 部門求賢若渴,有意的同學請傳送簡歷到 chenjun.cj@alibaba-inc.com

深度 | 螞蟻金服自動化運維大規模 Kubernetes 叢集的實踐之路

長按關注,獲取最新分散式架構乾貨

歡迎大家共同打造 SOFAStack https://github.com/alipay




相關文章