一、背景
1.1 什麼是彈性伸縮
根據使用者的業務需求和政策,自動調整其彈性計算資源的管理服務,其優勢有:
- 從應用開發者的角度:能夠讓應用程式開發者專注實作業務功能,無需過多考慮系統層資源
- 從系統運維者的角度:極大的降低運維負擔, 如果系統設計合理可以實作“零運維”
- 從管理者角度:極大降低成本
- 是實作 Serverless 架構的基石,也是 Serverless 的主要特性之一
1.2 k8s 自動彈性伸縮功能包括
- Pod 水準自動伸縮,HPA,Horizontal Pod Autoscaler
- Pod 垂直自動伸縮,VPA,Vertical Pod Autoscaler
- 叢集自動伸縮,CA,Cluster Autoscaler。後續會針對CA做源碼分析。
1.3 HPA
- 負責調整 pod 的副本數量來實作。是最常用的彈性伸縮元件
- 解決的是業務負載波動較大的問題
- 依賴 metrics-server 元件收集 pod 上的 metrics,然後根據預先設定的伸縮政策決定擴縮容 pod
- metrics-server 預設隻支援基于 cpu、memory 監控名額伸縮政策
- 如果要使用自定義名額(比如 QPS)作為伸縮政策,需要額外安裝 prometheus-adapter,将自定義名額轉換為 k8s apiserver可以識别的名額
- HPA-Controller 在k8s預設的 controller-manager 中已經安裝
1.4 VPA
- 負責調整單個 pod 的資源限額 request、limit 實作
- 解決的是資源配額評估不準的問題
- 依賴曆史負載名額,自動計算或調整資源配額
- VPA-Controller 需要額外安裝,參考
1.5 CA
- 負責調整 k8s node 節點數量實作叢集級别的擴縮容
- 依賴底層 IaaS 層的彈性伸縮能力
- CA-Controller 需要額外安裝,參考
1.6 三者使用場景
- VPA 用的比較少
- HPA 用的比較多,流量變化觸發 HPA,新增或減少 pod
- Pod變化如果觸發 pending或資源不足,會觸發 CA的自動擴縮容
二、HPA
2.1 架構
參考
- k8s 提供了一種标準 metrics 接口
- HPA Controller 通過這個統一 metrics 接口可以查下到任意一個 HPA對象關聯的 metrics 資料
- 查詢 metrics 的接口是通過 apiserver 的聚合層轉發到後端真實的 metric-server 和 prometheus-adapter
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICMyYTMvw1dvwlMvwlM3VWaWV2Zh1Wa-cWZwpmLmFmZwMDNyIGN4AjZyUjYwE2N0ATMwUjMmNDNwMTYhZzLcdzM0EzNwQzLcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.jpeg)
2.2 原生名額
- 最早 metrics 資料由 metric-server 提供,隻支援 cpu 和 memory 作為名額
- 通過采集 Node、kubelet 資料彙總到本地
- 沒有持久化,儲存在記憶體
2.4 自定義名額
- 為了适應更靈活的需求,metrics APi 開始支援擴充使用者自定義名額 custom metrics
- 需要自行開發 custom metrics server,社群提供開發架構 custom-metrics-apiserver
- 社群還提供了更通用的 promethus adapter 适配自定義名額已經存在 prometheus 中的情況
- prometheus 幾乎是監控标準,是以 prometheus-adapter幾乎可以滿足所有自定義名額需求
2.5 原理
- 使用者在 HPA 裡設定 metrics 類型和期望的目标 metrics 數值
- HPA Controller 定期(預設15s)reconcile 每個 HPA 對象
- reconcile 裡通過 metrics 的 API 擷取該 HPA 的 metrics 實時最新數值,并與目标值比較,确定擴縮容方向
- 計算出 Deployment 的目标副本數,最後調用 Deployment 的 scale 接口調整副本數
- 存在多個名額時,最終會選擇擴縮容幅度最大的那個為最終副本數
- 擴容有一定門檻值
- 縮容要超過一定冷卻器(預設5min)
2.6 metrics 的分類
最新版 HPA:autoscaling/v2beta1,有四種類型的 metrics
- Resource:支援k8s所有系統資源,包括cpu、memory。一般隻用cpu,memory不準确。
- Pods:由 pod 自身提供的自定義 metrics 資料
- Object:監控名額部署由 pod 本身的服務提供,比如 Ingress
- External:來自外部系統的自定義名額
2.7 使用示例
- scaleTargetRef:針對哪個負載進行HPA,幾乎隻會用于 Deployment 對象
- minReplicas:縮容的最小值
- maxReplicas:擴容的最大值
- type:前面介紹的4中之一,這裡使用 Resource
- resource.target.type:
- Utilization:百分比
- AveragetValue:平均值
- Value:精确值
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-test
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
複制
2.8 缺點
使用 HPA 能滿足一些場景,但是也存在一些缺點:
- 彈性不夠及時:pod啟動、預熱需要一定時間
- 如何配置 HPA不好把控
- 不支援 Dryrun,一點修改就會實際修改執行個體數量
可以參考騰訊開源的 EHPA,實作智能 HPA。
三、VPA
3.1 架構
參考
VPA 包含以下元件:
- History Storage:通過 metrics api采集和存儲監控資料
- Recommender:根據監控名額(History Storage)結合内置機制給出資源建議值
- Updater:實時更新 pod resource requests,監聽 VPA API,根據建議值動态修改 pod 資源
- VPA Admission Controller:用于 pod 建立時修改 request、limit
3.2 流程說明
- vpa 連接配接檢查 pod 在運作過程中占用的資源,預設間隔為10s一次
- 當發現 pod 資源占用到達門檻值時,vpa會嘗試更改配置設定的記憶體或cpu
- vpa嘗試更新部署元件中的pod資源定義
- pod重新開機,新資源将應用于建立出來的執行個體
3.3 運作模式
vpa 支援4中更新政策:
- Initial:僅在 pod 建立時修改,以後都不再修改
- Auto:預設政策,pod建立時、pod更改時都會修改
- Recreate:類似 Auto,在 Pod 的建立和更新時都會修改資源請求,不同的是,隻要Pod 中的請求值與新的推薦值不同,VPA 都會驅逐該 Pod,然後使用新的推薦值重新啟一個。是以,一般不使用該政策,而是使用 Auto,除非你真的需要保證請求值是最新的推薦值。
- Off:不改變 Pod 的資源請求,不過仍然會在 VPA 中設定資源的推薦值
3.4 使用注意
- 同一個 deployment,不能同時使用 hpa 和 vpa
- vpa 更新資源會導緻 pod 重建、重新開機、甚至重新排程
- vpa 使用 admission webhook ,需要確定與其他 webhook 不沖突
- vpa的性能沒有在大型叢集中測試過
- vap建議值可能超過實際資源上限,進而導緻pod處于pending無法被排程
- 多個 vpa 同時配置同一個pod會造成未定義的行為
- vpa不支援擴充控制器
3.5 總結
- 使用的場景太少,重新開機 pod業務不可接受
- 沒有大規模場景驗證,一般不太會用這個功能
四、CA
4.1 架構
參考
CA由一下幾個子產品組成:
- autoscaler:核心子產品,負責整體擴縮容功能
- Estimator:負責評估計算擴容節點
- Simulator:負責模拟排程,計算縮容節點
- Cloud Provider:與雲上 IaaS 層互動,負責增删改查節點。雲廠商需要實作相關接口。
4.2 擴縮容的時機
參考ca官方說明
- pod 因資源不足 pending,觸發擴容。不可排程後最多 10s 可以觸發擴容
- node 資源使用率低,且 node 上所有 pod 都能排程到其他 node 上。節點不可用後 10min 開始縮容
- 可以在啟動時關閉縮容功能
4.3 哪些pod會阻止CA縮容Node
- 節點上有pod被PodDisruptionBudget控制器限制。
- 節點上有命名空間是kube-system的pods。
- 節點上的pod不是被控制器建立,例如不是被deployment, replica set, job, stateful set建立。
- 節點上有pod使用了本地存儲
- 節點上pod驅逐後無處可去,即沒有其他node能排程這個pod
- 節點有注解:"cluster-autoscaler.kubernetes.io/safe-to-evict": "false"
4.4 配置某些Node禁止縮容
為節點添加特殊标簽: "cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"
kubectl annotate node <nodename> cluster-autoscaler.kubernetes.io/scale-down-disabled=true
複制
五、HPA + CA結合有多快
5.1 影響因素
當 CA 和 HPA 結合使用時,從負載增加到新 pod 運作的總時間主要由三個因素決定:
- HPA 反應時間
- CA 反應時間
- 節點建立時間
5.2 時間分析
具體每一環節的預設時間:
- kubelet 每隔 10s 對 pod 的 cpu 使用率名額進行抓取
- Metric server 每隔 1min 從 kubelet 擷取資料
- HPA 每隔 30s 檢查一次 Metric server 中的 CPU 負載名額
- CA 檢查到 pod pending 最多 10s 觸發擴容
5.3 具體數值
擴容最終時間:
- 做出擴容決定:預計大多數情況不到 30s
- 開出機器并且 pod 排程成功:取決于雲廠商,GCE一般是3~4min
縮容最終時間:
- 僅縮容pod:取決于 HPA 的縮容冷卻時間,預設好像是5min
- 縮容Node:CA的冷卻時間是10min
六、總結
本文針對 k8s 叢集擴容的背景、價值、實作做了大概的介紹,HPA 預設就可以使用,CA需要額外安裝元件使用,而VPA使用較少。我司正是使用了 HPA + CA的組合來實作關聯擴縮容,後續會做源碼級分析,敬請期待。