knative serving 自动扩缩容

发布时间 2023-10-09 18:22:01作者: 小吉猫

Knative Serving 自动缩放机制

缩容至0:即没有请求时,系统不会分配资源给KService.
从0开始扩容:由Activator缓存请求,并报告指标数据给AutoScaler.
按需扩容:AutoScaler根据Revision中各实例的QP报告的指标数据不断调整Revision中的实例数量.

Knative Serving 请求驱动计算

Knative Serving的自动扩缩容机制依赖于两个前提;
  1. 为Pod实例配置支持的目标并发数(在给定的时间里可同时处理的请求数)
  2. 应用实例支持的缩放边界
     1. 最少实例数,0即表示支持缩容至0实例;
     2. 最大实例数
AutoScaler的基本缩放逻辑:
  1. AutoScaler基于过去一段时间内(由stable window指定)统计的指标(metric)数据和单个实例的目标并发数(target)来计算目标实例数.
  2. 计算出的目标实例数将发送给相应Revision的Deployment执行缩放操作.

Autoscaler 执行扩缩容的基本流程

目标Revision零实例

1. 初次请求由Ingress GW转发给Activator进行缓存,同时报告数据给Autoscaler,进而控制相应的Deployment来完成Pod实例扩展;
2. Pod副本的状态Ready之后,Activator将缓存的请求转发至相应的Pod对象;
3. 随后,存在Ready状态的Pod期间,Ingress GW会将后续的请求直接转给Pod,而不再转给Activator;

目标Revision存在至少一个Ready状态的Pod

1. Autoscaler根据Revision中各Pod的Queue-Proxy容器持续报告指标数据持续计算Pod副本数;
2. Deployment根据Autoscaler的计算结果进行实例数量调整;

Revision实例数不为0,但请求数持续为0

1. Autoscaler在Queue-Proxy持续一段时间报告指标为0之后,即为将其Pod数缩减为0;
2. 随后,Ingress GW会将收到的请求再次转发为Activator;

Knative Serving 支持的自动缩放器类型

Knative Serving 支持 Knative Pod Autoscaler (KPA) 和 Kubernetes 的 Horizo​​ntal Pod Autoscaler (HPA) 的实现。

Knative Pod Autoscaler (KPA)

Knative Serving 核心的一部分,安装 Knative Serving 后默认启用。
支持缩放至零功能。
不支持基于CPU的自动缩放。

Horizo​​ntal Pod Autoscaler (HPA)

不是 Knative Serving 核心的一部分,您必须先安装 Knative Serving。
不支持缩放至零功能。
支持基于CPU的自动缩放。

Autoscaler 配置

配置参数

Global settings key: pod-autoscaler-class
Per-revision annotation key: autoscaling.knative.dev/class
Possible values: "kpa.autoscaling.knative.dev" or "hpa.autoscaling.knative.dev"
Default: "kpa.autoscaling.knative.dev"

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 pod-autoscaler-class: "kpa.autoscaling.knative.dev"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/class: "kpa.autoscaling.knative.dev"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

KPA 窗口模式

负载变动频繁时,Knative可能会因为响应负载变动而导致频繁创建或销毁Pod实例。
为避免服务规模“抖动”,AutoScaler支持两种扩缩容模式:stable和panic。每种模式都有单独的聚合窗口:分别是stable-window和panic-window。
stable模式用于一般操作,而panic模式默认情况下具有更短的窗口,并且将用于在突发流量到达时快速扩容。

Stable window

根据稳定窗口期(stable window,默认为60秒)的请求平均数(平均并发数)及每个Pod的目标并发数计算Pod数。

配置参数

Global key: stable-window
Per-revision annotation key: autoscaling.knative.dev/window
Possible values: Duration, 6s <= value <= 1h
Default: 60s

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 stable-window: "40s"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/window: "40s"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

Panic window

短期内收到大量请求时,将启用Panic模式。
panic窗口被定义为stable窗口的百分比,以确保两者以工作方式相互关联。

配置参数

Global key: panic-window-percentage
Per-revision annotation key: autoscaling.knative.dev/panic-window-percentage
Possible values: float, 1.0 <= value <= 100.0
Default: 10.0      # 百分比。Stable window模式的10%。

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 panic-window-percentage: "20.0"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/panic-window-percentage: "20.0"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

Panic mode 阈值

此阈值定义自动缩放器何时从stable模式转变为panic模式。
该值是当前副本数量可以处理的流量的百分比。
值100.0(100%) 表示自动缩放器始终处于panic模式,因此最小值应高于100.0。

配置参数

默认设置200.0意味着如果流量是当前副本群体可以处理的两倍,则将启动panic模式。

Global key: panic-threshold-percentage
Per-revision annotation key: autoscaling.knative.dev/panic-threshold-percentage
Possible values: float, 110.0 <= value <= 1000.0
Default: 200.0    # 百分比

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 panic-threshold-percentage: "150.0"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/panic-threshold-percentage: "150.0"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

Autoscaler  扩缩容速率

这些设置控制副本数量在单个评估周期中可以扩大或缩小的程度。

扩容速率

此设置确定所需 pod 与现有 pod 的最大比率。例如,如果值为 2.0,则revision只能在一个评估周期内从 N 个 pod 扩展到 2*N 个 pod。
当前可最大扩容数 = 最大扩容速率 * Ready状态的Pod数量

配置参数

Global key: max-scale-up-rate
Per-revision annotation key: n/a
Possible values: float
Default: 1000.0

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 max-scale-up-rate: "500.0"

缩容速率

此设置确定现有 pod 与所需 pod 的最大比率。例如,如果值为 2.0,则revision只能在一个评估周期内从 N 个 pod 扩展到 N/2 个 pod。
当前可最大缩容数 = Ready状态的Pod数量 / 最大缩容速率。

配置参数

Global key: max-scale-down-rate
Per-revision annotation key: n/a
Possible values: float
Default: 2.0

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 max-scale-down-rate: "4.0"

Autoscaler 可用指标

默认 KPA Autoscaler 支持concurrency和rps指标。
HPA Autoscaler 支持该cpu指标。

配置参数

Per-revision annotation key: autoscaling.knative.dev/metric
Possible values: "concurrency", "rps", "cpu", "memory" or 自定义指标
Default: "concurrency"

concurrency 指标配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/metric: "concurrency"

rps 指标配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/metric: "rps"

cpu 指标配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/class: "hpa.autoscaling.knative.dev"
        autoscaling.knative.dev/metric: "cpu"

memory 指标配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/class: "hpa.autoscaling.knative.dev"
        autoscaling.knative.dev/metric: "memory"

自定义指标配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/class: "hpa.autoscaling.knative.dev"
        autoscaling.knative.dev/metric: "<metric-name>"

配置支持缩容至0实例

启用缩放至零

enable-scale-to-zero设置为true允许副本缩小到零。设置为false则停止在 1 个副本。

配置参数

Global key: enable-scale-to-zero
Per-revision annotation key: 不支持
Possible values: boolean
Default: true

配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 enable-scale-to-zero: "false"  # 保留一个pod

缩容至0的宽限期

缩容至0的宽限期,即等待最后一个Pod删除的最大时长,默认为30s;

配置参数

Global key: scale-to-zero-grace-period
Per-revision annotation key: n/a
Possible values: Duration
Default: 30s

设置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 scale-to-zero-grace-period: "40s"

缩容至0时最后一个pod处于活动的最小时长

决定缩容至0后,允许最后一个Pod处于活动状态的最小时长,默认为0s;

配置参数

Global key: scale-to-zero-pod-retention-period
Per-revision annotation key: autoscaling.knative.dev/scale-to-zero-pod-retention-period
Possible values: Non-negative duration string
Default: 0s

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 scale-to-zero-pod-retention-period: "42s"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/scale-to-zero-pod-retention-period: "1m5s"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

配置并发数

并发数决定了应用程序的每个副本在任何给定时间可以处理的同时请求的数量。
对于每个revision 版本的并发性,必须配置 autoscaling.knative.dev/metric 和 autoscaling.knative.dev/target 进行软限制,或配置 containerConcurrency 进行硬限制。
对于全局设置,可以设置container-concurrency-target-default值。
如果同时指定了软限制和硬限制,则将使用两个值中较小的一个。这可以防止自动缩放器具有硬限制值不允许的目标值。

软限制

软限制是有针对性的限制,而不是严格执行的界限。在某些情况下,特别是请求突然爆发时,可能会超过该值。

配置参数

Global key: container-concurrency-target-default
Per-revision annotation key: autoscaling.knative.dev/target
Possible values: An integer.
Default: "100"

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 container-concurrency-target-default: "200"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/target: "200"

硬限制

硬限制是强制上限。如果并发达到硬限制,多余的请求将被缓冲,并且必须等待,直到有足够的可用容量来执行请求。
仅当应用程序有明确的用例时,才建议使用硬限制配置。指定较低的硬限制可能会对应用程序的吞吐量和延迟产生负面影响,并可能导致额外的冷启动。

配置参数

Global key: container-concurrency (in config-defaults.yaml)
Per-revision spec key: containerConcurrency
Possible values: 整数
Default: 0, 表示没有限制

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-defaults
 namespace: knative-serving
data:
 container-concurrency: "50"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    spec:
      containerConcurrency: 50

Target 目标利用率

除了软限制和硬限制设置之外,还可以使用target利用率值进一步调整并发值。
该值指定自动缩放器实际应定位的先前指定目标的百分比。这也称为指定副本运行的热度,这会导致自动缩放器在达到定义的硬限制之前进行扩展。
例如,如果containerConcurrency设置为10,目标利用率值设置为70(百分比),则当所有现有副本的平均并发请求数达到7时,自动缩放器将创建新副本。编号为 7 到 10 的请求仍将发送到现有副本,但这允许在达到容器并发限制时启动额外的副本,以应对需要的情况。

配置参数

Global key: container-concurrency-target-percentage
Per-revision annotation key: autoscaling.knative.dev/target-utilization-percentage
Possible values: float
Default: 70

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 container-concurrency-target-percentage: "80"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/target-utilization-percentage: "80"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

配置每秒目标请求数 (RPS)

此设置指定应用程序每个副本的目标每秒请求数。revision 版本还必须配置为使用 rps 指标注释。

配置参数

Global key: requests-per-second-target-default
Per-revision annotation key: autoscaling.knative.dev/target
Possible values: An integer.
Default: "200"

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 requests-per-second-target-default: "150"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/target: "150"
        autoscaling.knative.dev/metric: "rps"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

配置扩缩容边界

可以配置上限和下限来控制自动缩放行为。
还可以指定revision在创建后立即缩放到的初始比例。这可以是所有revision的默认配置,也可以是使用注释的特定revision的默认配置。

最小实例数

该值控制每个revision应具有的最小副本数。Knative 将尝试在任何一个时间点都不会少于此数量的副本。

配置参数

Global key: min-scale
Per-revision annotation key: autoscaling.knative.dev/min-scale
Possible values: integer
Default: 启用KPA且支持缩容至0时,该参数的默认值为0;其它情况下,默认值为1。

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  min-scale: "3"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/min-scale: "3"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

最大实例数

该值控制每个revision 应具有的最大副本数。Knative 将尝试在任何一个时间点运行或创建过程中永远不会有超过此数量的副本。
如果设置了 max-scale-limit 全局键,Knative 确保全局最大比例和新revision 的每个revision 最大比例都不会超过该值。当 max-scale-limit 设置为正值时,不允许最大比例高于该值(包括 0,表示无限制)的revision 。

配置参数

Global key: max-scale
Per-revision annotation key: autoscaling.knative.dev/max-scale
Possible values: integer
Default: 0 表示无限制

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  max-scale: "3"
  max-scale-limit: "100"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/max-scale: "3"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

初始规模

创建Revision,需要立即初始创建的实例数,满足该条件后Revision才能Ready,默认值为1;
该值控制Revision从零扩展时将创建的最小副本数。当修订达到此比例一次后,该值将被忽略。这意味着在达到激活规模后,如果实际接收到的流量需要更小的规模,则Revision将缩小。
创建Revision时,将自动选择激活规模和下限中的较大者作为初始目标规模。

配置参数

Global key: initial-scale 和 allow-zero-initial-scale
Per-revision annotation key: autoscaling.knative.dev/initial-scale
Possible values: integer
Default: 1

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  initial-scale: "0"
  allow-zero-initial-scale: "true"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/initial-scale: "0"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

最小规模扩大

该值控制Revision从零扩展时将创建的最小副本数。当修订达到此比例一次后,该值将被忽略。这意味着在达到激活规模后,如果实际接收到的流量需要更小的规模,则Revision将缩小。
创建Revision时,将自动选择激活规模和下限中的较大者作为初始目标规模。

配置参数

Global key: n/a
Per-revision annotation key: autoscaling.knative.dev/activation-scale
Possible values: integer
Default: 1

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/activation-scale: "5"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

缩容延迟

时间窗口,在应用缩容决策前,该时间窗口内并发请求必须处于递减状态,取值范围[0s, 1h]

配置参数

Global key: scale-down-delay
Per-revision annotation key: autoscaling.knative.dev/scale-down-delay
Possible values: Duration, 0s <= value <= 1h
Default: 0s (无延迟)

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  scale-down-delay: "15m"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/scale-down-delay: "15m"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

Stable 窗口

stable 窗口定义了滑动时间窗口,在该窗口上对指标进行平均,以便在自动缩放器不处于Panic模式时为缩放决策提供依据。

配置参数

Global key: stable-window
Per-revision annotation key: autoscaling.knative.dev/window
Possible values: Duration, 6s <= value <= 1h
Default: 60s

全局配置示例

apiVersion: v1
kind: ConfigMap
metadata:
 name: config-autoscaler
 namespace: knative-serving
data:
 stable-window: "40s"

单个 revision 配置示例

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/window: "40s"
    spec:
      containers:
        - image: ghcr.io/knative/helloworld-go:latest

全局配置参数

◼ container-concurrency-target-default:实例的目标并发数,即最大并发数,默认值为100;
◼ container-concurrency-target-percentage:实例的目标利用率,默认为“0.7”;
◼ enable-scale-to-zero:是否支持缩容至0,默认为true;仅KPA支持;
◼ max-scale-up-rate:最大扩容速率,默认为1000;
  ◆当前可最大扩容数 = 最大扩容速率 * Ready状态的Pod数量
◼ max-scale-down-rate:最大缩容速率,默认为2;
  ◆当前可最大缩容数 = Ready状态的Pod数量 / 最大缩容速率
◼ panic-window-percentage:Panic窗口期时长相当于Stable窗口期时长的百分比,默认为10,即百分之十;
◼ panic-threshold-percentage:因Pod数量偏差而触发Panic阈值百分比,默认为200,即2倍;
◼ scale-to-zero-grace-period:缩容至0的宽限期,即等待最后一个Pod删除的最大时长,默认为30s;
◼ scale-to-zero-pod-retention-period:决定缩容至0后,允许最后一个Pod处于活动状态的最小时长,默认为0s;
◼ stable-window:稳定窗口期的时长,默认为60s;
◼ target-burst-capacity:突发请求容量,默认为200;
◼ requests-per-second-target-default:每秒并发(RPS)的默认值,默认为200;使用rps指标时生效;

参考文档

https://knative.dev/docs/serving/autoscaling