溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

監(jiān)控自定義指標的HPA怎么部署

發(fā)布時間:2021-12-24 09:57:35 來源:億速云 閱讀:159 作者:iii 欄目:云計算

本篇內容介紹了“監(jiān)控自定義指標的HPA怎么部署”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

HPA簡介

HPA(Horizontal Pod Autoscaler)是kubernetes(以下簡稱k8s)的一種資源對象,能夠根據(jù)某些指標對在statefulSet、replicaController、replicaSet等集合中的pod數(shù)量進行動態(tài)伸縮,使運行在上面的服務對指標的變化有一定的自適應能力。

HPA目前支持四種類型的指標,分別是Resource、Object、External、Pods。其中在穩(wěn)定版本autoscaling/v1中只支持對CPU指標的動態(tài)伸縮,在測試版本autoscaling/v2beta2中支持memory和自定義指標的動態(tài)伸縮,并以annotation的方式工作在autoscaling/v1版本中。HPA在k8s中的結構
首先可以看一下HPA在k8s中的結構,這里找了一個k8s官方給出的HPA例子,我在關鍵字段上給出一些注釋方便理解。

  - type: Pods
    pods:
      metric:
        name: packets-per-second
      # AverageValue類型的目標值,Pods指標類型下只支持AverageValue類型的目標值
      target:
        type: AverageValue
        averageValue: 1k
  # External類型的指標
  - type: External
    external:
      metric:
        name: queue_messages_ready
        # 該字段與第三方的指標標簽相關聯(lián),(此處官方文檔有問題,正確的寫法如下)
        selector:
          matchLabels:
            env: "stage"
            app: "myapp"
      # External指標類型下只支持Value和AverageValue類型的目標值
      target:
        type: AverageValue
        averageValue: 30

autoscaling/v1版本將metrics字段放在了annotation中進行處理。

target共有3種類型:Utilization、Value、AverageValue。Utilization表示平均使用率;Value表示裸值;AverageValue表示平均值。

metrics中的type字段有四種類型的值:Object、Pods、Resource、External。
Resource指的是當前伸縮對象下的pod的cpu和memory指標,只支持Utilization和AverageValue類型的目標值。
Object指的是指定k8s內部對象的指標,數(shù)據(jù)需要第三方adapter提供,只支持Value和AverageValue類型的目標值。
Pods指的是伸縮對象(statefulSet、replicaController、replicaSet)底下的Pods的指標,數(shù)據(jù)需要第三方的adapter提供,并且只允許AverageValue類型的目標值。
External指的是k8s外部的指標,數(shù)據(jù)同樣需要第三方的adapter提供,只支持Value和AverageValue類型的目標值。

HPA動態(tài)伸縮的原理

HPA在k8s中也由一個controller控制,controller會間隔循環(huán)HPA,檢查每個HPA中監(jiān)控的指標是否觸發(fā)伸縮條件,默認的間隔時間為15s。一旦觸發(fā)伸縮條件,controller會向k8s發(fā)送請求,修改伸縮對象(statefulSet、replicaController、replicaSet)子對象scale中控制pod數(shù)量的字段。k8s響應請求,修改scale結構體,然后會刷新一次伸縮對象的pod數(shù)量。伸縮對象被修改后,自然會通過list/watch機制增加或減少pod數(shù)量,達到動態(tài)伸縮的目的。

HPA伸縮過程敘述

HPA的伸縮主要流程如下:

1.判斷當前pod數(shù)量是否在HPA設定的pod數(shù)量區(qū)間中,如果不在,過小返回最小值,過大返回最大值,結束伸縮。

2.判斷指標的類型,并向api server發(fā)送對應的請求,拿到設定的監(jiān)控指標。一般來說指標會根據(jù)預先設定的指標從以下三個aggregated APIs中獲?。?code>metrics.k8s.io、custom.metrics.k8s.io、 external.metrics.k8s.io。其中metrics.k8s.io一般由k8s自帶的metrics-server來提供,主要是cpu,memory使用率指標,另外兩種需要第三方的adapter來提供。custom.metrics.k8s.io提供自定義指標數(shù)據(jù),一般跟k8s集群有關,比如跟特定的pod相關。external.metrics.k8s.io同樣提供自定義指標數(shù)據(jù),但一般跟k8s集群無關。許多知名的第三方監(jiān)控平臺提供了adapter實現(xiàn)了上述api(如prometheus),可以將監(jiān)控和adapter一同部署在k8s集群中提供服務,甚至能夠替換原來的metrics-server來提供上述三類api指標,達到深度定制監(jiān)控數(shù)據(jù)的目的。

3.根據(jù)獲得的指標,應用相應的算法算出一個伸縮系數(shù),并乘以目前pod數(shù)量獲得期望pod數(shù)量。系數(shù)是指標的期望值與目前值的比值,如果大于1表示擴容,小于1表示縮容。指標數(shù)值有平均值(AverageValue)、平均使用率(Utilization)、裸值(Value)三種類型,每種類型的數(shù)值都有對應的算法。以下幾點值得注意:如果系數(shù)有小數(shù)點,統(tǒng)一進一;系數(shù)如果未達到某個容忍值,HPA認為變化太小,會忽略這次變化,容忍值默認為0.1。
HPA擴容算法是一個非常保守的算法。如果出現(xiàn)獲取不到指標的情況,擴容時算最小值,縮容時算最大值;如果需要計算平均值,出現(xiàn)pod沒準備好的情況,平均數(shù)的分母不計入該pod。
一個HPA支持多個指標的監(jiān)控,HPA會循環(huán)獲取所有的指標,并計算期望的pod數(shù)量,并從期望結果中獲得最大的pod數(shù)量作為最終的伸縮的pod數(shù)量。一個伸縮對象在k8s中允許對應多個HPA,但是只是k8s不會報錯而已,事實上HPA彼此不知道自己監(jiān)控的是同一個伸縮對象,在這個伸縮對象中的pod會被多個HPA無意義地來回修改pod數(shù)量,給系統(tǒng)增加消耗,如果想要指定多個監(jiān)控指標,可以如上述所說,在一個HPA中添加多個監(jiān)控指標。

4.檢查最終的pod數(shù)量是否在HPA設定的pod數(shù)量范圍的區(qū)間,如果超過最大值或不足最小值都會修改為最大值或最小值。然后向k8s發(fā)出請求,修改伸縮對象的子對象scale的pod數(shù)量,結束一個HPA的檢查,獲取下一個HPA,完成一個伸縮流程。

HPA的應用場景

HPA的特性結合第三方的監(jiān)控應用,使得部署在HPA伸縮對象(statefulSet、replicaController、replicaSet)上的服務有了非常靈活的自適應能力,能夠在一定限度內復制多個副本來應對某個指標的急劇飆升,也可以在某個指標較小的情況下刪除副本來讓出計算資源給其他更需要資源的應用使用,維持整個系統(tǒng)的穩(wěn)定。非常適合于一些流量波動大,機器資源吃緊,服務數(shù)量多的業(yè)務場景,如:電商服務、搶票服務、金融服務等。

k8s-prometheus-adapter

前文說到,許多監(jiān)控系統(tǒng)通過adapter實現(xiàn)了接口,給HPA提供指標數(shù)據(jù)。在這里我們具體介紹一下prometheus監(jiān)控系統(tǒng)的adapter。

prometheus是一個知名開源監(jiān)控系統(tǒng),具有數(shù)據(jù)維度多,存儲高效,使用便捷等特點。用戶可以通過豐富的表達式和內置函數(shù),定制自己所需要的監(jiān)控數(shù)據(jù)。

prometheus-adapter在prometheus和api-server中起到了適配者的作用。prometheus-adapter接受從HPA中發(fā)來,通過apiserver aggregator中轉的指標查詢請求,然后根據(jù)內容發(fā)送相應的請求給prometheus拿到指標數(shù)據(jù),經過處理后返回給HPA使用。prometheus可以同時實現(xiàn)metrics.k8s.iocustom.metrics.k8s.io、 external.metrics.k8s.io三種api接口,代替k8s自己的matrics-server,提供指標數(shù)據(jù)服務。

prometheus-adapter部署能否成功的關鍵在于配置文件是否正確。配置文件中可以設定需要的指標以及對指標的處理方式,以下是一份簡單的配置文件,加上注釋以稍做解釋。

# 指標規(guī)則,可以多個規(guī)則共存,上一個規(guī)則的結果會傳給下一個規(guī)則
rules:
    # 計算指標數(shù)據(jù)的表達式
  - metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>)
    # 指標重命名,支持正則表達式。這里表示刪除指標名字中的"_seconds_total"
    name:
      as: ""
      matches: (.*)_seconds_total$
    # 指標與k8s資源通過標簽關聯(lián),這里將指標通過標簽與k8s的namspace和pod相互關聯(lián)
    resources:
      overrides:
        namespace:
          resource: namespace
        pod:
          resource: pod
    # 過濾指標條件
    seriesFilters: []
    # 指標查詢表達式,可以根據(jù)標簽等條件,篩選特定的指標
    seriesQuery: '{namespace!="",pod!=""}'

metricsQuery字段會在k8s請求時執(zhí)行,其中,“<<” “>>”是go的模板語法,Series表示指標名稱,LabelMatchers表示指標與k8s對象名稱匹配的標簽鍵值對,GroupBy表示指標數(shù)值歸并的標簽名。

不太好理解,這里截取官方文檔中的一個例子來進行說明,看了就應該明白了:

For instance, suppose we had a series http_requests_total (exposed ashttp_requests_per_second in the API) with labels service, pod,ingress, namespace, and verb. The first four correspond to Kubernetes resources. Then, if someone requested the metric pods/http_request_per_second for the pods pod1 and pod2 in the somens namespace, we’d have:

- Series: "http_requests_total"

- LabelMatchers: "pod=~\"pod1|pod2",namespace="somens"

- GroupBy: pod

resources字段是k8s資源對象與指標關聯(lián)的重要字段,本質上是根據(jù)指標的標簽值與k8s資源對象名稱進行匹配,resources字段告訴系統(tǒng),應該用指標的哪個標簽的標簽值來匹配k8s資源對象名稱。有兩個方法關聯(lián)資源,一種是通過overrides,將特定的標簽與k8s資源對象綁定起來,當k8s請求指標的時候,會將資源對象名稱與這個特定的標簽值進行比較,來分辨指標具體是哪個對象的;另一種是template,通過go語言模板語法將k8s資源對象名轉化成標簽名,進行匹配。

第二種方法,不太好理解,同樣截取官方文檔中的一個例子來進行說明:

# any label `kube_<group>_<resource>` becomes <group>.<resource> in Kubernetes
resources:
template: "kube_<<.Group>>_<<.Resource>>"

部署一個監(jiān)控自定義指標的HPA

1.部署prometheus應用,使其正常工作??梢允褂霉俜降膆elm包快捷部署,之后的應用也基本以helm包的方式部署,不再贅述。

2.部署需要伸縮的應用。這里我選擇了一個簡單的nginx服務,部署為deployment作為伸縮對象。

監(jiān)控自定義指標的HPA怎么部署

3.在應用的命名空間下,部署提供自定義指標的應用。這里我選擇了官方的prometheus-node-exporter,并以nodeport的方式暴露數(shù)據(jù)端口,作為自定義指標數(shù)據(jù)的來源。這個應用會以daemonSet的方式運行在k8s集群的每個node上,并對外開放在自己node上獲取到的指標。

監(jiān)控自定義指標的HPA怎么部署

在prometheus的界面上已經可以看到node-exporter暴露出來的指標了

監(jiān)控自定義指標的HPA怎么部署

4.部署prometheus-adapter應用。在helm包的values中修改其配置文件,配置文件如下

      resources:
        template: <<.Resource>>
      seriesFilters: []
      seriesQuery: '{namespace!="",pod!=""}'
    - metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>)
      name:
        as: ""
        matches: (.*)_total$
      resources:
        template: <<.Resource>>
      seriesFilters:
      - isNot: (.*)_seconds_total$
      seriesQuery: '{namespace!="",pod!=""}'
    - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
      name:
        as: ""
        matches: (.*)$
      resources:
        template: <<.Resource>>
      seriesFilters:
      - isNot: (.*)_total$
      seriesQuery: '{namespace!="",pod!=""}'

上述配置文件將secondstotal和_total結尾的指標用prometheus的內置函數(shù)進行了速率計算,并去掉對應的后綴作為指標名稱。

我們在k8s中利用kubectl查看指標是否能夠獲得到指標

kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/

你會看到所有的你能夠獲得的指標名稱,但是名字和數(shù)據(jù)已經和原來的指標有所不同了,因為我們在adapter的配置文件中做了一定程度的修改。

然后我們獲取一下node_cpu這個指標,看看是否能夠正確地顯示出來

kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/my-nginx/pods/*/node_cpu | jq

這個命令能夠顯示my-nginx這個namspace下的所有pod的node_cpu指標的數(shù)據(jù),結果如下

{
  "kind": "MetricValueList",
 "apiVersion": "custom.metrics.k8s.io/v1beta1",
  "metadata": {
 "selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/my-nginx/pods/%2A/node_cpu"
  },
 "items": [
    {
   "describedObject": {
        "kind": "Pod",
     "namespace": "my-nginx",
        "name": "prometheus-node-exporter-b25zl",
        "apiVersion": "/v1"
      },
      "metricName": "node_cpu",
      "timestamp": "2019-10-29T03:33:47Z",
      "value": "3822m"
    }
  ]
}

ok,到這里,說明所有的組件工作正常,hpa能夠順利地得到這個指標。需要注意的是HPA和監(jiān)控對象,伸縮對象一定要部署在同一個命名空間下,不然會獲取不到相應的指標。

5.部署hpa,其yaml文件如下

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-asdfvs
  namespace: my-nginx
spec:
  scaleTargetRef:
    apiVersion: apps/v1beta1
    kind: Deployment
    name: my-nginx
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Object
    object:
      metric:
        name: node_cpu
      describedObject:
        apiVersion: v1
        kind: Pod
        name: prometheus-node-exporter-b25zl
      target:
        type: Value
        value: 9805m

我們將根據(jù)prometheus-node-exporter這個pod的node_cpu這個指標來動態(tài)伸縮我們的nginx應用。

我們來獲取一下這個hpa

kubectl get horizontalPodAutoscaler -n my-nginx hpa-asdfvs -oyaml

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  annotations:
    autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2019-10-29T02:54:50Z","reason":"ReadyForNewScale","message":"recommended
      size matches current size"},{"type":"ScalingActive","status":"True","lastTransitionTime":"2019-10-29T03:05:24Z","reason":"ValidMetricFound","message":"the
      HPA was able to successfully calculate a replica count from Pod metric node_cpu"},{"type":"ScalingLimited","status":"False","lastTransitionTime":"2019-10-29T02:54:50Z","reason":"DesiredWithinRange","message":"the
      desired count is within the acceptable range"}]'
    autoscaling.alpha.kubernetes.io/current-metrics: '[{"type":"Object","object":{"target":{"kind":"Pod","name":"prometheus-node-exporter-b25zl","apiVersion":"v1"},"metricName":"node_cpu","currentValue":"3822m"}}]'
    autoscaling.alpha.kubernetes.io/metrics: '[{"type":"Object","object":{"target":{"kind":"Pod","name":"prometheus-node-exporter-b25zl","apiVersion":"v1"},"metricName":"node_cpu","targetValue":"9805m"}}]'
    kubectl.kubernetes.io/last-applied-configuration: |
  {"apiVersion":"autoscaling/v2beta2","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"hpa-asdfvs","namespace":"my-nginx"},"spec":{"maxReplicas":10,"metrics":[{"object":{"describedObject":{"apiVersion":"v1","kind":"Pod","name":"prometheus-node-exporter-b25zl"},"metric":{"name":"node_cpu"},"target":{"type":"Value","value":"9805m"}},"type":"Object"}],"minReplicas":1,"scaleTargetRef":{"apiVersion":"apps/v1beta1","kind":"Deployment","name":"my-nginx"}}}
  creationTimestamp: "2019-10-29T02:54:45Z"
  name: hpa-asdfvs
  namespace: my-nginx
  resourceVersion: "164701"
  selfLink: "/apis/autoscaling/v1/namespaces/my-nginx/horizontalpodautoscalers/hpa-asdfvs"
  uid: 76fa6a19-f9f7-11e9-8930-0242c5ccd054
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1beta1
    kind: Deployment
    name: my-nginx
status:
  currentReplicas: 1
  desiredReplicas: 1
  lastScaleTime: "2019-10-29T03:06:10Z"

可以看到hpa以annotation的方式在v1版本工作,并將matrics字段寫入了annotation中。在annotation的condition字段中,我們清楚地看到HPA已經獲取到了這個指標。之后我們可以嘗試降低target值來讓pod擴展,或者增加target值來使pod縮減。

“監(jiān)控自定義指標的HPA怎么部署”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

hpa
AI