1. 程式人生 > >Kubernetes彈性伸縮全場景解讀(二) - HPA的原理與演進

Kubernetes彈性伸縮全場景解讀(二) - HPA的原理與演進

前言

在上一篇文章中,我們介紹了在Kubernetes在處理彈性伸縮時的設計理念以及相關元件的佈局,在今天這篇文章中,會為大家介紹在Kubernetes中彈性伸縮最常用的元件HPA(Horizontal Pod Autoscaler)。HPA是通過計算Pod的實際工作負載進行重新容量規劃的元件,在資源池符合滿足條件的前提下,HPA可以很好的實現彈性伸縮的模型。HPA到目前為止,已經演進了三個大的版本,在本文中會為大家詳細解析HPA底層的原理以及在Kubernetes中彈性伸縮概念的演變歷程。

HPA基本原理

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的基本原理後,我們來聊一下HPA的演進歷程,目前HPA已經支援了autoscaling/v1autoscaling/v1beta1autoscaling/v1beta2三個大版本。大部分的開發者目前比較熟悉的是autoscaling/v1的版本,這個版本的特點是隻支援CPU一個指標的彈性伸縮,大致的yaml內容如下:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50

接下來我們再來看一下v2beta1與v2beta2的yaml,會發現裡面支援的metrics型別增加了很多,結構也複雜了很多。

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        kind: AverageUtilization
        averageUtilization: 50
  - type: Pods
    pods:
      metric:
        name: packets-per-second
      targetAverageValue: 1k
  - type: Object
    object:
      metric:
        name: requests-per-second
      describedObject:
        apiVersion: extensions/v1beta1
        kind: Ingress
        name: main-route
      target:
        kind: Value
        value: 10k
---
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

而這些變化的產生不得不提的是Kubernetes社群中對監控與監控指標的認識與轉變。在Kubernetes中,有兩個核心的監控元件HeapsterMetrics Server。Heapster是早期Kubernetes社群中唯一的監控元件,它所包含的功能很強大,通過採集kubelet提供的metrics介面,並支援監控資料的離線與歸檔。
4831f8abbdaf67f45ac40f5d91fa5c5e.png

大致的架構圖如下,source的部分是不同的資料來源,主要是kubelet的common api與後來提供的summary api;processor的作用是將採集的資料進行處理,分別在namespace級別、cluster級別進行聚合,並建立新的聚合型別的監控資料;sink的作用是資料離線與歸檔,常見的歸檔方式包括influxdb、kafka等等。Heapster元件在相當長時間成為了Kubernetes社群中監控資料的唯一來源,也因此有非常多的和監控相關的元件通過Heapster的鏈路進行監控資料的消費。但是後來,Kubernetes社群發現了Heapster存在非常嚴重的幾個問題。

  • 強大繁多的Sink由不同的Maintainer進行維護,50%以上的Heapster Issues都是關於Sink無法使用的,而由於Maintainer的活躍度不同造成Heapster社群有大量的issues無法解決。
  • 對於開發者而言,監控資料的型別已經不再是CPU、Memory這麼簡單的幾個指標項了,越來越多的開發者需要應用內或者接入層的監控指標,例如ingress的QPS、應用的線上活躍人數等等。而這些指標的獲取是Heapster無法實現的。
  • Prometheus的成熟讓Heapster的生存空間不斷被擠壓,自從Prometheus被CNCF收錄為孵化專案,Heapster的不可替代地位被正式移除。

社群經過反思後,決定將監控的指標邊界進行劃分,分為Resource、Custom和External三種不同的Metrics,而Heapster(Metrics Server)的定位就只關心在了Resource這一種指標型別。為了解決程式碼維護性的問題,Metrics Server對Heapster進行了裁剪,裁剪後的架構如下:

99bf9ef330cace77238ede19f368f314.png

去掉了Sink的機制,並將呼叫方式改為標準的API註冊的方式,這樣的好處是既精簡了核心程式碼的邏輯又提供了替代的可能,也就是說此時Metrics Server也是可以替代的,只要實現了相同的API介面,並註冊到API Server上,就可以替代Metrics Server。

接下來我們解析一下三種不同的Metrics與使用的場景

API 註釋
Resource metrics.k8s.io Pod的資源指標,計算的時要除以Pod數目再對比閾值進行判斷
Custom custom.metrics.k8s.io Object: CRD等物件的監控指標,直接計算指標比對閾值
Pods : 每個Pod的自定義指標,計算時要除以Pods的數目
External external.metrics.k8s.io External:叢集指標的監控指標,通常由雲廠商實現

其中autoscaling/v2beta1支援Resource與Custom兩種指標,而autoscaling/v2beta2中增加了External的指標的支援。

最後

HPA目前已經進入了GA階段,在大體的功能上面不會進行過多的變化,目前社群的主要發力點在如何配置化的調整細節引數、豐富監控adapter的實現等等。在本文中,我們在概念上給大家介紹了HPA的一些原理以及發展的趨勢,在下一篇文章中,我們會為大家講解如何開啟v2beta1v2beta2的。