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



猜你喜欢

转载自blog.51cto.com/12480612/2457624