指标类型

Master 的 kube-controller-manager 服务持续检测目标 Pod 的某种性能指标,以计算是否需要调整 Pod 副本数量。Kubernetes 目前支持的指标类型如下:

  • Pod 资源指标:Pod 级别的性能指标,通常是一个比率,例如 CPU 使用率。
  • Container 资源指标:Container 级别的性能指标,该指标特性从 Kubernetes v1.20 版本开始引入,需要通过开启 HPAContainerMetrics 特性门控进行启用,到 v1.27 版本时,该特性达到 Beta 阶段默认开启,可以基于某个容器的性能指标进行自动扩缩容。到 v1.30 版本为 stable 正式版本默认启动。
  • Pod 自定义指标:Pod 级别的性能指标,通常是一个数值,例如接受的请求数量。
  • Object 自定义指标或外部自定义指标:通常是一个数值,需要容器应用以某种方式提供,例如通过 HTTP URL "/metrics"提供,或者使用外部服务提供的指标采集 URL。

Kubernetes HPA 当前有以下两个版本:

  • autoscaling/v1 版本:仅支持基于 CPU 使用率指标的自动扩缩容。
  • autoscaling/v2 版本:支持基于内存使用率指标、自定义指标及外部指标的自动扩缩容并且进一步扩展以支持多指标缩放。在定义了多个指标时,HPA 会根据每个指标进行计算,其中缩放幅度最大的指标会被采纳。

扩缩容算法

自动扩缩容控制器会经过算法计算目标 Pod 副本数量,与当前运行的 Pod 副本数量进行对比,决定是否需要进行扩容:当前 Pod 副本数量 ×(当前指标值/期望的指标值),并将结果向上取整。

以 CPU 请求数量为例,如果用户设置的期望指标为 100m:

  • 当前实际使用的指标值为 200m,则计算得到的 Pod 副本数量应为 2 个(200/100=2)。
  • 如果当前实际使用的指标为 50m,计算结果为 0.5,则向上取整为 1 个。

当计算结果与 1 非常接近时,可以设置一个容忍度让系统不做扩缩容操作。通过 kube-controller-manager 服务的启动参数--horizontal-pod-autoscaler-tolerance进行设置,默认值为 0.1(10%),表示基于算法得到的结果在 [-10%, +10%] 区间内,即在 [0.9, 1.1] 区间内,控制器都不会执行扩缩容操作。

也可以将期望指标值desiredMetricValue设置为指标的平均值类型,例如targetAverageValuetargetAverageUtilization,那么此时当前所有 Pod 副本指标值的总和除以 Pod 副本数量得到平均值做为currentMetricValue指标。

在计算“当前指标值/期望指标值”(currentMetricValue/desiredMetricValue)时,将不包含以下异常 Pod:

  • Pod 正在被删除(设置了删除时间戳)。
  • 无法获得 Pod 的当前指标值。
  • 如果指标类型是 CPU 使用率,则正在启动但还未处于 Ready 状态的 Pod。可以通过 kube-controller-manager 服务的启动参数--horizontal-pod-autoscaler-initial-readiness-delay设置首次探测 Pod 是否 Ready 的延时时间,默认值为 30s。另一个启动参数--horizontal-pod-autoscaler-cpu-initialization-period用于设置首次采集 Pod 的 CPU 使用率的延时时间,默认值为 5min。

HorizontalPodAutoscaler(HPA)控制器有两个命令行选项会影响 Pod 启动期间如何收集其 CPU 指标:

  1. <font style="background-color:rgb(248, 249, 250);">--horizontal-pod-autoscaler-cpu-initialization-period</font>(默认:5 分钟)

此命令行选项所定义的是 Pod 启动后的一个时间窗口,在此期间内其 CPU 使用率被忽略,除非:

- <font style="color:rgb(33, 37, 41);">Pod 处于</font><font style="color:rgb(33, 37, 41);"> </font>`<font style="background-color:rgb(248, 249, 250);">Ready</font>`<font style="color:rgb(33, 37, 41);"> </font><font style="color:rgb(33, 37, 41);">状态</font>**<font style="color:rgb(33, 37, 41);">且</font>**
- <font style="color:rgb(33, 37, 41);">指标样本完全是在它处于</font><font style="color:rgb(33, 37, 41);"> </font>`<font style="background-color:rgb(248, 249, 250);">Ready</font>`<font style="color:rgb(33, 37, 41);"> </font><font style="color:rgb(33, 37, 41);">状态期间采集的。</font>

此命令行选项有助于排除初始化 Pod 中的误导性高 CPU 使用率 (例如,Java 应用程序预热)对 HPA 扩缩决策的影响。

  1. <font style="background-color:rgb(248, 249, 250);">--horizontal-pod-autoscaler-initial-readiness-delay</font>(默认:30 秒)

这定义了一个短暂的延迟期,在 Pod 启动后,HPA 控制器将当前为 <font style="background-color:rgb(248, 249, 250);">Unready</font> 的 Pod 视为仍在初始化中,即使它们之前曾短暂转变为**** **<font style="background-color:rgb(248, 249, 250);">Ready</font>**

其设计目的是:

- <font style="color:rgb(33, 37, 41);">避免包含在启动期间快速在</font><font style="color:rgb(33, 37, 41);"> </font>`<font style="background-color:rgb(248, 249, 250);">Ready</font>`<font style="color:rgb(33, 37, 41);"> </font><font style="color:rgb(33, 37, 41);">和</font><font style="color:rgb(33, 37, 41);"> </font>`<font style="background-color:rgb(248, 249, 250);">Unready</font>`<font style="color:rgb(33, 37, 41);"> </font><font style="color:rgb(33, 37, 41);">之间波动的 Pod。</font>
- <font style="color:rgb(33, 37, 41);">确保在 HPA 认为它们的指标有效之前,初始就绪信号的稳定性。</font>

HPA 对象的配置

基于 autoscaling/v1 版本

基于 autoscaling/v1 版本的 HorizontalPodAutoscaler 配置:

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:                     # 对象目标,Deployment、ReplicationController、StatefulSet
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1                      # Pod副本数的最小值 
  maxReplicas: 10                     # Pod副本数的最大值
  targetCPUUtilizationPercentage: 50  # 期望每个Pod的CPU使用率都为50%。

其中 targetCPUUtilizationPercentage 的期望值,根据 Pod 设置的 CPU Request 值计算。例如设置为 200m(0.2 核),那么系统将维持 Pod 的实际 CPU 使用值为 100m(0.1 核)。在 minReplicas 到 maxReplicas 范围内自动扩缩容,并维持每个 Pod 的 CPU 使用率为 50%

基于 autoscaling/v2 版本

基于 autoscaling/v2 版本的 HorizontalPodAutoscaler 配置:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:                      # 对象目标,Deployment、ReplicationController、StatefulSet
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1                       # Pod副本数的最小值
  maxReplicas: 10                      # Pod副本数的最大值
  metrics:                             # 目标指标值。
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

可以将 metrics 中的 type(指标类型)设置为以下几种:

  • Resource:指的是当前伸缩对象下 Pod 的 CPU 和 Memory 指标,只支持 Utilization 和 AverageValue 类型的目标值。
    • 对于 CPU 使用率,在 target 参数中设置 averageUtilization 定义目标平均 CPU 使用率。
    • 对于内存资源,在 target 参数中设置 AverageValue 定义目标平均内存使用值。
  • ContainerResource:指的是伸缩对象 Pod 中特定容器的指标,设置方法同 Resource 一样。
  • Pods:指的是伸缩对象 Pod 的指标,数据需要由第三方适配器(Adapter)提供,只允许 AverageValue 类型的目标值。
  • Object:Kubernetes 内部对象的指标,数据需要由第三方适配器(Adapter)提供,只支持 Value 和 AverageValue 类型的目标值。
  • External:指的是 Kubernetes 外部的指标,数据需要由第三方适配器(Adapter)提供,只支持 Value 和 AverageValue 类型的目标值。

ContainerResource 示例

下面是一个类型为 ContainerResource 的 Metrics 示例:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10 
  metrics:
  - type: ContainerResource
    containerResource:
      name: cpu
      container: application
      target:
        type: Utilization
        averageUtilization: 60

其中针对 Pod 中名为“application”的容器设置了目标指标的内容,即全部容器的目标 CPU 使用率平均值为 60%,系统将根据监控到的指标值自动触发缩扩容操作。

Pods 实例

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10 
  metrics:
  - type: Pods
    Pods:
      name: packets-per-second
      target:
        type: AverageValue
        averageValue: 1k

设置 Pod 的指标名称名称为“packets-per-second”,在目标指标的平均值为 1000 时触发扩缩容操作。

Object 实例

例 1

设置指标的名称为“packets-per-second”,指标值类源于 Ingress“main-route”,将目标值(value)设置为 2000。即在 Ingress 的每秒请求数量达到 2000 个时触发扩缩容操作:

apiVersion: autoscaling/v2
  kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10 
  metrics:
  - type: Object
    object:
      metric:
        name: requests-per-second
      describeObject:
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        name: main-route
      target:
        type: Value
        value: 2k
例 2

设置指标的名称为“http_requests”,该资源对象具有标签verb=GET,在指标的平均值达到 500 时触发扩缩容操作:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10 
  metrics:
  - type: Object
    object:
      metric:
        name: 'http_requests'
        selector: 'verb=GET'
      target:
        type: AverageValue
        averageValue: 500

还可以定义多个类型的指标,系统将针对每种类型的指标都计算 Pod 副本的目标数量,以最大的值执行扩缩容。下面的示例中,配置了 3 种类型的指标,包括 Pod 的 CPU 使用率为 50%、Pod 处理的每秒数据包请求数量为 1000,以及 Ingress 后端 Pod 处理的每秒请求数量为 10000:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
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:
      name: packets-per-second
    targetAverageValue: 1k
  - type: Object
    object:
      metric:
        name: requests-per-second
      describeObject:
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        name: main-route
      target:
        type: Value
        value: 10k

External 实例

设置指标名称为“queue_messages_ready”,具有queue=worker_tasks标签,在目标指标平均值为 30 时触发自动扩缩容操作:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10 
  metrics:
  - type: External
    external:
      metric:
        name: 'queue_messages_ready'
        selector:
          matchLabels:
            queue: "worker_tasks"
      target:
        type: AverageValue
        averageValue: 30

在使用外部服务的指标时,要安装、部署能够对接到 Kubernetes HPA 模型的监控系统,并且完全了解监控系统采集这些指标的机制,这样后续的自动扩缩容操作才能完成。