• 【kubernetes】带你入门k8s中的HPA


    1 为什么需要HPA

    k8s作为云操作系统,跟主机操作系统一样,核心功能就是管理云中的资源,例如,CPU、内存等。

    从业务角度上看,单个Pod能够提供的服务资源肯定是有限的,因此,在使用Deployment进行部署时可能会需要配置多个副本,那么,配置多少个合适呢?如果配置的副本数少,单个Pod的资源使用率会比较高,业务逻辑可能会执行异常;如果配置的副本数多,单个Pod的资源使用率会比较低,造成资源的浪费。有没有一种办法可以让Pod的副本数能够随业务的流量动态调整,当Pod资源使用率升高,就增加副本数,当Pod资源使用率降低,就减少副本数。

    也就是需要一种机制:它能够实时监控Pod的资源使用率,然后给Pod的资源使用率设置一个范围,当Deployment的Pod的平均资源使用率超过这个范围,则增加Pod的副本数;当Deployment的Pod的平均资源使用率低于这个范围,则减少Pod副本数。

    这就是k8s中的Horizontal Pod Autoscaler,简称HPA,翻译为水平Pod自动伸缩,水平的意思表明它是调整Pod的数量。既然有水平,那肯定有垂直,也就是调整Pod的参数配置,Vertical Pod Autoscaler,简称VPA,翻译为垂直Pod自动伸缩。无论是HPA还是VPA,都是在集群中自动进行Pod的伸缩,那如果平均资源使用率超过一定范围,而且HPA和VPA都不能扩容时,应该怎么办呢?此时,所有的节点的资源使用率都比较高,那就只能增加节点了,这就是Cluster Autoscaler,简称CA,翻译为集群自动伸缩

    它们实现的基本思路是:

    • 配置副本数的范围和目标资源使用率
    • 采集Pod或者Node的资源使用率
    • 控制器定时检测Pod或者Node的平均资源使用率
    • 如果平均资源使用率超过目标资源使用率,则进行Pod的扩容,但是不会超过配置的最大副本数
    • 如果平均资源使用率低于目标资源使用率,则进行Pod的缩容,但是不会低于配置的最小副本数

    2 HPA

    2.1 metrics-server组件部署

    由于要监控Pod的资源使用率,,就需要有组件可以采集Pod的资源使用率,最常见的是metrics-server。

    按照metrics-servers官方文档,直接执行下面的语句就可以完成metrics-server的部署:

    kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    
    • 1

    但是在实际使用中会发现有三个问题:

    • 镜像下载问题:将metrics-server的镜像仓库换成registry.aliyuncs.com/google_containers
    • 探针检查失败:将存活探针和就绪探针从http改成socket方式
    • 证书过期问题:对metrics-server的参数进行调整
        containers:
          - args:
            - --cert-dir=/tmp
            - --secure-port=4443
            - --kubelet-use-node-status-port
            - --metric-resolution=15s
            - --kubelet-insecure-tls
            - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
            - --requestheader-username-headers=X-Remote-User
            - --requestheader-group-headers=X-Remote-Group
            - --requestheader-extra-headers-prefix=X-Remote-Extra-
            image: registry.aliyuncs.com/google_containers/metrics-server:v0.6.4
            imagePullPolicy: IfNotPresent
            livenessProbe:
              failureThreshold: 3
              tcpSocket:
                port: 4443
              periodSeconds: 10
            name: metrics-server
            ports:
            - containerPort: 4443
              name: https
              protocol: TCP
            readinessProbe:
              failureThreshold: 3
              tcpSocket:
                port: 4443
              initialDelaySeconds: 20
              periodSeconds: 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    部署完成后用kubectl top nodekubectl top pod命令就可以看到按照资源使用率排序的node和pod,说明metrics-server正常工作了。

    2.2 聚合API

    有了metrics-server,那怎么提供给HPA Controller使用呢?或者说怎么能够让HPA Controller从metrics-server获取到指标数据呢?如果HPA Controller直接调用metrics-server的服务,那么两者就有依赖关系,不便于扩展。

    这里使用了Aggregate API的方式:在k8s中注册一个APIService的资源,APIService中指定了API的group、version和service的名称,当某个组件访问apiserver的接口时,会根据接口中的group和version,将调用转发给后端的service,这种方式就实现了对k8s api的一种扩展。

    HPA Controller在获取资源使用率时,group会设置为metrics.k8s.io,而metrics.k8s.io的常用的后端就是metrics-server。

    2.3 HPA扩缩容计算方式

    现在HPA Controller可以通过调用Aggregate API的方式获取Pod的资源使用率,下一步就是决策是否需要进行扩容和缩容。

    获取到Pod的资源使用率后,需要与定义的资源使用率限制进行对比,如果超过定义的资源使用率,则需要进行扩容,否则,进行缩容。

    这里以CPU使用率说明计算方式:

    当从metrics-server获取到nginx的Deployment的所有Pod中的容器的CPU使用量,然后计算出每个Pod的CPU使用量,再获取出Pod的CPU的requests使用量,然后将当前的CPU使用量/requests使用量,就得到单个Pod的CPU使用率,最终可以计算出Deployment的平均CPU使用率,再与预先定义的资源使用率限制进行对比。例如,当Deployment的Pod的平均CPU使用率是60,当前Pod数是3,用户设置目标CPU使用率是20,那么HPA就会认为Pod需要扩容至9,如果maxReplicas小于9,那就只会扩容到maxReplicas。

    下面看下HPA资源的定义和使用:

    apiVersion: autoscaling/v1
    kind: HorizontalPodAutoscaler
    metadata:
      name: nginx
    spec:
      maxReplicas: 10    # 最大副本数
      minReplicas: 1     # 最小副本数
      scaleTargetRef:    # 进行自动伸缩的目标资源
        apiVersion: apps/v1
        kind: Deployment
        name: nginx
      targetCPUUtilizationPercentage: 2 # 目标CPU使用率
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里需要注意的是:如果使用HPA对Pod进行管理,Pod就需要配置requests:pod.spec.containers.resources.requests

    # kubectl get hpa -o wide
    NAME    REFERENCE          TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    nginx   Deployment/nginx   0%/2%     1         10        1          23h
    
    • 1
    • 2
    • 3

    在TARGETS列展示的就是当前平均CPU使用率/目标CPU使用率

    当对该nginx的Deployment的Service增加负载:

    kubectl run test --image nginx --rm -i -- /bin/bash -c "while true; do curl service_ip:service_port;done"
    
    • 1

    然后用kubectl get pods --watch命令查看Pod的变化,并且可以看到

    请添加图片描述

    请添加图片描述

    2.4 快扩容,慢缩容

    但是上面的判断逻辑还有两个问题:

    • 多久执行一次判断?
    • 当某次判断需要扩容或者缩容时,是否立即就去进行扩容或者缩容?

    多久执行一次判断?这是通过kube-controller-manager的horizontal-pod-autoscaler-sync-period参数设置的,默认是15秒。

    那么,当某次执行判断认为需要需要进行扩容或者缩容时,是否就要立即进行扩容或者缩容呢?如果完全根据上面的计算方法进行扩容或者缩容,由于流量可能是变化的,而且获取metrics-server的数据可能有延后或者不稳定,可能导致前一次判断需要扩容,后一次判断需要缩容,从而导致集群的抖动,这肯定是不被允许的。为了解决这种场景,k8s提供了两种机制来减少抖动造成的影响:

    • horizontal-pod-autoscaler-tolerance参数控制副本变化幅度的范围,默认为0.1,因此,Pod扩缩容的变化比例必须不在[0.9,1.1]之间,也就是说,不是只要计算出需要扩容的比例就进行扩容,当计算出需要扩容的比例时,这个比例需要大于1.1,当缩容时这个比例需要小雨小于0.9。
    • 如果根据指标计算得到的最终Pod数量比当前Pod数量大很多,HPA不是一下就将Pod扩容至最终的目标数,而是针对变化的比例有限制,必须小于2,因此,一次扩容最多增加一倍,特例是,当原副本数为1时,最大可以扩容到4。

    以上主要针对的是扩容,当某个判断周期中计算得到的扩容比例位于[1.1,2]时,就可以进行扩容,此时可以快速解决业务负载高的问题,但是对于缩容则不能立即执行,因为缩容会带来业务上的不稳定,因此,HPA中会通过一个时间窗口进行若干次判断,如果这段时间的Pod变化比例都小于0.9就可以进行缩容,默认的时间窗口是5分钟。

    3 总结

    本文讲解了k8s中的HPA水平Pod伸缩机制,分析了扩缩容的整体流程,简单说明了扩缩容的计算方式,并对扩容和缩容中的工程实践中的一些机制进行了分析。

  • 相关阅读:
    【Nacos】源码之服务端服务注册
    ENVI5.6超详细教程大全-从安装包到安装流程详解
    彻底清除Mac缓存数据的方法,这样清理Mac缓存数据太干净了
    英语演讲常用连接词和句子
    局域网内无法连接时间源?使用Chrony服务搭建时间源
    解决SpringBoot项目配置文件自动提示功能消失解决方案
    Golang学习笔记—结构体
    搜狗输入法安装教程
    Nacos作为配置中心详解
    计算一个数的N次方,int和Integer的区别
  • 原文地址:https://blog.csdn.net/ILOVEYOUXIAOWANGZI/article/details/133831945