
作者 | 聲東 阿裡雲技術專家
<關注公衆号,回複 排查 即可下載下傳電子書>
《深入淺出 Kubernetes》一書共彙集 12 篇技術文章,幫助你一次搞懂 6 個核心原理,吃透基礎理論,一次學會 6 個典型問題的華麗操作!以下内容節選自本書:
阿裡雲 K8s 叢集的一個重要特性,是叢集的節點可以動态的增加或減少。有了這個特性,叢集才能在計算資源不足的情況下擴容新的節點,同時也可以在資源使用率降低的時候,釋放節點以節省費用。
這篇文章,我們将讨論阿裡雲 K8s 叢集擴容與縮容的實作原理。了解實作原理,在遇到問題的時候,我們就可以高效地排查并定位原因。
雖然我們的讨論是基于1.12.6 版本的,但是理論上後續版本與這篇文章所述叢集伸縮原理出入不大。
節點增加原理
阿裡雲 K8s 叢集可以給叢集增加節點的方式有,添加已有節點,叢集擴容,和自動伸縮。其中,添加已有節點又可分為手動添加已有節點和自動添加已有節點。節點的增加涉及到的元件有,節點準備,彈性伸縮(ESS),管控,Cluster Autoscaler 以及排程器。
手動添加已有節點
節點準備,其實就是把一個普通的 ECS 執行個體,安裝配置成為一個 K8s 叢集節點的過程。這個過程僅靠一條指令就可以完成。這條指令使用 curl 下載下傳 attach_node.sh 腳本,然後以 openapi token 為參數,在 ECS 上運作。
curl http:///public/pkg/run/attach//attach_node.sh | bash -s -- --openapi-token
這裡 token 是一個對的 key,而 value 是目前叢集的基本資訊。阿裡雲 K8s 叢集的管控,在接到手動添加已有節點請求的時候,會生成這個對,并把 key 作為 token 傳回給使用者。
這個 token(key)存在的價值,是其可以讓 attach_node.sh 腳本,以匿名身份在 ECS 上索引到叢集的基本資訊(value),而這些基本資訊,對節點準備至關重要。
總體上來說,節點準備就做兩件事情,讀和寫。讀即資料收集,寫即節點配置。
這裡的讀寫過程,絕大部分都很基礎,大家可以通過閱讀腳本來了解細節。唯一需要特别說明的是,kubeadm join 把節點注冊到 Master 的過程。此過程需要新加節點和叢集 Master 之間建立互信。
一邊,新加節點從管控處擷取的 bootstrap token(與 openapi token 不同,此 token 是 value 的一部分内容),實際上是管控通過可信的途徑從叢集 Master 上擷取的。新加節點使用這個 bootstrap token 連接配接 Master,Master 則可通過驗證這個 bootstrap token 來建立對新加節點的信任。
另一邊,新加節點以匿名身份從 Master kube-public 命名空間中擷取叢集 cluster-info,cluster-info 包括叢集 CA 證書,和使用叢集 bootstrap token 對這個 CA 做的簽名。新加節點使用從管控處擷取的 bootstrap token,對 CA 生成新的簽名,然後将此簽名與 cluster-info 内簽名做對比,如果兩個簽名一緻,則說明 cluster-info 和 bootstrap token 來自同一叢集。新加節點因為信任管控,是以建立對 Master 的信任。
自動添加已有節點
自動添加已有節點,不需要人為拷貝黏貼腳本到 ECS 指令行來完成節點準備的過程。管控使用了 ECS userdata 的特性,把類似以上節點準備的腳本,寫入 ECS userdata,然後重新開機 ECS 并更換系統盤。當 ECS 重新開機之後,會自動執行 Userdata 裡邊的腳本,來完成節點添加的過程。這部分内容,大家其實可以通過檢視節點 userdata 來确認。
!/bin/bash
mkdir -p /var/log/acs
curl http:///public/pkg/run/attach/1.12.6-aliyun.1/attach_node.sh | bash -s -- --docker-version --token --endpoint --cluster-dns > /var/log/acs/init.log
這裡我們看到,attach_node.sh 的參數,與前一節的參數有很大的不同。其實這裡的參數,都是前一節 value 的内容,即管控建立并維護的叢集基本資訊。自動添加已有節點省略了通過 key 擷取 value 的過程。
叢集擴容
叢集擴容與以上添加已有節點不同,此功能針對需要新購節點的情形。叢集擴容的實作,在添加已有節點的基礎上,引入了彈性伸縮 ESS 元件。ESS 元件負責從無到有的過程,而剩下的過程與添加已有節點類似,即依靠 ECS userdata 腳本來完成節點準備。下圖是管控通過 ESS 從無到有建立 ECS 的過程。
自動伸縮
前邊三種方式是需要人為幹預的伸縮方式,而自動伸縮的本質不同,是它可以在業務需求量增加的時候,自動建立 ECS 執行個體并加入叢集。為了實作自動化,這裡引入了另外一個元件 Cluster Autoscaler。叢集自動伸縮包括兩個獨立的過程。
其中第一個過程,主要用來配置節點的規格屬性,包括設定節點的使用者資料。這個使用者資料和手動添加已有節點的腳本類似,不同的地方在于,其針對自動伸縮這種場景,增加了一些專門的标記。attach_node.sh 腳本會根據這些标記,來設定節點的屬性。
!/bin/sh
curl http:///public/pkg/run/attach/1.12.6-aliyun.1/attach_node.sh | bash -s -- --openapi-token --ess true --labels k8s.io/cluster-autoscaler=true,workload_type=cpu,k8s.aliyun.com=true
而第二個過程,是實作自動增加節點的關鍵。這裡引入了一個新的元件 Autoscaler,它以 Pod 的形式運作在 K8s 叢集中。理論上來說,我們可以把這個元件當做一個控制器。因為它的作用與控制器類似,基本上還是監聽 Pod 狀态,以便在 Pod 因為節點資源不足而不能被排程的時,去修改 ESS 的伸縮規則來增加新的節點。
這裡有一個知識點,叢集排程器衡量資源是否充足的标準,是“預訂率”,而不是“使用率”。這兩者的差别,類似酒店房價預訂率和實際入住率:完全有可能有人預訂了酒店,但是并沒有實際入住。在開啟自動伸縮功能的時候,我們需要設定縮容門檻值,就是“預訂率”的下線。之是以不需要設定擴容門檻值。是因為 Autoscaler 擴容叢集,依靠的是 Pod 的排程狀态:當 Pod 因為節點資源“預訂率”太高無法被排程的時候,Autoscaler 就會擴容叢集。
節點減少原理
與增加節點不同,叢集減少節點的操作隻有一個移除節點的入口。但對于用不同方法加入的節點,其各自移除方式略有不同。
首先,通過添加已有節點加入的節點,需要三步去移除:管控通過 ECS API 清除 ECS userdata;管控通過 K8s API 從叢集中删除節點;管控通過 ECS InvokeCommand 在 ECS 上執行 kubeadm reset 指令清理節點。
其次,通過叢集擴容加入的節點,則在上邊的基礎上,增加了斷開 ESS 和 ECS 關系的操作。此操作由管控調用 ESS API 完成。
最後,經過 Cluster Autoscaler 動态增加的節點,則在叢集 CPU 資源“預訂率”降低的時候,由 Cluster Autoscaler 自動移除釋放。其觸發點是 CPU“預訂率”,即上圖寫 Metrics 的原因。
總結
總體上來說,K8s 叢集節點的增加與減少,主要涉及四個元件,分别是 Cluster Autoscaler,ESS,管控以及節點本身(準備或清理)。根據場景不同,我們需要排查不同的元件。其中 Cluster Autoscaler 是一個普通的 Pod,其日志的擷取和其他 Pod 無異;ESS 彈性伸縮有其專門的控制台,我們可以在控制台排查其伸縮配置、伸縮規則等相關子執行個體日志和狀态;而管控的日志,可以通過檢視日志功能來檢視;最後,對于節點的準備與清理,其實就是排查對應的腳本的執行過程。
以上講道理居多,但如果結合問題診斷實踐,一定會對大家的運維工作有所幫助。
“ 阿裡巴巴雲原生 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”