HPA 控制器

简介

kubernetes支持通过使用控制器来实现自动动态扩展pod的数量;支持的动态控制器类型有:

  1. HPA 控制器: 基于 pod 资源利用率, 横向(水平)自动调整 pod 的数据
  2. VPA 控制器: 基于 pod 资源利用率, 调整对单个 pod 的最大资源限制
  3. 集群伸缩控制器(Cluster Autoscale, CA): 基于集群中 node 的资源使用情况, 动态伸缩 node 节点数量;(目前只有公有云环境以及kubernetes是运行在OpenStack集群上的环境支持)
    PS:
       1. 对于同一个pod, HPA 和 VPA 不能同时使用.
       2. 配置了 VPA 的 POD,在达到触发条件后,VPA 控制器可能会将 pod 调度到其它 node 上(node 资源利用率低), pod 会重启影响业务。

目前,kubernetes 官方已经内置了 HPA 控制器, 而 VPA 需要额外部署 autoscaler 来实现;

K8S 支持以下几种方法进行扩缩容:

  • 手动扩缩容

    • 服务的 yaml 清单进行手动扩缩容
    • 使用 scale 命令扩缩容
      # 格式: kubectl scale 控制器类型 控制器名称 --replicas=N [-n NAMESPACE]
      kubectl scale deployment steam-nginx-deployment --replicas=3 -n dev-41
  • 自动扩缩容

    • 使用 HPA(水平扩缩容)VPA(垂直扩缩容,针对单个pod的资源使用率)CA(cluster autoscale,云服务商提供,扩缩容node节点) 控制器进行自动扩缩容
    • 使用 autoscale 命令进行自动扩缩容
      # 格式: kubectl autoscale 控制器类型 控制器名称 --min=N --max=N < --cpu-percent=N > [-n NAMESPACE]
      kubectl autoscale deployment test-nginx --max=5 --min=2 --cpu-percent=80 -n dev-41

HPA 控制器

K8S 从1.1版本开始新增了名为 HPA(Horizontal Pod Autoscaler)的控制器,用于实现基于 pod 资源(CPU/Memory等)利用率对Pod进行横向(水平)方向自动扩缩容功能; Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。

早期的版本支持根据 Heapster 组件实现对CPU利用率作为触发条件;从K8S 1.11 版本以后支持使用 Metrices Server 进行数据采集,将采集的数据通过API(Aggregated API, 汇总Api)聚合汇总, 例如 metrics.k8s.io、custom.metrics.k8s.io、external.metrics.k8s.io,然后再把数据提供给HPA控制器进行查询,已实现基于某个资源利用率对Pod进行扩缩容的目的。

HPA 控制器默认每隔 15s 查询 metrics

HPA 查询间隔可以通过修改 kube-controller-manager 的启动参数 --horizontal-pod-autoscaler-sync-period 来修改

HPA 原理

HPA 是通过一个控制循环(HPA Controller)来定时对应用进行动态扩缩容的,通过启动 kubernetes kube-controller-manager 服务时配置的 --horizontal-pod-autoscaler-sync-period 参数来指定(默认15秒);

HPA架构图

每个周期内,HPA Controller 通过用户定义的 hpa 规则(metrics),然后通过 aggregator 层, 请求资源度量指标 API(可能是 metrics-server 或者 custom-resource-server 服务提供)来获取相应的CPU、Memory指标数据。

这里需要了解一下 k8s 的 APIServer 扩展API的两种方式:

  1. 通过 API Aggregation聚合层将外部服务注册到APIServer的特定接口(metrics-server、custom-resource-server)
  2. 通过 CRD 方式提供服务

HPA 提供了三种指标接口,用于不同指标信息的提供:

  • 对于资源指标,将使用 metrics.k8s.io API,一般由 metrics-server 提供
  • 对于自定义指标,将使用 custom.metrics.k8s.io API。 它由其他度量指标方案厂商的“适配器(Adapter)” API 服务器提供(比如 prometheus-adapter)
  • 对于外部指标,将使用 external.metrics.k8s.io API。可能由上面的自定义指标适配器提供。

下图就是 HPA 调用以上注册的接口进行指标获取的流程图:

HPA调用接口获取数据流程图

所有的指标数据都是通过 kubelet 服务内置的 cadvisor(指标收集组件)来定时获取存储在内存中的,其本质上是通过读取 /sys/fs/cgroup 目录下应用的资源情况;

HPA 控制器根据 资源度量指标 API(可能是 metrics-server 或者 custom-resource-server 服务提供) 获取的资源信息如CPU的利用率,根据公式计算得出新的副本数,通过和用户定义的期望副本数进行比较,如果不一致,则进行扩容或缩容的流程。

网易轻舟提供的更具体的HPA架构图:

网易轻舟HPA架构图

HPA 指标数据源

从 HPA 的架构图可以看出,如果需要完整使用 HPA 的全部指标类型,那么需要提供三个接口所需的服务:

  1. metrics-server: 通过 metrics.k8s.io API 提供服务
  2. custome-metrics-server: 通过custom.metrics.k8s.io API 提供服务
  3. external-metrics-server: 通过 external.metrics.k8s.io API 提供服务

并不是一定需要三个组件,像 prometheus-adapter, 已经实现了 metrics-server 组件的接口。因此安装了 prometheus-adapter 就不需要额外安装 metrics-server

metrics-server 部署

metrics-server 详细内容请转至:https://qianchen.cc/?p=43

# 1. 下载 metrics-server,用作 HPA 的数据源, github 地址: https://github.com/kubernetes-sigs/metrics-server
# PS:
#    注意 metrics-server 兼容的 K8S 版本
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.6.3/components.yaml
mv components.yaml metrics-server-v0.6.3.yaml

# 修改镜像地址为内网仓库地址
docker pull registry.k8s.io/metrics-server/metrics-server:v0.6.3
docker tag registry.k8s.io/metrics-server/metrics-server:v0.6.3 harbor.k8s.com/baseimage/metrics-server:v0.6.3
sed -i 's@image: registry.k8s.io/metrics-server/metrics-server:v0.6.3@image: harbor.k8s.com/baseimage/metrics-server:v0.6.3@g' metrics-server-v0.6.3.yaml

kubectl apply -f metrics-server-v0.6.3.yaml

HPA 控制器 yaml 清单格式

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  # 最大扩容Pod数量
  maxReplicas: 10
  # pod 缩容最小数量
  # k8s v1.16之后才放开允许Objetct和External类型的metrics的minReplicas == 0,需要apiserver开启–feature-gates mapStringBool HPAScaleToZero=true
  minReplicas: 1
  # HPA 控制器 控制的目标
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: test-nginx
  # HPA 进行扩缩容依据的指标
  metrics:
    # 类型:ContainerResource | Resource | Pods | Object | External
    - type: Resource
      resource:
        name:
        target:
          type:
          averageValue:
          averageUtilization:
      ...
  # 定义 HPA scale 速度
  # 从 1.18 以后开始支持
  behavior:
    scaleDown:
    scaleUp:

HPA 的 metrics 分类

HPA v2版本 支持4中类型的 metrics: ContainerResource、Resource、Pods、Object、External;每种类型的 metrics 所对应的场景如下:

  • Resource支持k8s里Pod的所有系统资源(包括cpu、memory等),但是一般只会用cpu,memory因为不太敏感而且跟语言相关:大多数语言都有内存池及内置GC机制导致进程内存监控不准确。
  • Pods类型的metrics表示cpu,memory等系统资源之外且是由Pod自身提供的自定义metrics数据,比如用户可以在web服务的pod里提供一个promesheus metrics的自定义接口,里面暴露了本pod的实时QPS监控指标,这种情况下就应该在HPA里直接使用Pods类型的metrics。
  • Object类型的metrics表示监控指标不是由Pod本身的服务提供,但是可以通过k8s的其他资源Object提供metrics查询,比如ingress等,一般Object是需要汇聚关联的Deployment下的所有的pods总的指标。
  • External类型的metrics也属于自定义指标,与Pods和Object不同的是,其监控指标的来源跟k8s本身无关,metrics的数据完全取自外部的系统。

HPA 的各种类型metrics与 target type 对应关系

Metrics Type \ Target Type Utilization AverageValue Value 备注
Resource Yes Yes No
Pods No Yes No
Object No Yes Yes
External No Yes Yes

PS:

  1. Utilization: 表示 百分比
  2. AverageValue: 表示 平均值
  3. Value: 表示 当前值 与指标值直接比较

HPA 算法

在HPA控制器里,针对不同类型的metrics和不同metrics下的target 类型,都有独立的计算算法,虽然有很多细节差异,但是总的来说,计算公式可以抽象为:

 desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
 期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]

例如如果配置期望指标是100m,当前从metrics接口读取到的 metrics value 是 200m,说明最新的副本数应该是当前的 200m/100m=2.0倍, 如果当前副本数为 2,则HPA计算后的期望副本数是2*2.0=4;

而如果当前从metrics接口读取到的 metrics value是 50m,说明最新的副本数应该是 当前的 50m/100m=0.5倍,也就是最终scale的副本数将为1。

当然实际上当前的metrics value并不一定就只有一个值,如果是 Resource或者Pods类型的metrics,实际上 GetMetrics 会返回一批关联的Pods对应的metrics数据,一般需要做一个平均后再与target的metrics的做比较。

此外,为了保证结果尽量精确,metrics的计算都是浮点数计算,但是最终的副本数肯定要是整数,为了统一HPA控制器在最后,都会对计算出的浮点数副本数向上取整,也就是上面公式里最外层的ceil函数。

扩缩容threshold控制

当然上面的公式也只是纯数学模型,实际工程实现还要考虑很多现实细节问题:比如监控数据可能会有一定的误差,如果GetMetrics里读到数据不稳定就会造成算出的期望副本数不稳定,导致deployment一会扩缩1个副本,一会又扩容1副本。所以为了避免这种问题kube-controller-manager里有个HPA的专属参数 horizontal-pod-autoscaler-tolerance, 表示HPA可容忍的最小副本数变化比例,默认是0.1;
如果期望变化的副本倍数在[0.9, 1.1] 之间就直接停止计算返回。那么如果相反,某个时间点开始metrics数据大幅增长,导致最后计算的副本数变化倍数很大,是否HPA控制器会一步扩容到位呢? 事实上HPA控制器为了避免副本倍增过快还加了个约束:单次倍增的倍数不能超过2倍,而如果原副本数小于2,则可以一次性扩容到4副本,注意这里的速率是代码写死不可用配置的。(这个也是HPA controller默认的扩缩容速率控制,autoscaling/v2的HPA Behavior属性可以覆盖这里的全局默认速率)

缩容冷却机制(cooldown delay)

虽然HPA同时支持扩容和缩容,但是在生产环境上扩容一般来说重要性更高,特别是流量突增的时候,能否快速扩容决定了系统的稳定性,所以HPA的算法里对扩容的时机是没有额外限制的,只要达到扩容条件就会在reconcile里执行扩容(当前一次至少扩容到原来的1.1倍)。但是为了避免过早缩导致来回波动(thrashing ),而容影响服务稳定性甚,HPA的算法对缩容的要求比较严格,通过设置一个默认5min(可配置horizontal-pod-autoscaler-downscale-stabilization)的滑动窗口,来记录过去5分钟的期望副本数,只有连续5分钟计算出的期望副本数都比当前副本数小,才执行scale缩容操作,缩容的目标副本数取5分钟窗口的最大值。

总的来说k8s HPA算法的默认扩缩容原则是:快速扩容,谨慎缩容。

Pod的metrics数据过滤检查机制

一般情况下HPA的数据指标都来自k8s的Pod里,但是实际上每次创建deployment、对deployment做扩缩容,Pod的副本数和状态都会不断变化,这就导致HPA controller在reconcile里获取到的metrics的指标肯定会有一定的异常,比如Pod还没有Running、Pod刚刚启动还在预热期、或者Pod中间临时OOM恰逢采集时刻、或者Pod正处在删除中,这些都可能导致metrics指标缺失。如果有任何 pod 的指标缺失,HPA控制器会采取最保守的方式重新计算平均值, 在需要缩小时假设这些 pod 消耗了目标值的 100%, 在需要放大时假设这些 pod 消耗了0%目标值, 这可以在一定程度上抑制伸缩的幅度。

具体来说,HPA算法里把deployment下的所有Pod的metrics的指标数据分为三类:

  1. ready pods list, deployment下处于Running状态的Pod且HPA controller成功通过GetMetrics获取的pod metrics的列表

  2. ignore pods list, deployment下处于pending状态的Pods或者(仅对Resouce类似的cpu metrics有效)虽然pod running了但controller成功通过GetMetrics获取的pod metrics,但是pod的启动时间在配置的initial-readiness-delay和cpu-initialization-period 保护期内。

  3. missing pods list,deployment下处于running状态的pod(非pending、非failed、非deleted状态)但是HPA controller通过GetMetrics无法获取的pod metrics的列表

在计算pod的平均metrics值的时候,统一把 ignore pods的metrics设置为最小值0,如果HPA扩缩容的方向是扩容,把missing pods的metrics也设置为最小值0,如果是缩容方向则把missing pods的metrics也设置为最大值(如果是Resouce类型,最大值是Pod的request值,否则最大值就是target value)

总计:

  1. 正在关闭的 pod 或 failed pod 不会参与HPA 计算
  2. Pod 指标信息缺少时,在最后计算扩缩副本数的时候才会参与计算
  3. 使用 CPU 指标扩缩容时,未就绪(pending) 和刚就绪的 Pod 也不会参与计算
  4. 指标信息缺少的Pod,在缩容时,当成 100% 计算,在扩容时,当成 0% 计算
  5. 未就绪和刚就绪的Pod, 默认当成 0% 计算

HPA 相关的 kube-controller-manager 参数:

  • --horizontal-pod-autoscaler-sync-period: HPA控制器每隔15s(默认值)查询一次 metrics
  • --horizontal-pod-autoscaler-tolerance: HPA控制器能够容忍的数据差异(浮点数,默认为0.1),即新的指标要与当前的阀值差异在0.1及以上;比如阙值为CPU利用率50%,当前值为80%,那么80/50=1.6 > 1.1(1+0.1), 则会触发扩容,反之(小于 (1 – 0.1))会缩容。
  • --horizontal-pod-autoscaler-cpu-initialization-period: 初始化延迟周期,在此时间内的pod的CPU资源指标不生效,默认5分钟
    也可在创建Pod的时通过annotation注解手动指定, 比如:spec.template.metadata.ammotation.HPAScaleUpDelay: 3m 表示早Pod创建3分钟以后开始执行HPA,单位支持ms
  • --horizontal-pod-autoscaler-downscale-stabilization: 缩容间隔周期,默认为5分钟
  • --horizontal-pod-autoscaler-initial-readiness-delay: 用于设置pod就绪时间,在此时间内的pod统统被认为未就绪,不采集指标数据,默认为30s

HPA的scale速度控制

讲解完HPA的原理及具体算法后,最后再重点介绍HPA在扩缩容的速率控制机制。在前面讲过HPA controller里默认扩缩容总原则是:快速扩容,谨慎缩容,扩容上虽然强调快,但是速度却是固定的最大于当前副本数的2倍速度,对于想设置其他倍数或者说想精确控制副本数增量的方式的需求都是不行的;缩容上则仅仅只是靠设置一个集群全局的窗口时间,窗口期过后也就失去控制能力。

为了能更精准灵活地控制HPA的autoscale速度,从k8s v1.18(依赖HPA autoscaling/v2beta2)开始HPA的spec里新增了behavior结构扩展了HPA的scale速度控制策略,该结构支持每个HPA实例独立配置扩缩容的速度,而且还可以单独配置扩容scaleUp和缩容scaleDown使用不同的策略。

在扩容策略ScalingRules里,有个StabilizationWindowSeconds用来记录最近计算的期望副本数,效果跟上面缩容的cooldown delay机制一样,每次都会选择窗口里所有推荐值的最大值,保证结果的稳定性。

Policies是一个HPAScalingPolicy数组,每个HPAScalingPolicy才是真正控制速度的部分:扩缩容计算周期和周期内扩缩容变化的最大幅度,PeriodSeconds周期单位是秒,Percent是设置副本数每次变化的百分比,扩容后副本数是:(1+PercentValue%)* currentReplicas,缩容后副本数是:(1-PercentValue%)* currentReplicas; Pods则是设置每次副本数变化的绝对值。

次外,每个方向还可以设置多个策略,多个策略会同时计算最终副本数,最后结果则是通过SelectPolicy:Max/Min/Disabled做聚合,注意在缩容时Max会选择计算副本数最小的那个,Min会选择计算的副本数最大的那个,Disabled表示禁止这个方向的扩缩容

HPA behavior 默认配置

HPA的Behavior如果不设置,k8s会自动设置扩缩容的默认配置, 具体内容如下:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  # 定义 HPA scale 速度
  # 从 1.18 以后开始支持
  behavior:
    # 缩容配置
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 100
          periodSeconds: 15
    # 扩容配置
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100
          periodSeconds: 15
        - type: Pods
          value: 4
          periodSeconds: 15
      selectPolicy: Max

默认配置里分别定义了扩容和缩容的速率策略,缩容按照百分比,每15秒最多减少currentReplicas*100%个副本(但最终不可小于minReplicas),且缩容后的最终副本不得低于过去300s内计算的历史副本数的最大值;扩容则采用快速扩容,不考虑历史计算值(窗口时间为0),每15秒副本翻倍或者每15秒新增4个副本(取最大值),即:max(2*currentReplicas,4)。这个默认Behavior的默认配置是否有点似曾相似的感觉,没错它跟HPA没有Behavior时的默认快速扩容,缩容的策略是完全一致的。

不同扩缩容速率需求场景下的behavior用法举例

场景1:扩容越快越好

如果业务希望能尽快的扩容,可以配置大的 percent值,可以按照如下配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  behavior:
    scaleUp:
      policies:
      - type: Percent
        value: 900
        periodSeconds: 60

假如 deployment的副本数最开始是1,那么每隔60s的的极限扩容副本数的变化如下:

1 -> 10 -> 100 -> 1000

也就是每个扩容period都是(1+900%)=10倍的速度,不过最大副本数依然不可用超过HPA 的 maxReplicas上界,缩容则使用默认行为。当然Percent类型可能对资源消耗波动特别大,如果希望资源消耗可控,可以按绝对副本数来Pods类型来配置。

场景 2: 扩容越快越好但要逐步缩容

当业务希望能尽快的扩容,但是缩容需要缓慢一些时,可以使用如下配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  behavior:
    scaleUp:
      policies:
      - type: Percent
        value: 900
        periodSeconds: 60
    scaleDown:
      policies:
      - type: Pods
        value: 1
        periodSeconds: 600

假如 pod 最开始数量为 1,那么扩容路径如下:

1 -> 10 -> 100 -> 1000

同时,缩容路径如下 (每 10 分钟缩容一次,每次减少一个 pod):

1000 -> 1000 -> 1000 -> … (another 7 min) -> 999 (最小不低于minReplicas)

场景 3: 逐步扩容、正常的缩容

当希望缓慢的扩容、正常的缩容,可以使用如下配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  behavior:
    scaleUp:
      policies:
      - type: Pods
        value: 1
        periodSeconds: 600

假如 pod 最开始数量为 1,那么扩容路径如下:

1 -> 2 -> 3 -> 4

场景 4: 正常扩容、不要缩容

如果希望能正常的扩容,但是不要自动缩容,可以使用如下配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  behavior:
    scaleDown:
      policies:
      - type: Percent 或 Pods
        value: 0
        periodSeconds: 600

把缩容的百分比或者pod 都置为 0,那么就永远不会缩容。
或者直接设置 selectPolicy: Disabled。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  behavior:
    scaleDown:
      selectPolicy: Disabled
延后缩容

一般在流量激增时,都希望快速扩容应对,那么发现流量降低是否应该立马缩容呢,加入只是临时的流量降低呢,这样就可能导致短时间反复的扩缩容,为了避免这种情况,缩容时应该更谨慎些,可以使用延迟缩容机制:delaySeconds(这个跟 kube-controller-managerhorizontal-pod-autoscaler-downscale-stabilization 非常类似,但是这个参数是全局的,如果HPA有配置优先使用delaySeconds),配置如下:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  ...
  behavior:
    scaleDown:
      policies:
      - type: Pods
        value: 5
        periodSeconds: 600

那么,每次缩容最多减少 5 个 pod,同时每次缩容,至少要往前看 600s 窗口期的所有推荐值,每次都从窗口期中选择最大的值。这样,除非连续600s的推荐值都比之前的最大副本数小,才开始缩容

通过 HPA 实现自动扩缩容示例

1. 创建测试 pod


vim test-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: test-nginx
        image: nginx
        ports:
        - containerPort: 80
kubectl apply -f test-nginx.yaml

kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
test-nginx-7fd96f5f44-7hhcc   1/1     Running   0          9m12s

2. 创建 HPA

# hpa 规则:当 test-nginx pod CPU使用率大于 10%,开始进行扩容
vim hpa-demo.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-demo
  namespace: default
spec:
  maxReplicas: 5
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: test-nginx
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 10
kubectl apply -f hpa-demo.yaml

# 注意,此时会报错,错误原因是 test-nginx 没有做 资源限制,因为 HPA默认是通过 `实际的利用率/request` 作为利用率的数值
kubectl describe hpa hpa-demo
Warning: autoscaling/v2beta2 HorizontalPodAutoscaler is deprecated in v1.23+, unavailable in v1.26+; use autoscaling/v2 HorizontalPodAutoscaler
Name:                                                  hpa-demo
Namespace:                                             default
Labels:                                                
Annotations:                                           
CreationTimestamp:                                     Tue, 25 Jul 2023 17:03:49 +0800
Reference:                                             Deployment/test-nginx
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):   / 10%
Min replicas:                                          1
Max replicas:                                          5
Deployment pods:                                       1 current / 0 desired
Conditions:
  Type           Status  Reason                   Message
  ----           ------  ------                   -------
  AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scale
  ScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: failed to get cpu utilization: missing request for cpu
Events:
  Type     Reason                        Age   From                       Message
  ----     ------                        ----  ----                       -------
  Warning  FailedGetResourceMetric       5s    horizontal-pod-autoscaler  failed to get cpu utilization: missing request for cpu
  Warning  FailedComputeMetricsReplicas  5s    horizontal-pod-autoscaler  invalid metrics (1 invalid out of 1), first error is: failed to get cpu utilization: missing request for cpu

3. 修改 test-nginx 添加 资源限制

vim test-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: test-nginx
        image: nginx
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 50m
kubectl apply -f test-nginx.yaml

# 重新配置 HPA
kubectl delete -f hpa-demo.yaml
kubectl apply -f hpa-demo.yaml

kubectl get hpa
NAME       REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
hpa-demo   Deployment/test-nginx   0%/10%    1         5         1          13s

4. 压测

# 查找 test-nginx pod 的 ID
kubectl get pod -o wide

# 进入pod
kubectl exec -it test-nginx-649694479c-vfd8z -- bash

# 新建一个 SSH 终端,监控 pod
kubectl get pod -l app=nginx --watch

# 在 pod 容器内 压测
while true; do curl -sq 127.0.0.1 >> /dev/null; done

kubectl get pod -l app=nginx –watch 命令 输出:
此时可以看出 HPA 在自动扩容

NAME                          READY   STATUS    RESTARTS   AGE
test-nginx-649694479c-vfd8z   1/1     Running   0          6m1s
test-nginx-649694479c-l428t   0/1     Pending   0          0s
test-nginx-649694479c-t4npb   0/1     Pending   0          0s
test-nginx-649694479c-l428t   0/1     Pending   0          0s
test-nginx-649694479c-wmb67   0/1     Pending   0          0s
test-nginx-649694479c-l428t   0/1     ContainerCreating   0          0s
test-nginx-649694479c-t4npb   0/1     ContainerCreating   0          0s
test-nginx-649694479c-wmb67   0/1     ContainerCreating   0          0s
test-nginx-649694479c-bwb8v   0/1     ContainerCreating   0          0s
test-nginx-649694479c-l428t   1/1     Running             0          20s
test-nginx-649694479c-t4npb   1/1     Running             0          31s
test-nginx-649694479c-bwb8v   1/1     Running             0          19s
test-nginx-649694479c-wmb67   1/1     Running             0          36s
kubectl describe hpa hpa-demo
Warning: autoscaling/v2beta2 HorizontalPodAutoscaler is deprecated in v1.23+, unavailable in v1.26+; use autoscaling/v2 HorizontalPodAutoscaler
Name:                                                  hpa-demo
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Tue, 25 Jul 2023 17:13:34 +0800
Reference:                                             Deployment/test-nginx
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  393% (196m) / 10%
Min replicas:                                          1
Max replicas:                                          5
Deployment pods:                                       5 current / 5 desired
Conditions:
  Type            Status  Reason               Message
  ----            ------  ------               -------
  AbleToScale     True    ScaleDownStabilized  recent recommendations were higher than current one, applying the highest recent recommendation
  ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  True    TooManyReplicas      the desired replica count is more than the maximum replica count
Events:
  Type    Reason             Age    From                       Message
  ----    ------             ----   ----                       -------
  Normal  SuccessfulRescale  2m34s  horizontal-pod-autoscaler  New size: 4; reason: cpu resource utilization (percentage of request) above target
  Normal  SuccessfulRescale  2m19s  horizontal-pod-autoscaler  New size: 5; reason: cpu resource utilization (percentage of request) above target

kubectl get pod
NAME                          READY   STATUS    RESTARTS   AGE
test-nginx-649694479c-bwb8v   1/1     Running   0          2m30s
test-nginx-649694479c-l428t   1/1     Running   0          2m45s
test-nginx-649694479c-t4npb   1/1     Running   0          2m45s
test-nginx-649694479c-vfd8z   1/1     Running   0          10m
test-nginx-649694479c-wmb67   1/1     Running   0          2m45s
上一篇
下一篇