導讀
此文章分享了螞蟻金服如何自動化運維大規模 Kubernetes 叢集的實踐幹貨。
"大規模 Kubernetes 叢集"主要展現在幾十個 Kubernetes 叢集,十萬級别的 Kubernetes Worker 節點。
螞蟻金服使用 Operator 的模式去運維 Kubernetes 叢集,能便捷、自動化的管理 Kubernetes 叢集生命周期,做到 " Kubernetes as a Service " 。
此文适合 Kubernetes 愛好者,Kubernetes 架構師,以及 PE/SRE 閱讀。
前序知識
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 是用代碼運維應用最好的實踐之一。
比如我們有一個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 角色
如何快速建立、下線一個 Kubernetes 叢集 (初始化、删除 Master 角色)。由于螞蟻業務的快速增長,我們随時面臨着需要在新機房建立、下線一個 Kubernetes叢集;CI 和測試也有快速建立、删除一個 Kubernetes 叢集的需求。
如何管理幾十個 Kubernetes 叢集 Master 元件版本。比如我們需要更新某幾個Kubernetes 叢集的 Apiserver,Scheduler 等元件。
如何自動化處理幾十個 Kubernetes 叢集 Master 元件發生的故障。
如何能擷取幾十個 Kubernetes 叢集 Master 元件的統一視圖。我們希望有一個統一的接口,一下就能擷取每個 Kubernetes 叢集 Master 角色的版本、狀态等資訊。
難點2:運維 Kubernetes Worker 節點
如何快速上線、下線 Kubernetes Worker 節點。上線時,我們需要保證 Kubernetes Worker 節點所需要的on-host軟體版本、配置正确。
如何更新十萬級别的 Kubernetes Worker 節點上的 on-host 軟體。如我們需要将所有Work節點的 docker、cni 版本更新到某個版本。
如何優雅的執行灰階釋出 Kubernetes Worker 節點上的軟體包。在 on-host 軟體新版本上線前,我們需要對它做小範圍的灰階釋出,即挑選 N 台 Worker 節點釋出新版本軟體包,執行驗證,最後根據驗證結果決定是否全規模的釋出新版本,或者復原這個灰階釋出。
如果自動化處理十萬級别的 Kubernetes Worker 節點可能出現的 on-host 軟體故障。比如 dockerkubelet 發生 panic,我們是否能自動化得處理。
實作方案
在螞蟻,我們使用 Kube-on-Kube-Operator 和 Node-Operator 組合使用解決上述的難題。
首先,我們需要借助工具,使用Kubernetes官方提供的方案( Static Pod 方式)部署“ Kubernetes 元叢集”(後面簡稱元叢集)到 “元叢集”的 Master 節點上。
然後,我們将 Kube-on-Kube-Operator 部署到 “ Kubernetes 元叢集”。我們将一個 Kubernetes 叢集所需的一系列 Master 元件當成一個複雜的應用。當我們需要一個“ Kubernetes 業務叢集”(後面簡稱業務叢集),我們隻需要向元叢集 Apiserver 送出用于描述“ Kubernetes 業務叢集”的 Cluster CRD Resource (下文會介紹我們如何設計 CRD 結構),Kube-on-Kube-Operator 就為我們準備好了一個可以工作的“Kubernetes 業務叢集”("業務叢集" Master 元件都已經Ready,需要擴容 Worker 節點)。
之後我們在“ Kubernetes 業務叢集”上,部署上 Node-Operator。Node-Operator 負責 Worker 節點的生命周期。當我們需要擴容一個 Worker 節點,我們隻需要送出描述 Worker 節點的中繼資料( IP, Hostname, 機器運維登入方式等)的 Machine CRD Resource (下文會介紹我們如何設計 CRD 結構),Node-Operator 就會将 Worker 節點初始化完成,并成功加入到 “ 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 業務叢集”的最終狀态:
Cluster CRD 的定義包含如下一些資訊:
業務叢集名。
業務叢集部署模式: 分為标準生産和最小化。标準生産提供Master元件都是3副本的部署,最小化則都是1個副本的部署。
業務叢集 Master 節點 NodeSelector,即表示如何在元叢集内如何選擇業務叢集Master 節點。
業務叢集各 Master 元件版本,自定義參數等
業務叢集所使用的 etcd 啟動配置,主要涉及 etcd data volume 的設定。有ClaimTemplate 和 VolumeSource 兩種模式,即使用 ClaimTemplate 模式就使用PVC 來初始化 etcd volume,而使用 VolumeSource 模式,即使用 VolumeSource 所表示的 volume 來挂載 etcd volume。
業務叢集 Master 元件證書過期時間: Master 元件所使用 kubeconfig 中的證書都有過期時間,以保證安全性。而 Kube-on-Kube-Operator 會在證書過期時自動完成滾動證書、Master 元件重新加載證書等操作。
業務叢集額外使用者 kubeconfig:即為 “額外使用者”提供的使用者名群組名,簽出證書,并生成 kubeconfig 儲存在元叢集 Secret 中供讀取。
業務叢集狀态: 這部分資訊不需要使用者送出,而是由 Kube-on-Kube-Operator 自動生成,使用者回報這個業務叢集的狀态,參考 Pod.Status 。
一個業務叢集的 Master元件 部署 實際是元叢集中的一系列 Resource 組成,即包括Deployment,Secret,Pod,PVC 等組合使用。各 Master 元件 所需要的部署 Resource 如下:
Apiserver: 一個 Deployment 即可,因為 Apiserver 是無狀态應用,副本數和Cluster CRD 描述的一緻即可。除此之外,需要為Apiserver建立兩個 Service:
向同個業務叢集的其它 Master 元件提供服務的 Service: 建議使用元叢集内的 Headless Service。
向 Kubelet、外部元件提供服務的 Service: 建議使用機房 DNS RR Service (需要自己實作 Service Controller )。
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還是保持一緻的。
Controller-Manager: 一個 Deployment 即可,因為 Controller-Manager 是無狀态應用。副本數和 Cluster CRD 描述的一緻即可。
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"狀态。架構圖如下:
Machine CRD 的定義包含如下一些資訊:
機器中繼資料: IP, Hostname, IDC 等
機器運維 ssh 登入方式和登入秘鑰: 如最常見的 SSH Key;如果 Machine 是阿裡雲的 ECS, 那麼登入方式和登入秘鑰是阿裡雲提供的 SSH 接口和對應的鑒權資訊等。
各個on-host 軟體版本和自定義參數
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 中。由于篇幅原因,我們不再贅述。