Kubernetes1.16基於Prometheus自定義指標彈性伸縮

    HPA原理

    K8S彈性伸縮,指在大業務量情況下,當前容器資源如cpu,內存,自定義指標等,已超出正常設定的範圍時進行的自動擴容操作,將業務負載到擴容後的容器上,降低容器壓力,直到達到HPA設定的容器數量上限,當業務量降低後,實現自動縮容操作。Kubernetes 中的 Metrics Server 持續採集所有 Pod 副本的指標數據。HPA 控制器通過 Metrics Server 的 API(Heapster 的 API 或聚合 API)獲取這些數據,基於用戶定義的擴縮容規則進行計算,得到目標 Pod 副本數量。當目標 Pod 副本數量與當前副本數量不同時,HPA 控制器就向 Pod 的副本控制器(Deployment、RC 或 ReplicaSet)發起 scale 操作,調整 Pod 的副本數量,完成擴縮容操作。

    HPA的具有擴縮容冷卻週期,防止因網絡抖動而造成的不必要擴縮容操作

    擴容冷卻時間默認值:3分鐘

    縮容冷卻時間默認值:5分鐘

    可以通過調整kube-controller-manager組件啓動參數設置冷卻時間:

        --horizontal-pod-autoscaler-downscale-delay :擴容冷卻

        --horizontal-pod-autoscaler-upscale-delay :縮容冷卻

    HPA發展初期只支持內存,cpu的自動擴縮容操作,不支持自定義指標,發展至今,已經可以通過第三方插件與Prometheus等監控服務進行交互,獲取到自定義指標,並轉換成apiserver能夠理解的內容,供HPA進行自動化擴縮容操作。如下圖

image.png


    HPA發展歷程

    

    目前 HPA 已經支持了 autoscaling/v1、autoscaling/v2beta1和autoscaling/v2beta2  三個大版本 。

    目前大多數人比較熟悉是autoscaling/v1,這個版本只支持CPU一個指標的彈性伸縮。

    而autoscaling/v2beta1增加了支持自定義指標,autoscaling/v2beta2又額外增加了外部指標支持。

    而產生這些變化不得不提的是Kubernetes社區對監控與監控指標的認識與轉變。從早期Heapster到Metrics Server再到將指標邊界進行劃分,一直在豐富監控生態。


    傳統HPA,只針對cpu,內存進行擴縮容編寫方式也很簡單,可以通過yaml,也可以通過kubectl 命令行形式設定閥值。


    v1版本:

        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


    v2beta2版本:

        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

          - type: Pods

            pods:

              metric:

                name: packets-per-second

              target:

                type: AverageValue

                averageValue: 1k

          - type: Object

            object:

              metric:

                name: requests-per-second

              describedObject:

                apiVersion: networking.k8s.io/v1beta1

                kind: Ingress

                name: main-route

              target:

                type: Value

                value: 10k

          - type: External

            external:

              metric:

                name: queue_messages_ready

                selector: "queue=worker_tasks"

              target:

                type: AverageValue

                averageValue: 30


        metrics中的type字段有四種類型的值:Object、Pods、Resource、External。

            Resource:指的是當前伸縮對象下的pod的cpu和memory指標,只支持Utilization和AverageValue類型的目標值。

            Object:指的是指定k8s內部對象的指標,數據需要第三方adapter提供,只支持Value和AverageValue類型的目標值。

            Pods:指的是伸縮對象Pods的指標,數據需要第三方的adapter提供,只允許AverageValue類型的目標值。

            External:指的是k8s外部的指標,數據同樣需要第三方的adapter提供,只支持Value和AverageValue類型的目標值。


基於Prometheus自定義指標縮放

1.部署Prometheus

參考我之前的博客部署即可


2.部署Prometheus Adapter

      但是prometheus採集到的metrics並不能直接給k8s用,因爲兩者數據格式不兼容,還需要另外一個組件(k8s-prometheus-adpater),將prometheus的metrics 數據格式轉換成k8s API接口能識別的格式,轉換以後,因爲是自定義    API,所以還需要用Kubernetes aggregator在主APIServer中註冊,以便直接通過/apis/來訪問。

       直接使用Helm Charts安裝

    

       # wget https://get.helm.sh/helm-v3.0.0-linux-amd64.tar.gz

       # tar zxvf helm-v3.0.0-linux-amd64.tar.gz 

       # mv linux-amd64/helm /usr/bin/

       # helm repo add stable http://mirror.azure.cn/kubernetes/charts

       # helm repo update

       # helm repo list

       image.png

        

       # helm install prometheus-adapter stable/prometheus-adapter --namespace kube-system --set prometheus.url=http://prometheus.kube-system,prometheus.port=9090

       # helm list -n kube-system

        image.png


       確保適配器adapter註冊到apiserver

       # kubectl get apiservices |grep custom 

       image.png

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

       image.png

        

    3.創建metrics deployment

    容器需要暴露出讓prometheus獲取數據的端口,metrics路徑,需要和開發商量好,服務暴露在外的需要監控的指標放在/metrics路徑下

    注意:鏡像爲私人鏡像,需要實驗的話,需要進行替換

        apiVersion: apps/v1

        kind: Deployment

        metadata:

          labels:

            app: metrics-app

          name: metrics-app

        spec:

          replicas: 3

          selector:

            matchLabels:

              app: metrics-app

          template:

            metadata:

              labels:

                app: metrics-app

              annotations:

                prometheus.io/scrape: "true"

                prometheus.io/port: "80"

                prometheus.io/path: "/metrics"

            spec:

              containers:

              - image: 172.30.0.109/metrics-app

                name: metrics-app

                ports:

                - name: web

                  containerPort: 80

                resources:

                  requests:

                    cpu: 200m

                    memory: 256Mi

                readinessProbe:

                  httpGet:

                    path: /

                    port: 80

                  initialDelaySeconds: 3

                  periodSeconds: 5

                livenessProbe:

                  httpGet:

                    path: /

                    port: 80

                  initialDelaySeconds: 3

                  periodSeconds: 5

        ---

        apiVersion: v1

        kind: Service

        metadata:

          name: metrics-app

          labels:

            app: metrics-app

        spec:

          ports:

          - name: web

            port: 80

            targetPort: 80

          selector:

            app: metrics-app    


        訪問容器/metrics路徑,得到總共http訪問量,經過prometheus指標轉換爲QPS

        image.png


    4.創建HPA規則

    針對容器QPS進行擴縮容操作,Pods類型只支持averageValue,deployment最大擴容數設爲10。

    HPA yaml:

        apiVersion: autoscaling/v2beta2

        kind: HorizontalPodAutoscaler

        metadata:

          name: metrics-app-hpa 

          namespace: default

        spec:

          scaleTargetRef:

            apiVersion: apps/v1

            kind: Deployment

            name: metrics-app

          minReplicas: 1

          maxReplicas: 10

          metrics:

          - type: Pods

            pods:

              metric:

                name: http_requests_per_second

              target:

                type: AverageValue

                averageValue: 800m   # 800m 即0.8個/秒


    配置好HPA後,hpa還不能獲取到http_requests_per_second的數據,kubetcl get hpa看到的獲取指標是unknown,需要在prometheus adapter適配器中配置http_requests_per_second

相當於白名單,去獲取prometheus中的指標數據。

    修改prometheus adapter configmap

    # kubectl edit cm -n kube-system prometheus-adapter

    新增:

    - seriesQuery: 'http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}'

      resources:

        overrides:

          kubernetes_namespace: {resource: "namespace"}

          kubernetes_pod_name: {resource: "pod"}

      name:

        matches: "^(.*)_total"

        as: "${1}_per_second"

      metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'

    image.png

    

    這裏主要是利用promSQL的形式通過將http_requests_total轉換成一個區間的平均訪問量,如上兩分鐘,求容器所有的和,即爲QPS


    注意:將/metrics中的http_requests_total名稱替換爲http_requests_per_second,HPA根據http_requests_per_second去獲取指標數據進行擴縮容操作

    prometheus-adapter配置修改後,需要重啓容器加載新的配置

    

    到這一步,指標已經獲取到了

    # kubectl get hpa

    image.png

    

    5.測試HPA

    進行壓測

    # yum install -y httpd-tools

    使用ab命令對metrics-app service進行壓力測試

     image.png

    

    查看HPA,指標數據已經打滿,deployment下的容器已經擴容到了10個,等壓力測試結束,就會自動縮容

    image.png



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章