k8s學習之-HPA


我們知道,當訪問量或資源需求過高時,使用:kubectl scale命令可以實現對pod的快速伸縮功能
但是我們平時工作中我們並不能提前預知訪問量有多少,資源需求多少。
這就很麻煩了,總不能為了需求總是把pod設置為最多狀態,這樣太浪費資源;也不能當請求量上來以后再去伸縮pod,這樣會有好多請求不成功。
k8s既然是雲原生時代的產品,當然得有智能,自動這些特性。
所以現在引入一個新的概念:
HPA(Horizontal Pod Autoscaler )

HPA是根據實際工作負載水平伸縮容器數目的組件,從中可以提煉出兩個非常重要的關鍵字:負載數目。我們可以用一個非常簡單的數學公式進行歸納:

bacc0483353082a419e4d86a069b906a.png

下面舉一個實際例子進行上述公式的闡述,假設存在一個叫ADeployment,包含3個Pod,每個副本的Request值是1核,當前3個Pod的CPU利用率分別是60%、70%與80%,此時我們設置HPA閾值為50%,最小副本為3,最大副本為10。接下來我們將上述的數據帶入公式中。

  • 總的Pod的利用率是60%+70%+80% = 210%。
  • 當前的Target是3。
  • 算式的結果是70%,大於閾值的50%閾值,因此當前的Target數目過小,需要進行擴容。
  • 重新設置Target值為5,此時算式的結果為42%低於50%,判斷還需要擴容兩個容器。
  • 此時HPA設置Replicas為5,進行Pod的水平擴容。

經過上面的推演,可以協助開發者快速理解HPA最核心的原理,不過上面的推演結果和實際情況下是有所出入的,如果開發者進行試驗的話,會發現Replicas最終的結果是6而不是5。這是由於HPA中一些細節的處理導致的,主要包含如下三個主要的方面:

  1. 噪聲處理

通過上面的公式可以發現,Target的數目很大程度上會影響最終的結果,而在Kubernetes中,無論是變更或者升級,都更傾向於使用Recreate而不是Restart的方式進行處理。這就導致了在Deployment的生命周期中,可能會出現某一個時間,Target會由於計算了Starting或者Stopping的的Pod而變得很大。這就會給HPA的計算帶來非常大的噪聲,在HPA Controller的計算中,如果發現當前的對象存在Starting或者StoppingPod會直接跳過當前的計算周期,等待狀態都變為Running再進行計算。

  1. 冷卻周期

在彈性伸縮中,冷卻周期是不能逃避的一個話題,很多時候我們期望快速彈出與快速回收,而另一方面,我們又不希望集群震盪,所以一個彈性伸縮活動冷卻周期的具體數值是多少,一直被開發者所挑戰。在HPA中,默認的擴容冷卻周期是3分鍾,縮容冷卻周期是5分鍾。

  1. 邊界值計算

我們回到剛才的計算公式,第一次我們算出需要彈出的容器數目是5,此時擴容后整體的負載是42%,但是我們似乎忽略了一個問題,一個全新的Pod啟動會不會自己就占用了部分資源?此外,8%的緩沖區是否就能夠緩解整體的負載情況,要知道當一次彈性擴容完成后,下一次擴容要最少等待3分鍾才可以繼續擴容。為了解決這些問題,HPA引入了邊界值△,目前在計算邊界條件時,會自動加入10%的緩沖,這也是為什么在剛才的例子中最終的計算結果為6的原因。

有了HPA,我們就不用為上面的問題而煩惱,HPA會幫我們自動完成pod的擴縮容。

當資源需求過高時,會自動創建出pod副本;當資源需求低時,會自動收縮pod副本數。
注意:首先必須確保集群中已經安裝metrics-server的組件,否則無法獲取集群內資源數據,無法進行以下操作。

具體這個組件不細講了,可以看我前面文章的介紹

在 Kubernetes 中,有兩個核心的監控組件 Heapster 與 Metrics Server。Heapster 是早期 Kubernetes 社區中唯一的監控組件,它所包含的功能很強大,
通過采集 kubelet 提供的 metrics 接口,並支持監控數據的離線與歸檔。目前已經由metrics server 取代

接下來我們解析一下三種不同的 Metrics 與使用的場景:
Resource metrics.k8s.io Pod的資源指標,計算的時要除以Pod數目再對比閾值進行判斷
Custom custom.metrics.k8s.io Object: CRD等對象的監控指標,直接計算指標比對閾值
Pods 每個Pod的自定義指標,計算時要除以Pods的數目
External external.metrics.k8s.io External:集群指標的監控指標,通常由雲廠商實現

                                                  

 

 

 

 


原理:
通過集群內的資源監控系統(metrics-server),來獲取集群中資源的使用狀態。
根據CPU、內存、以及用戶自定義的資源指標數據的使用量或連接數為參考依據,來制定一個臨界點,一旦超出這個點,HPA就會自動創建出pod副本,如下圖

 

 

 

HPA通過定期(定期輪詢的時間通過–horizontal-pod-autoscaler-sync-period選項來設置,默認的時間為30秒)通過Status.PodSelector來查詢pods的狀態,獲得pod的CPU使用率。然后,通過現有pods的CPU使用率的平均值(計算方式是最近的pod使用量(最近一分鍾的平均值,從metrics-serve中獲得)

除以設定的每個Pod的CPU使用率限額)跟目標使用率進行比較,並且在擴容時,還要遵循預先設定的副本數限制:MinReplicas <= Replicas <= MaxReplicas。

計算擴容后Pod的個數:sum(最近一分鍾內某個Pod的CPU使用率/量的平均值)/CPU使用上限的整數+1

流程
1、創建HPA資源,設定目標CPU使用率限額,以及最大、最小實例數
2、收集一組中(PodSelector)每個Pod最近一分鍾內的CPU使用率,並計算平均值
3、讀取HPA中設定的CPU使用限額
4、計算:平均值之和/限額,求出目標調整的實例個數
5、目標調整的實例數不能超過1中設定的最大、最小實例數,如果沒有超過,則擴容;超過,則擴容至最大的實例個數
6、回到2,不斷循環

HPA的演進歷程

在了解了HPA的基本原理后,我們來聊一下HPA的演進歷程,目前HPA已經支持了三個大版本

通過kubectl api-versions可以看到

autoscaling/v1 #只支持通過cpu為參考依據,來改變pod副本數
autoscaling/v2beta1 #支持通過cpu、內存、連接數以及用戶自定義的資源指標數據為參考依據。
autoscaling/v2beta2 #同上,小的變動

kubectl explain hpa ##默認查詢到的是autoscaling/v1版本
kubectl explain hpa --api-version=autoscaling/v2beta1 ##如果使用其他版本,可以使用--api-version指明版本

目前比較熟悉的是autoscaling/v1 的版本,這個版本的特點是只支持 CPU 一個指標的彈性伸縮
我們可以簡單的通過 kubectl autoscale 命令來創建一個 HPA 資源對象
Controller默認30s輪詢一次(可通過 kube-controller-manager 的--horizontal-pod-autoscaler-sync-period 參數進行設置),
查詢指定的資源中的 Pod 資源使用率,並且與創建時設定的值和指標做對比,從而實現自動伸縮的功能
kubectl autoscale deployment hpa-demo --cpu-percent=10 --min=1 --max=10
或者用yaml 文件

 

 

注意一下如果要想讓 HPA 生效,對應的 Pod 資源必須添加 requests 資源聲明

 

 

 kubectl describe hpa hpa-demo

 

 

現在可以看到 HPA 資源對象已經正常了,現在我們來增大負載進行測試,我們來創建一個 busybox 的 Pod,並且循環訪問上面創建的 Pod

$ kubectl run -it --image busybox test-hpa --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://10.244.4.97; done

$ kubectl get hpa

我們可以看到已經自動拉起了很多新的 Pod,最后定格在了我們上面設置的 10 個 Pod,同時查看資源 hpa-demo 的副本數量,副本數量已經從原來的1變成了10個

$ kubectl get pods -l app=nginx --watch

 

 

 kubectl get deployment hpa-demo

 

 

 同樣的這個時候我們來關掉 busybox 來減少負載,然后等待一段時間觀察下 HPA 和 Deployment 對象

 

基於內存和自定義指標

這里會用到兩個版本autoscaling/v1beta1 和 autoscaling/v1beta2

 

這兩的測試方式也可以通過上面的流程測試一下

除了基於 CPU 和內存來進行自動擴縮容之外,我們還可以根據自定義的監控指標來進行。這個我們就需要使用 Prometheus Adapter,Prometheus 用於監控應用的負載和集群本身的各種指標,Prometheus Adapter 可以幫我們使用 Prometheus 收集的指標並使用它們來制定擴展策略,這些指標都是通過 APIServer 暴露的,而且 HPA 資源對象也可以很輕易的直接使用。

這塊內容相關的可以參考我之前的文章

https://www.cnblogs.com/centos-python/articles/10921991.html

推薦一篇博文

https://github.com/stefanprodan/k8s-prom-hpa

https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

這里在強調說明一下,因為我這邊生成環境POD 是有兩個容器,分別是nginx 和  php,如果只對單個容器做資源聲明,HPA 的cpu資源不顯示,需要對兩個容器都做資源聲明

 

后續可以加監控監控這種HPA 的擴展

 

 這是我們線上報警的規則,當然監控的項目比較多,自己根據實際情況去監控,可以去prometheus 看相應的監控指標

 

我們現在回過頭來看看 metrics-server 創建的對象PodMetrics:

$ kubectl get podmetrics -n demo
NAME AGE
nginx-deployment-6d4b885966-zngnd 0s
nginx-deployment-6d4b885966-lgwd9 0s
nginx-deployment-6d4b885966-hhk7v 0s
$ kubectl get podmetrics -n demo nginx-deployment-6d4b885966-zngnd -o yaml
apiVersion: metrics.k8s.io/v1beta1
containers:
- name: nginx
usage:
cpu: "0"
memory: 5524Ki
kind: PodMetrics
metadata:
creationTimestamp: "2020-10-13T09:38:15Z"
name: nginx-deployment-6d4b885966-zngnd
namespace: demo
selfLink: /apis/metrics.k8s.io/v1beta1/namespaces/demo/pods/nginx-deployment-6d4b885966-zngnd
timestamp: "2020-10-13T09:37:55Z"

HPAController 就是通過這些 PodMetrics 來計算平均的 CPU 使用率,從而確定 spec.replicas 的新數值。

 

常見的問題匯總

https://help.aliyun.com/knowledge_detail/186980.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM