基於自定義指標的HPA實戰


概念

Kubernetes自1.11版本開始引入了名為"HorizontalPodAutoscaler"的控制器用於完成Pod基於CPU使用率進行水平擴展。所謂水平擴展是在Pod中CPU的使用率達到設定的某個值時,HPA告知Pod對應的高層控制器(如Deployment、RS等控制器)。高層控制器隨即創建出多個pod副本平衡負載使Pod的平均CPU使用率低於我們設定的值。當Pod的平均CPU使用率變小時,又能回收多余的Pod以避免資源浪費。

image-20210313152925460

除了CPU使用率這個指標外,還可以采用自定義的指標。通常自定義的指標需要容器以某種方式提供,如URL路徑"/metrics"提供,即http:// : /metrics獲取相應的指標數據。當然如果kubernetes構建在公有雲上,亦可以采用公有雲服務商提供的指標數據如負載均衡器的QPS等作為HPA控制器的指標來源。

HPA控制器配置

目前HPA(HorizontalPodAutoscaler)資源對象處於Kubernetes的API組"autoscaling"中,包括v1、v2beta1及v2beta2三個API版本,其中"autoscaling/v1"僅支持基於CPU的自動擴縮容,而"autoscaling/v2"則支持基於自定義指標類型的數據。
為了使用HPA需要實現部署Metrics-Server。項目地址https://github.com/kubernetes-sigs/metrics-server,由於我本地環境是用Operator部署的Prometheus,部署完自帶metrics-server,所以不再手動部署。

image-20210313161330100

部署完成metrics-server后稍等一會后就可以使用kubectl top node/pod命令查看節點或者pod的CPU及內存使用率了。

image-20210313161538317

(1)基於autoscaling/v1版本的HPA配置,僅可以設置CPU使用率

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  miniReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 50
  • scaleTargetRef:定義目標作用對象,可以是Deployment、RS
  • targetCPUUtilizationPercentage:目標pod的CPU閾值,超過這個值即觸發擴容操作
  • miniReplicas及maxReplicas:最小及最大副本數量,HPA會自動在這個范圍內進行Pod的自動伸縮同時維持各個Pod的CPU使用率為50%

(2)基於autoscaling/v2beta2的HPA配置

type=Resource

type=Resource的指標數據由metrics-server采集並提供給HPA控制器

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: sample-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sample-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu / memory
      target:
        type: Utilization
        averageUtilization: 50  / averageValue: 200MiB

其中type字段可為:

  • Resource:基於資源的指標值,指標數據可以通過metrics.k8s.io這個API查詢。

  • Pods:基於Pod的指標

  • Object:基於某種資源對象,如ingress或者任意自定義的指標
    Pods與Object是自定義指標,需要搭建自定義的Metrics Server和監控工具進行指標采集。指標數據通過custom.metrics.k8s.io進行查詢,必須先啟動自定義的Metrics Server。

type=pods(本次采用的類型)

類型為Pods的類型指標數據來源於Pod對象本身,target指標只能是AverageValue

  metrics:
  - type: Pods
    pods:
      metrics:
        name: packet-per-second
      target:
        type: AverageValue
        averageValue: 1k

type=object

type=object的指標數據來自其他資源或者是自定義的指標。target指標為Value或者是AverageValue

#指標名稱為requests-per-second,其值來源於Ingress"main-route"的目標值,即Ingress每秒請求量達到2000時觸發擴容操作
    metrics:
    - type: Object
      object:
        metric:
          name: requests-per-second
        describeObject:
          apiVersion: extensions/v1beta1
          kind: Ingress
          name: main-route
        target:
          type: Value
          value: 2k
#指標名稱為requests-per-second,其值來源於Ingress"main-route"的目標值,即Ingress每秒請求量達到2000時觸發擴容操作
    metrics:
    - type: Object
      object:
        metric:
          name: 'http_requests'
          selector: 'verb=GET'
        target:
          type: AverageValue
          averageValue: 500

基於自定義指標的HPA實戰

整體概述

image-20210313164205820

按照《Kubernetes權威指南(第四版)》所述的架構圖,由Prometheus采集各個pod的指標通過prometheus-adapter這個適配器將數據提交給指標聚合器,並最終注冊到api-server中,以/apis/custom.metrics.k8s.io的路徑提供指標數據。HPA控制器從該路徑下獲取數據作為水平自動擴縮容的依據。

配置controller-manager

一般而言通過kubeadm部署的k8s集群不需要進行api-server的手動配置,所需要的配置已經默認開啟。我們只需要配置kube-controller-manager的參數即可。

image-20210313164735322

編輯/etc/kubernetes/manifests/kube-controller-manager.yaml添加上圖所示的啟動參數。為了加快試驗的效果,這里縮短了默認的配置。生產環境推薦以官方默認配置為准。

創建對象pod

該pod會在/metrics路徑下提供名為http_requests_total的指標。

apiVersion: v1
kind: Service
metadata:
  name: sample-app
  labels:
    app: sample-app
spec:
  selector:
    app: sample-app
  ports:
  - name: http
    port: 80
    targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  labels:
    app: sample-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - image: luxas/autoscale-demo:v0.1.2
        name: metrics-provider
        ports:
        - name: http
          containerPort: 8080

image-20210313165453521

創建ServiceMonitor對象,用於監控程序提供的指標

$ cat service-monitor.yaml 
kind: ServiceMonitor
apiVersion: monitoring.coreos.com/v1
metadata:
  name: sample-app
  labels:
    app: sample-app
spec:
  selector:
    matchLabels:
      app: sample-app
  endpoints: 
  - port: http

注意:這里的port:http一定要和上面部署的Service對象中port的名稱一致。應用該對象后稍等2~3分鍾打開promethes的頁面,即可發現相應的監控項已經是up狀態:

image-20210313165930266

配置Adapter

以上配置的指標作http_requests_total為一種持續增長的值,不能反映單位時間內的增長量,不能用作HPA的依據。需要進行適當地轉換,打開adapter的配置,添加如下配置並應用:

image-20210313170429702

config.yaml: |
    rules:
                    #sum(rate(http_requests_total{namespace="xx",pod="xx"}[1m])) by pod:1分鍾內全部pod指標http_requests_total的總和的每秒平均值
    - metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)                                       
      #將metricsQuery計算的結果賦給新的指標`http_requests`並提供給HPA控制器
      name:
        as: "${1}"
        matches: ^(.*)_total$
      resources:
        template: <<.Resource>>
      seriesFilters:
      - isNot: .*_seconds_total$
      seriesQuery: '{namespace!="",__name__=~"http_requests_.*"}'

應用configmap完成后刪除adapter Pod,使新的配置生效。

自定義API資源

創建名為v1beta1.custom.metrics.k8s.io的自定義聚合API資源

apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
  name: v1beta1.custom.metrics.k8s.io
spec:
  service:
    name: prometheus-adapter
    namespace: monitoring
  group: custom.metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100

創建HPA控制器資源

在以上資源創建完成后即可以創建HPA控制器了

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta2
metadata:
  name: sample-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sample-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests
      target:
        type: AverageValue
        averageValue: 500m
  • type=pods:表示從Pods自身獲取指標
  • name=http_requests:即adapter中的配置,有http_requests_total計算而來
  • averageValue=500m:即http_requests的目標值為500m。

通過聚合API查詢指標數據,pod指標成功采集

image-20210313172852633

image-20210313172954061

驗證動態擴縮容

在其他終端請求sample-app的地址進行壓測:

$ for i in {1..100000};do wget -q -O- 10.233.38.160 > /dev/null;done

image-20210313173159598

自動擴容成功

停止訪問請求一分鍾后(kube-controller-manager中設定的參數--horizontal-pod-autoscaler-downscale-stabilization=1min進行縮容操作)pod數量成功回落到1個

image-20210313173612060

參考

  • 《Kubernetes權威指南(第四版)》(p241-p264)


免責聲明!

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



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