基于CPU指标的容器原地垂直伸缩

AVPA(ack-advanced-vertical-pod-autoscaler)是阿里云推出的柔性资源变配组件,在基于指标的垂直伸缩能力以外,还提供了应用启动加速能力。本文主要介绍基于CPU指标的垂直伸缩能力,从使用场景、具体的使用和配置方式以及使用限制进行介绍。

背景信息

AVPA提供启动加速和基于指标的垂直伸缩能力,结合ACS柔性变配能力,可以在不中断服务的前提下进行原地的资源垂直伸缩,并且支持按Pod粒度处理,满足业务的局部负载热点产生的变配需求。

AVPA和社区VPA对比

VPA

AVPA

变配方式

滚动重建Pod。

原地热变配。

变配范围

整体同升同降。

实例独立升降。

适用负载

  • 无状态应用。

  • 有状态应用(效果有限)。

  • CronJob。

  • 无状态应用。

  • 有状态应用。

  • Job 类型应用。(avpa0.2.0版本支持)

  • 通过 selector 模式可支持任意负载管理的Pod。(avpa0.3.0版本支持)

适用场景

长期、均衡的业务负载变化。

周期性负载变化、突发的或不均衡的负载变化。

适用场景

  • 游戏业务:适用于周期性CPU负载变化,支持热升配和热降配。

  • 在线业务:针对局部负载热点,支持对热点Pod进行垂直扩缩容。

使用限制

  • 暂不支持和社区VPA/HPA同时使用。

  • 指标弹性提供针对CPU的按指标垂直伸缩,如果CPU扩容后不再符合ACS的规格要求,会被拒绝变配,如2vCpu2Gi无法继续升配至3vCpu2Gi。同时,目标变配的容器需要声明requests资源。

  • 垂直扩缩容会同时调整PodCPU RequestLimit,在ACKACK Serverless场景中,弹性可能受限于节点的资源余量情况。

  • 在 ACK 和 ACK Serverless 场景下,组件 ack-virtual-node版本至少为v2.14.0

  • 当前AVPA不会生产画像,只对存量的Pod生效, 因此增量新建的Pod会使用Workload 里定义的原始规格进行创建。

说明
  • 当前柔性变配在邀测阶段,您可以提交工单申请进行试用。

  • 当前ACS产品支持对ComputeClass=general-purposeComputeQoS=defaultACS Pod CPU资源的柔性变配:

    • 最大支持原始规格的100%扩容,最小支持原始规格的50%缩容。例如,一个4vCpu8GiACS Pod扩缩容范围是2vCpu8Gi8vCpu8Gi

    • 资源变配当前存在最大16Core的上限。

操作流程

本文我们采用一个样例工作负载和一个影子工作负载来进行演示,您可以自行决定是否部署影子工作负载。其中,样例工作负载配置AVPA,影子工作负载与样例工作负载规格相同,但不配置AVPA。通过模拟真实的业务负载来进行基于CPU负载的垂直扩缩。具体流程如下:

image

示例应用通过一同创建的服务作为流量入口,包括一个模拟工具,可以通过接口触发的方式来消耗指定的CPU,如在6000秒内持续消耗500毫核(0.5核)。

操作步骤

步骤一:开启原地变配的特性门控

  1. 登录容器计算服务控制台,在左侧导航栏选择集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理组件管理

  3. 核心组件区域选择Kube API Server > 配置。在featureGates配置项中填入InPlacePodVerticalScaling=true,开启原地变配的特性门控。

    image

    说明

    配置过程中Kube API Server卡片会显示状态为操作执行中,当状态重新变为已安装时,说明原地变配的特性门控开启成功。

步骤二:安装AVPA

在左侧导航栏,选择应用 > Helm,搜索并安装ack-advanced-vertical-pod-autoscaler组件。具体操作,请参见使用Helm管理ACS应用

image

步骤三:部署应用并建立本地连接

  1. 创建应用YAML。您可以选择同步创建shadow-hello-avpa.yaml,用于后续的压测对比。

    创建hello-avpa.yaml。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-avpa
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          name: hello-avpa
      template:
        metadata:
          annotations:
            scaling.alibabacloud.com/enable-inplace-resource-resize: 'true'
          labels:
            name: hello-avpa
            vpa: enabled
        spec:
          containers:
            - image: 'registry.cn-hangzhou.aliyuncs.com/acs-demo-ns/simulation-resource-consumer:1.13'
              name: hello-avpa
              resources:
                limits:
                  cpu: '2'
                  memory: '4Gi'
                requests:
                  cpu: '2'
                  memory: '4Gi'
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: hello-avpa-svc
      namespace: default
    spec:
      ports:
        - port: 80
          protocol: TCP
          targetPort: 8080
      selector:
        name: hello-avpa
      type: ClusterIP

    (可选)创建shadow-hello-avpa.yaml。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: shadow-hello-avpa
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          name: shadow-hello-avpa
      template:
        metadata:
          annotations:
            scaling.alibabacloud.com/enable-inplace-resource-resize: 'true'
          labels:
            vpa: enabled
            name: shadow-hello-avpa
        spec:
          containers:
            - image: 'registry.cn-hangzhou.aliyuncs.com/acs-demo-ns/simulation-resource-consumer:1.13'
              name: shadow-hello-avpa
              resources:
                limits:
                  cpu: '2'
                  memory: '4Gi'
                requests:
                  cpu: '2'
                  memory: '4Gi'
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: shadow-avpa-svc
      namespace: default
    spec:
      ports:
        - port: 80
          protocol: TCP
          targetPort: 8080
      selector:
        name: shadow-hello-avpa
      type: ClusterIP
  2. 部署应用。

    kubectl apply -f hello-avpa.yaml
    kubectl apply -f shadow-hello-avpa.yaml
  3. 通过kubectl port-forward建立本地连接。

    重要

    请注意kubectl port-forward建立的端口转发不具备生产级别的可靠性、安全性和扩展性,因此仅适用于开发和调试目的,不适合在生产环境使用。更多关于Kubernetes集群内生产可用的网络方案的信息,请参见Ingress管理

    kubectl port-forward svc/hello-avpa-svc -n default 28080:80
    kubectl port-forward svc/shadow-avpa-svc -n default 28081:80

步骤四:创建AVPA配置

您可以通过创建AdvancedVerticalPodAutoscaler资源配置弹性策略。

  1. 创建avpa.yaml。

    TargetRef模式

    以下为AVPATargetRef模式的示例配置,旨在根据CPU使用率调整default命名空间下名为hello-avpaDeployment创建的Pod的资源设置。

    apiVersion: autoscaling.alibabacloud.com/v1beta1
    kind: AdvancedVerticalPodAutoscaler
    metadata:
      name: hello-avpa
      namespace: default
    spec:
      metrics:
        - containerResource:
            container: hello-avpa
            name: cpu
            target:
              averageUtilization: 30
              type: Utilization
          type: ContainerResource
          watermark: low
        - containerResource:
            container: hello-avpa
            name: cpu
            target:
              averageUtilization: 50
              type: Utilization
          type: ContainerResource
          watermark: high
      scaleResourceLimit:
        maximum:
          cpu: '4'
        minimum:
          cpu: '1'
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: hello-avpa

    部分配置项说明如下:

    配置项

    是否必选

    说明

    scaleTargetRef

    指定目标工作负载。目前支持原生Deployment、StatefulSet、JobOpenKruiseAdvancedStatefulSet、CloneSet。

    metrics.containerResource

    用于设置指标采集的目标资源类型,利用率阈值等:

    • container:声明需要采集指标的目标容器名称。

    • name:声明要采集的指标名称(当前支持cpu)。

    • target:声明阈值信息。

      • type:取值为Utilization

      • averageUtilization:平均利用率阈值。

    metrics.watermark

    用于设置监控指标的阈值类型:

    • low:低水位阈值,当指标计算结果低于此阈值时,在满足时间窗口后进行缩容。

    • high:高水位阈值,当指标计算结果高于此阈值时,在满足时间窗口后进行扩容。

    metrics.type

    用于设置指标采集的粒度,按容器粒度进行汇聚,或Pod粒度进行汇聚,默认值为ContainerResource

    说明

    目前支持按容器粒度进行采集和汇聚计算。

    scaleResourceLimit.minimum

    垂直伸缩时的下限(目前仅支持设置cpu):

    • cpu: 默认值为250m(毫核)。

    scaleResourceLimit.maximum

    垂直伸缩时的上限(目前仅支持设置cpu):

    • cpu: 默认值为64(核)。

    Selector模式

    以下为0.2.0版本引入的Selector模式配置,可以更灵活的Selector选择目标Pod,从而简化AVPA针对一类Pod的配置流程。

    apiVersion: autoscaling.alibabacloud.com/v1beta1
    kind: AdvancedVerticalPodAutoscaler
    metadata:
      name: hello-avpa
      namespace: default
    spec:
      metrics:
        - containerResource:
            container: "*"
            name: cpu
            target:
              averageUtilization: 30
              type: Utilization
          type: ContainerResource
          watermark: low
        - containerResource:
            container: "*"
            name: cpu
            target:
              averageUtilization: 50
              type: Utilization
          type: ContainerResource
          watermark: high
      scaleResourceLimit:
        maximum:
          cpu: '4'
        minimum:
          cpu: '1'
      # 以下为示例的 selector 配置,可根据需求自行修改
      selector:
        matchLabels:
          vpa: enabled
        matchExpressions:
        # acs pod 的通用 label,作用在所有使用 acs 算力的 pod 上
        - key: alibabacloud.com/compute-class 
          operator: Exists
        - key: name 
          operator: In
          values: 
          - hello-avpa
        # 预留一个开关,便于不希望作用的应用可以自行关闭
        - key: alibabacloud.com/disable-avpa 
          operator: DoesNotExist

    配置项说明如下:

    selector配置项区别于scaleTargetRef只能指向一个workload,可以更灵活选择作用的Pod,满足更多场景的指标变配需求。

    配置项

    是否必选

    说明

    selector

    selectorscaleTargetRef互斥,二者需择一进行配置,以指定作用的Pod。selector模式可简化AVPA的配置流程,从而便于对同类应用的Pod进行统一管理,无需为多个工作负载分别设置AVPA。

    metrics.containerResource

    用于设置指标采集的目标资源类型,利用率阈值等:

    • container:声明需要采集指标的目标容器名称。

    说明

    支持使用通配符*来匹配所有容器名称。

    若某一容器同时符合默认通配符规则以及针对单个容器的特定规则,则以针对单个容器的规则为准。

    • name:声明要采集的指标名称(当前支持cpu)。

    • target:声明阈值信息。

      • type:取值为Utilization

      • averageUtilization:平均利用率阈值。

    metrics.watermark

    用于设置监控指标的阈值类型:

    • low:低水位阈值,当指标计算结果低于此阈值时,在满足时间窗口后进行缩容。

    • high:高水位阈值,当指标计算结果高于此阈值时,在满足时间窗口后进行扩容。

    metrics.type

    用于设置指标采集的粒度,按容器粒度进行汇聚,或Pod粒度进行汇聚,默认值为ContainerResource

    说明

    目前支持按容器粒度进行采集和汇聚计算。

    scaleResourceLimit.minimum

    垂直伸缩时的下限(目前仅支持设置cpu):

    • cpu: 默认值为250m(毫核)。

    scaleResourceLimit.maximum

    垂直伸缩时的上限(目前仅支持设置cpu):

    • cpu: 默认值为64(核)。

  2. [可选] avpa 可配置的高级设置字段示例如下:

    高级配置

    以下为AVPA高级配置,您可以通过细化控制变配的资源步长等信息来创建AVPA配置。

    apiVersion: autoscaling.alibabacloud.com/v1beta1
    kind: AdvancedVerticalPodAutoscaler
    metadata:
      name: hello-avpa
      namespace: default
    spec:
      behavior:
        parallelism: 1
        stabilizationWindowSeconds: 600
        scaleDown: #详细定义缩容的资源步长和策略,一般建议采用缓慢下降策略,但需要保证每次缩容的幅度能超过规整粒度
          policies:
          - type: CpuPercent
            value: 10%
            periodSeconds: 60
          - type: Cpus
            value: 500m
            periodSeconds: 60
          selectPolicy: Max
        scaleUp: #详细定义扩容的资源步长和策略,一般建议采用相对陡升的策略,以少量扩容次数满足负载的增加
          policies:
          - type: CpuPercent
            value: 60%
            periodSeconds: 60
          - type: Cpus
            value: 500m
            periodSeconds: 60
          selectPolicy: Max
      metricObserveWindowSeconds: 600
      metrics:
        - containerResource:
            container: hello-avpa
            name: cpu
            target:
              averageUtilization: 30
              type: Utilization
          type: ContainerResource
          watermark: low
        - containerResource:
            container: hello-avpa
            name: cpu
            target:
              averageUtilization: 50
              type: Utilization
          type: ContainerResource
          watermark: high
      scaleResourceLimit:
        maximum:
          cpu: '4'
        minimum:
          cpu: '1'
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: hello-avpa

    配置项说明如下:

    spec.behavior配置项中的scaleDownscaleUp分别描述扩容和缩容的资源策略,包含的子配置项语义相同。

    配置项

    是否必选

    说明

    policies[].type

    • Cpus:绝对值,变配的CPU资源步长绝对值。

    • CpuPercent:百分比,按当前规格的百分比计算CPU资源步长。

    policies[].value

    • type配置为Cpus时使用此配置,取值可配置250m1等。

    • type配置为CpuPercent时使用此配置,取值可配置为5%等百分比。

    selectPolicy

    计算策略,取值为:

    • Max:当设置多个策略时,按最大值作为目标步长。

    • Min:当设置多个策略时,按最小值作为目标步长。

    metricObserveWindowSeconds

    数据采集的窗口时间,当指标采集点满足此窗口时间的跨度后,开始进行指标的负载计算并判断是否进行变配。单位是秒,默认值为600秒,最小值为300秒。

    behavior.parallelism

    用于配置变配的并行度,同时处于变配的Pod数量,默认值为1

    behavior.stabilizationWindowSeconds

    变配的冷却时间,单位是秒,默认值为600秒,最小值为300秒。同时需要保证冷却时间不比数据采集的窗口时间metricObserveWindowSeconds小。

    AVPA在需要变配时会采用默认策略计算目标资源规格,即将highWaterMarklowWaterMark的平均值作为目标负载水位,计算出需要扩容或缩容的资源步长。例如,对于一个1vCpu的容器,高低阈值分别设置为6040,当前利用率100%,则目标利用率为50%,预期扩容步长为1vCpu,扩容至2vCpu

    按上述YAML中的配置,将按500m取最大值,即按600m步长进行扩容。

    说明

    建议配置:陡升缓降,快速扩容满足负载增加的需求,缓慢降配以提高稳定性。

    scaleUp:采用相对大的步长进行扩容,以少量的扩容次数满足负载诉求。如采用type: Cpusvalue: 1

    scaleDown:缓慢下降,随着负载下降小步长逐步降配,提升稳定性。如采用type: Cpusvalue: 250m

  3. 部署配置。

    kubectl apply -f avpa.yaml

步骤五:模拟压测

通过流量入口服务请求后端服务,进行CPU负载的加压。采用相同的规格配置和施加相同的业务请求负载,观察通过AVPA启用了变配和未启用变配的工作负载监控数据情况。

  1. 请求后端服务,进行加压。

    当前测试PodCPU规格为2vCpu,我们将负载初始提高至50%左右,即消耗1000毫核,持续加压2000s。并在之后每隔60s持续增加负载,每次多消耗200毫核,最终会在30分钟后达到4000毫核的负载。

    # 初始加压,单条命令最大加压限制为1000毫核
    curl --data "millicores=1000&durationSec=2000" http://localhost:28080/ConsumeCPU
    curl --data "millicores=1000&durationSec=2000" http://localhost:28081/ConsumeCPU
    # 持续小步长持续加压
    for i in {1..30}
    do
      sleep 60
      curl --data "millicores=100&durationSec=2000" http://localhost:28080/ConsumeCPU
      curl --data "millicores=100&durationSec=2000" http://localhost:28081/ConsumeCPU
    done
  2. 观察监控指标。

    在左侧导航栏,单击运维管理 > Prometheus 监控,在应用监控 > 无状态应用监控页签下查看监控数据。

    1. 可以看到在加压后CPU负载不断上升,在到达阈值10分钟左右CPU开始升配到2vCpu,且在30分钟内逐步升配至4vCpu。升配完成后,CPU的整体负载明显下降。

      image

    2. 切换到影子负载的监控,可以看到CPU很快被打满。

      image

  3. 观察Pod事件信息。

    通过Pod事件可以观测到Pod在扩缩容前的模板变配信息和结束事件。

    image

  4. 模拟低负载缩容。

    在加压结束,CPU负载降低到阈值后,将进行逐步的缩容,将CPU加压逐步撤除,模拟低负载情况。

    • 当负载逐步下降触达到缩容阈值后,CPU将被逐步按小步长进行缩容,确保服务整体的稳定性,不会因为资源陡降而引起业务波动。

    • 当负载长期处于低位后,容器的资源最终被缩容至AVPA中声明的最小资源规格1vCpu

    image

(可选)步骤六:清理资源

  1. 删除测试工作负载、服务和AVPA资源。

    kubectl delete -f hello-avpa.yaml
    kubectl delete -f shadow-hello-avpa.yaml
  2. 在左侧导航栏,选择应用 > Helm,单击ack-advanced-vertical-pod-autoscaler操作列的删除

常见问题 FAQ

如何查看avpa的状态信息

使用kubectl命令来获取avpa对象的实时状态

# 示例已经将集群的连接信息存储到 ~/.kube/acs-test 文件中,需自行准备
# export KUBECONFIG=~/.kube/acs-test 
kubectl get avpa -n [namespace] [-oyaml]

可能的返回如下:

$ kubectl get avpa
NAME         TARGETTYPE   TARGETNAME   REPLICAS   UPDATING   WAITING   LASTSCALED   AGE
hello-avpa                             1          0          0         11d          11d

如何查找正在变配中的实例信息

v0.3.0以上版本的avpa控制器会对正在变配中的pod附加一个特有的标签avpa.alibabacloud.com/resizing-lock以方便更好地定位变配状态。

kubectl get po -n  [ns] -lavpa.alibabacloud.com/resizing-lock

如何查找变配失败的实例信息

v0.3.0以上版本的avpa控制器会记录变配失败的Kubernetes event,用户可以在事件日志库中以InplaceResizedTimeoutFailed关键词进行搜索,同时增加对该失败事件的告警配置。

说明

对变配失败事件增加告警配置可参考创建告警监控规则