一文读懂HPA弹性扩展自定义指标和缩放策略

目录

❤️ 摘要: 随着业务需求的多样化发展,HPA单纯依赖 CPU 和内存来控制扩缩容已经无法满足应用场景需求。因此,Kubernetes 引入了 自定义指标(Custom Metrics)多指标(Multiple Metrics) 支持,以便开发者能够更灵活地定义扩缩容策略。通过这些机制,HPA 可以根据业务相关的指标(如请求数、队列长度等)来动态扩缩容。本文将详细介绍 HPA 的自定义指标、基于多指标的 HPA 配置,以及扩缩容行为的概念,并通过实验展示如何使用这些机制来优化 Kubernetes 应用的弹性扩展。


💯 本文关联以往文章:


1 概念


1.1 什么是HPA

如果想更深入了解HPA弹性扩展的原理, 请先看《一文读懂HPA弹性扩展以及实践攻略》

Horizontal Pod Autoscaler (HPA) 是 Kubernetes 的一项重要功能,允许用户根据 Pod 的 CPU、内存利用率,或者其他资源使用情况,自动扩展或缩减 Pod 副本数。这使得应用在高负载下可以自动扩展来增加处理能力,而在低负载时则可以缩减以节省资源。

Horizontal Pod Autoscaler (HPA) 是 Kubernetes autoscaling API 组中的 API 资源。Kubernetes v1.23.0版本后autoscaling/v2 API 版本转为稳定版本,其中包括对自定义指标、基于多指标方式、扩缩行为策略的支持。

1.2 HPA 的自定义指标(Custom Metrics)与扩展

传统的 HPA 使用的主要是 CPU 和内存 这两种资源利用率作为指标,但这些资源指标无法完全代表所有业务场景的需求。为此,Kubernetes 引入了 自定义指标多指标 的支持。通过自定义指标,HPA 允许用户根据业务相关的指标(例如请求数、队列长度、数据库连接数等)来定义扩缩容策略。这些指标往往来自于应用的性能监控或外部监控系统(如 Prometheus)。

典型场景

  • 按照 Web 应用的 每秒请求数(QPS) 进行扩缩容。
  • 根据消息队列中的 未处理消息数 扩容消费实例。

如何实现自定义指标?

为了支持自定义指标,可以使用 Prometheus Adapter 或其他监控系统来将 Prometheus 中的监控数据暴露为 Kubernetes 自定义指标, HPA 配置中引用这些自定义指标,触发扩缩容策略的执行。


1.3 基于多指标的 HPA

在许多场景中,应用的负载不仅依赖单一的资源或指标。Kubernetes 的 HPA 支持基于 多指标(Multiple Metrics) 的扩缩容。你可以为 HPA 配置多个指标,HPA 将根据所有配置的指标来决定是否进行扩缩容。

1.3.1 工作原理

  • HPA 控制器会对每个指标进行独立的评估和计算。具体来说,HPA 会分别计算每个指标所推荐的扩缩容副本数(desiredReplicas)。
  • 例如,如果你同时监控 CPU 和内存,HPA 会分别根据这两个指标计算出它们各自推荐的副本数量。假设 CPU 建议扩展到 8 个副本,而内存建议扩展到 5 个副本。
  • 当多个指标计算得出的扩缩容建议不同,HPA 会选择所有建议中的 最大值 来调整副本数量。这个策略保证了即使某个资源(如 CPU 或内存)出现瓶颈,应用也能够及时扩容,以应对潜在的负载压力。
  • 同时,扩容的副本数不会超过用户配置的最大副本数限制(maxReplicas)。

1.3.2 例子:基于 CPU、内存和 QPS 的 HPA 配置

你可以配置 HPA 同时根据 CPU、内存和 QPS 进行扩缩容。当任一指标超出阈值时,HPA 会触发扩容;当所有指标都低于阈值时,HPA 会触发缩容。

示例 YAML 配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: multi-metric-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 70
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: 100

❔说明:

  • CPU 和内存:配置了 CPU 和内存的目标利用率,当任一指标超过设定的目标时如70%,将触发扩容。
  • QPS 指标:使用自定义指标 requests_per_second 监控每秒的请求数,如果 QPS 超过 100,HPA 也会触发扩容。

1.4 HPA 的扩缩容行为(Behavior)

Kubernetes 中的 HPA 除了监控资源利用率,还可以通过 Behavior 配置来控制扩缩容的行为,包括:

  • 扩稳定性窗口(Stabilization Window):用于避免负载短期内上升引发的频繁扩容。
  • 缩容的延迟(Downscale Delay):缩容时的最小等待时间,避免短期内负载下降时立即缩容。
  • 控制缩放速率: 在扩缩容过程,可以按数量和比例进行副本数调整并周期性监测执行情况。

1.4.1 扩缩容行为配置示例:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app
  minReplicas: 2
  maxReplicas: 15
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60  # 等待 60 秒再进行扩容
      policies:
      - type: Percent
        value: 100  # 每次扩容最多增加 100% 的副本数
        periodSeconds: 30  # 每 30 秒检查一次扩容
    scaleDown:
      stabilizationWindowSeconds: 300  # 缩容的稳定窗口为 300 秒
      policies:
      - type: Percent
        value: 50  # 每次缩容最多减少 50% 的副本数
        periodSeconds: 60  # 每 60 秒检查一次缩容

❔ 参数说明:

  • scaleUp:每次扩容最多增加 100% 的副本数量,并有 60 秒的稳定性窗口,防止过快扩容。
  • scaleDown:缩容时有 5 分钟的延迟,每次缩容最多减少 50% 的副本数量,避免因短暂的负载下降而过早缩容。

1.4.2 指定多个策略(policies)

behavior 字段下,可以为扩容或缩容指定多个 策略(policies)。每个策略都定义了如何在一定时间内调整 Pod 副本数量。

  • Pod 数量策略:以固定数量的 Pod 来扩容或缩容。例如,配置每分钟最多减少 4 个 Pod。
  • 百分比策略:以当前 Pod 副本的百分比进行扩缩容(都会向上取整)。例如,配置每分钟最多减少 10% 的副本数,即扩缩容7.2个pod,都会向上取整,就是8个。

当多个策略被指定时,默认选择 允许最大变动的策略。比如,在以下配置中:

behavior:
  scaleDown:
    policies:
    - type: Pods
      value: 4
      periodSeconds: 60
    - type: Percent
      value: 10
      periodSeconds: 60
    selectPolicy: Max

❔ 参数说明:

  • 第一个策略表示在 60 秒内最多缩容 4 个 Pod。
  • 第二个策略表示在 60 秒内最多缩容当前副本数的 10%。
  • selectPolicy** 字段**可以控制选择哪种策略:
    • Max:选择允许副本数变动最大的策略(默认值)。
    • Min:选择允许副本数变动最小的策略。
    • Disabled:完全禁用扩容或缩容。

⚠️ 注意:periodSeconds 设置的最大值为 1800(半小时)。


2 实验:使用自定义和多指标配置 HPA

2.1 实验目的:

通过自定义指标和多指标配置,结合扩缩容行为,观察 HPA 在不同负载下的扩缩容反应,并有效减少 Thrashing 现象。

2.2 实验环境准备:

  • Kubernetes 集群
  • 已安装 Prometheus 和 Prometheus Adapter
  • 一个 Web 应用 Deployment(如 Nginx)

2.3 部署 Web 应用

创建一个简单的 Deployment,限制 CPU 和内存:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  replicas: 1
  selector:
    matchLabels:
      run: php-apache
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: harbor.zx/hcie/hpa-example
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"     # CPU 请求值
            memory: "128Mi" # 设置内存请求值
          limits:
            cpu: "200m"     # CPU 限制值
            memory: "256Mi" # 设置内存限制值
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache


创建Deployment

kubectl apply -f php-apache-deployment

查看deployment详细信息

[root@k8s-master1 hcie]# kubectl describe deploy php-apache
Name:                   php-apache
Namespace:              default
CreationTimestamp:      Mon, 23 Sep 2024 12:04:36 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               run=php-apache
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=php-apache
  Containers:
   php-apache:
    Image:      harbor.zx/hcie/hpa-example
    Port:       80/TCP
    Host Port:  0/TCP
    Limits:
      cpu:     200m
      memory:  256Mi
    Requests:
      cpu:        100m
      memory:     128Mi


2.4 配置 HPA 使用多指标和行为配置

编辑 HPA YAML,使用多指标(CPU、内存和 QPS)并配置扩缩容行为:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 50
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: 100
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 100
        periodSeconds: 30
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60

创建HPA

 kubectl apply -f  php-apache-hpa.yaml

查看hpa详细信息

Name:                                                     php-apache-hpa
Namespace:                                                default
Labels:                                                   <none>
Annotations:                                              <none>
CreationTimestamp:                                        Sat, 21 Sep 2024 23:20:13 +0800
Reference:                                                Deployment/php-apache
Metrics:                                                  ( current / target )
  resource cpu on pods  (as a percentage of request):     1% (1m) / 50%
  resource memory on pods  (as a percentage of request):  7% (9715712) / 50%
  "requests_per_second" on pods:                          0 / 100
Min replicas:                                             2
Max replicas:                                             10
Behavior:
  Scale Up:
    Stabilization Window: 60 seconds
    Select Policy: Max
    Policies:
      - Type: Percent  Value: 100  Period: 30 seconds
  Scale Down:
    Stabilization Window: 300 seconds
    Select Policy: Max
    Policies:
      - Type: Percent  Value: 50  Period: 60 seconds

2.5 生成负载测试

使用 kubectl run 创建 BusyBox 容器,并生成负载:

kubectl run -i --tty load-generator --image=harbor.zx/hcie/busybox:1.29-2 /bin/sh


生成负载

while sleep 0.01; do wget -q -O- http://php-apache; done

2.6 观察 HPA 行为

使用以下命令观察 HPA 的扩缩容情况:

kubectl get hpa nginx-hpa --watch

观察 Pod 副本数量变化:

[root@k8s-master1 ~]# kubectl get hpa php-apache-hpa --watch
NAME             REFERENCE               TARGETS                       MINPODS   MAXPODS   REPLICAS   AGE
php-apache-hpa   Deployment/php-apache   40%/50%, 8%/50% + 1 more...   2         10        2          2m
php-apache-hpa   Deployment/php-apache   102%/50%, 9%/50% + 1 more...   2         10        2          2m
php-apache-hpa   Deployment/php-apache   105%/50%, 9%/50% + 1 more...   2         10        2          2m
php-apache-hpa   Deployment/php-apache   110%/50%, 9%/50% + 1 more...   2         10        2          2m
php-apache-hpa   Deployment/php-apache   102%/50%, 9%/50% + 1 more...   2         10        2          3m
php-apache-hpa   Deployment/php-apache   106%/50%, 9%/50% + 1 more...   2         10        4          3m
php-apache-hpa   Deployment/php-apache   82%/50%, 9%/50% + 1 more...    2         10        4          3m
php-apache-hpa   Deployment/php-apache   104%/50%, 9%/50% + 1 more...   2         10        4          3m
php-apache-hpa   Deployment/php-apache   106%/50%, 9%/50% + 1 more...   2         10        4          3m
php-apache-hpa   Deployment/php-apache   105%/50%, 9%/50% + 1 more...   2         10        4          4m
php-apache-hpa   Deployment/php-apache   106%/50%, 9%/50% + 1 more...   2         10        5          5m
php-apache-hpa   Deployment/php-apache   94%/50%, 9%/50% + 1 more...    2         10        8          6m
...
php-apache-hpa   Deployment/php-apache   26%/50%, 9%/50% + 1 more...   2         10        4          11m
php-apache-hpa   Deployment/php-apache   22%/50%, 9%/50% + 1 more...   2         10        4          12m
php-apache-hpa   Deployment/php-apache   20%/50%, 9%/50% + 1 more...   2         10        2          13m
php-apache-hpa   Deployment/php-apache   10%/50%, 9%/50% + 1 more...   2         10        2          13m


说明:

  • hpa检查三项指标,当cpu负载先达到阈值, 触发扩容延迟1分钟开始执行,并且每次最多扩容100%的副本数;
  • 当cpu负载下降到指标阈值时, 缩容行为延迟5分钟执行,并且每次缩容最多是当前50%的副本数。

3 总结

通过本文,我们深入探讨了 Kubernetes HPA 的自定义指标、多指标配置以及扩缩容行为策略。HPA 不再局限于简单的 CPU 和内存利用率,而是能够通过自定义指标和扩展配置更加灵活地处理复杂的业务场景。实验展示了如何使用自定义和多指标进行 HPA 配置,以及如何通过 Behavior 配置减少 Thrashing 现象。 那什么是Thrashing现象呢,预告下文:《解读HPA的 thrashing(抖动)问题》。

4 参考资料

[1] HorizontalPodAutoscalerSpec

[2]Horizontal Pod Autoscaling

[3]HorizontalPodAutoscaler Walkthrough

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐