AWS EKS Horizontal Pod Autoscaler(HPA)

简介


本文是《AWS EKS 集群自动扩容 Cluster Autoscaler》一文中引申部分的扩展,介绍 Horizontal Pod Autoscaler(HPA)。

本文先简单介绍 Horizontal Pod Autoscaler,然后以前文的 EKS 测试环境为基础,进行简单测试。

HPA 算法介绍部分写的比较笼统,看不明白,可以先略过,先做测试,有个直观感受后再回头研究具体算法。

目录


  • 环境(配置)
  • Horizontal Pod Autoscaler 简介
    • HPA 版本
    • HPA 算法介绍
  • 实战步骤
    1. 部署 metrics server
    2. 部署测试应用
    3. 创建 Horizontal Pod Autoscaler
    4. 测试 Horizontal Pod Autoscaler
      • 增加 CPU 负载
      • 降低 CPU 负载
  • 总结
  • 引申
  • 资源下载
  • 后记

环境(配置)


  • AWS Global 帐号,可在官网申请,一年内使用指定资源免费
  • AWS EKS
  • Win10 + WSL
  • AWS CLI 2.2.17 如何 aws 版本太低还需要手工安装插件,建议升级到高版本
  • Kubectl

Horizontal Pod Autoscaler 简介


Horizontal Pod Autoscaler(HPA)基于资源 CPU 利用率(也可以基于 custom metrics)自动调整 deployment、replication controller 或者 replica 中 pod 的数量,以适应需要。

Horizontal Pod Autoscaler 以标准 Kubernetes API 资源和 controller 的方式实现,Kubernetes 本身已经包含了 Horizontal Pod Autoscaler 的 controller,所以不需要额外部署(这与 Cluster Autoscaler 不同)。

虽然 Horizontal Pod Autoscaler 不需要额外部署 controller,但它需要获取 metrics 信息,metrics 信息需要从 Metrics Server 中获取或者从第三方软件获取。

HPA 工作原理
AWS EKS Horizontal Pod Autoscaler(HPA)

Horizontal Pod Autoscaler 会周期性查询目标资源使用情况,然后和 HorizontalPodAutoscaler 中定义的值做比较,然后相应的调整 pod 数量。

周期大小通过 controller manager “--horizontal-pod-autoscaler-sync-period” flag 控制,默认为 15 秒。

主要有三种 metric

  1. per-pod resource metrics (like CPU)

这时 target 设定的值可以是利用率(utilization),也可以是一个具体的值(raw value)。HPA controller 会利用 metric 计算出当前 pod 利用率或者具体值的平均值,然后与 target 设定的值一起计算出一个调整比率(ratio)。

注意在使用时,pod 中要设定好 resource request 的值。比如我们要在 Pod 中设定使用的 CPU 数量,如果没有设置的话,是无法计算 CPU 利用率的。

  1. per-pod custom metrics

与第一种类型类似,但只能配合具体的值(raw value)工作

  1. object metrics and external metrics

用来描述对象信息的 metric

对于第一种 metric,我们可以通过 metric server 获得。对于后两种则需要第三方软件支持(比如 Prometheus Adapter)。我们下面只测试第一种 metric。

HPA 版本

Horizontal Pod Autoscaler 属于 K8s autoscaling API group,目前 autoscaling/v1 是稳定版本,只支持 CPU metrics autoscaling。

在 autoscaling/v2beta2 版本中,加入了 memory 和 custom metrics,这些指标在配合 autoscaling/v1 时,以 annotations 的形式出现。

HPA 算法介绍

HAP 以下列公式为基础计算调整比率(ratio)

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

例 1:
某个 deployment 中当前 replicas 设置为 2,CPU request 值为 100m(desiredMetricValue),当前从 metric server 得到的 CPU metric 为 200m(currentMetricValue)

100m,代表 0.1 个 CPU

则:desiredReplicas = 2 * ( 200 / 100 ) = 4,即运行的 Pod 数量会翻倍,ratio = 2

如果当前 CPU metric 为 50m

则:desiredReplicas = 2 * ( 50 / 100 ) = 1,即运行的 Pod 数量减半,ratio = 0.5

当 ratio 计算出来与 1 接近时,则不会变化,以防止出现过度扩展或者收缩,默认变化小于 0.1(tolerance)时(即 ratio 计算出来大于 0.9 小于 1.1)不会变动。

我们可以通过--horizontal-pod-autoscaler-tolerance 改变这个默认值。

当指定了 targetAverageValue 或者 targetAverageUtilization 值 ,计算 currentMetricValue 时会把得到的结果对目标(比如 deployment)中所有的 Pod 的数量取平均值。

在计算平均值时,正在停止或者失败的 Pod 不记入 Pod 数量。这里会计算两次平均值。

在第一次计算平均值时,不是 ready 状态和缺少 metric 的 Pod不记入Pod 总数。

在第二次计算平均值时,不是 ready 状态和缺少 metric 的 Pod记入Pod 总数。

用两次计算平均值算出对应的调整比率(ratio),如果第二次算出的 ratio 反转了 scale 方向,或者处于 tolerance 之内则放弃 scale,否则按第二次算出的 ratio 进行调整。

如果在 HPA 中指定多个目标 metric,则对每个 metric 重复上述计算过程,最后取 desiredReplicas 最大的值做为调整值。

最后,scale up 会尽快进行,而 scale down 会逐步进行,默认间隔为 5 分钟,可以通过--horizontal-pod-autoscaler-downscale-stabilization flag 更改设置。

在 5 分钟之内,每隔 15 秒计算一次 scale down 的值,最后取所有结果中最大的值做为这次 scale down 的最终值。

注意:目前 AWS EKS 并不支持自行设置 control plane flag,所以上述 flag 无法在 EKS 中改动,但在 autoscaling/v2beta2 中可以在 HPA 对象中控制 scaling 的行为。

实战步骤


1. 部署 metrics server

我们在《多种方式访问 AWS EKS 的 Kubernetes Dashboard 上篇》一文中已经在 EKS 中部署了 metrics server,这个 metrics server 就可以做为 Horizontal Pod Autoscaler 获取 metrics 的资源。

2. 部署测试应用

下载 K8s 官网的测试应用

wget --no-check-certificate https://k8s.io/examples/application/php-apache.yaml

AWS EKS Horizontal Pod Autoscaler(HPA)

php-apache.yaml 文件创建了一个 deployment “php-apache”和一个 service,文件内容截取一段如下

  #1
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
        #2
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m

说明:

  • #1 默认 replicas 为 1
  • #2 在 spec.containers.resources 中设定需要的 CPU 资源
    • limit:最多可使用资源,500m(0.5 个 CPU)
    • requests:期望使用资源(desiredMetricValue),200m(0.2 个 CPU)

运行以下命令创建应用

kubectl apply -f php-apache.yaml

AWS EKS Horizontal Pod Autoscaler(HPA)

观察部署的 php-apache pod

kubectl get pods

php-apache-d4cf67d68-2qllw 处于 pending 状态
AWS EKS Horizontal Pod Autoscaler(HPA)

用 describe 查看 pod 详情,可以看到我们在上一篇文章中部署的 Cluster Autoscaler 开始工作,扩容 node 了

kubectl describe pods/php-apache-d4cf67d68-2qllw
Events:
  Type     Reason            Age                From                Message
  ----     ------            ----               ----                -------
  Warning  FailedScheduling  72s (x2 over 73s)  default-scheduler   0/2 nodes are available: 2 Too many pods.
  Normal   TriggeredScaleUp  71s                cluster-autoscaler  pod triggered scale-up: [{eks-tsEKSnodeGrp-80be391c-95d8-ba91-fd97-e8b0b3f23444 2->3 (max: 3)}]
  Warning  FailedScheduling  2s (x3 over 32s)   default-scheduler   0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate, 2 Too many pods.

AWS EKS Horizontal Pod Autoscaler(HPA)
AWS EKS Horizontal Pod Autoscaler(HPA)

过一段时间再看 php-apache-d4cf67d68-2qllw,可以看到正在运行了
AWS EKS Horizontal Pod Autoscaler(HPA)

注意:Cluster Autoscaler 不是本篇要讲的内容,只是沿用之前的环境测试时,刚好资源不足触发了 node 扩容

3. 创建 Horizontal Pod Autoscaler

Horizontal Pod Autoscaler(HPA)是通过 k8s api 资源实现,也就是说 HPA 也是一个 K8s 对象。

下面,我们创建测试应用的 HPA 对象

运行以下语句创建 HPA

kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

AWS EKS Horizontal Pod Autoscaler(HPA)
说明:

  1. 命令创建了一个叫“php-apache”的 HPA,与 deployment 的名称相同
  2. 我们为 deployment “php-apache”创建了 HPA,replicas 变动范围是最小 1,最大 10。目标 CPU 利用率(utilization)为 50%。上面我们设定 CPU request 值为 200m,所以转发为目标平均 CPU 值为 100m
  3. 命令只能运行一次,重复运行会报“AlreadyExists”错误
Error from server (AlreadyExists): horizontalpodautoscalers.autoscaling "php-apache" already exists

查看 HPA “php-apache”
AWS EKS Horizontal Pod Autoscaler(HPA)

4. 测试 Horizontal Pod Autoscaler

我们可以运行 top 命令,查看当前 pod 的负载情况

kubectl top pod php-apache-d4cf67d68-2qllw

AWS EKS Horizontal Pod Autoscaler(HPA)
说明:目前消耗 1m(0.001 个 CPU)CPU,9Mi 内存

增加 CPU 负载

我们在新的 terminal 窗口中运行下列命令,让 php-apache 的 pod 过载

kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"

说明:这里利用 busybox 镜像临时生成一个 pod,用 while 循环不停的访问 php-apache 的 service,而 php-apache 中的 k8s.gcr.io/hpa-example 镜像已经配置了进行消耗 CPU 的计算网页,所以 php-apache pod 的 CPU 负载会很快增长

AWS EKS Horizontal Pod Autoscaler(HPA)

再用 top 查看 pod,可见 CPU 消耗增长很快
AWS EKS Horizontal Pod Autoscaler(HPA)

查看 HPA,可以看到 REPLICAS 已变成 7,目前平均 CPU 为 53%
AWS EKS Horizontal Pod Autoscaler(HPA)

过一会儿再次查看 HPA,可以看到 REPLICAS 已变成 8,平均 CPU 在 50%以下,scale up 稳定在 8 个 pod
AWS EKS Horizontal Pod Autoscaler(HPA)

AWS EKS Horizontal Pod Autoscaler(HPA)

我们再随便查看 3 个 pod 的 CPU 负载情况,虽然有的大于目标值 100m,但 8 个 pod 平均值会低于 100m
AWS EKS Horizontal Pod Autoscaler(HPA)

降低 CPU 负载

在刚才运行增加负载的窗口运行\<Ctrl\> + C,终止命令
AWS EKS Horizontal Pod Autoscaler(HPA)

回到原来的窗口查看 HPA,多次执行可以看到平均 CPU 负载已经降到 0 了,但 REPLICAS 还是 8 个,不会立即降低
AWS EKS Horizontal Pod Autoscaler(HPA)

差不多过了 4,5 分钟,REPLICAS 最终变为 1
AWS EKS Horizontal Pod Autoscaler(HPA)

总结


相对于 cluster autoscaler,HPA 实现更简单,在部署 metric server 或者其它第三方可以提供 metric 的软件后,我们就可以通过命令对 deployment 等创建 HPA 对象。

本文中利用 kubectl autoscale 直接创建 HPA 对象,当然我们也可以用熟悉的 yaml 文件的方式创建 HPA 对象。

资源下载


AWS 官网 Horizontal Pod Autoscaler
https://docs.aws.amazon.com/eks/latest/userguide/horizontal-pod-autoscaler.html

Kubernetes 官网 Horizontal Pod Autoscaler
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

后记


本文在测试的时候触发了 Cluster Autoscaler,最终增加了 2 node。大家在做实验的时候,如果没有部署 Cluster Autoscaler,

则可以先把之前实验部署的其它 deployment 先删除掉,或者再增加一个新的 nodegroup,防止扩容的 Pod 一直处于 pending 状态,影响实验效果。


::: hljs-center

喜欢请点赞,禁止转载,转发请标明出处
关注 B 站 UP 主“我是手拉面” 观看更多视频
微信公众号“全是 AWS 干货”

:::

:::