PoolAutoscaler 根据可用 Sandbox 数量与 Cron 定时计划自动调整预热池大小,不足时补池、空闲时缩池,兼顾领取延迟与预热成本。
背景信息
PoolAutoscaler 用于自动调整预热池的大小。它以未被领取的可用 Sandbox 数量和配置的 Cron 计划为依据,修改 SandboxSet 的 spec.replicas:可用 Sandbox 不足时补池,空闲 Sandbox 过多时缩池,也可以在已知高峰前提前预热。
相比基于 CPU、QPS 指标的自动伸缩,PoolAutoscaler 不采集业务指标,也不预测流量,仅管理预热池容量;Sandbox 被领取后的业务生命周期仍由 Agent Sandbox 服务处理。预热池的基础概念与创建方式,请参见创建Agent Sandbox。
应用场景
该能力适合以下场景:
请求量随时变化:例如通过 E2B API(开源沙箱服务接口)创建、使用并释放 Sandbox,希望始终保留一定数量的可用 Sandbox,以降低领取等待时间。
高峰时间可预期:例如工作日上班前、定时任务开始前或活动开始前,可在指定时间提前创建预热池。
两类流量并存:日常通过容量策略补池,并在已知高峰时由 Cron 策略指定预热规模。
适用范围
已安装
ack-agent-sandbox-controller组件且版本不低于v0.6.6-release.5:PoolAutoscaler 自该版本起提供并默认启用,无需额外配置;更低版本不支持该能力,需先升级组件。若组件版本已满足仍无法创建 PoolAutoscaler,可通过启动参数--feature-gates=PoolAutoscaler=true显式开启。版本与变更记录、安装方式,请参见ack-agent-sandbox-controller 使用说明。已创建待管理的 SandboxSet,且 SandboxSet 控制器正常运行。具体操作,请参见创建Agent Sandbox。
同一命名空间(Namespace)内,一个 SandboxSet 最多只能由一个 PoolAutoscaler 管理。
PoolAutoscaler 至少配置一种策略:
capacityPolicy或cronPolicies。
使用限制
PoolAutoscaler 仅修改目标 SandboxSet 的
spec.replicas,不直接创建或删除 Pod。请勿让 HPA(Horizontal Pod Autoscaler,Pod 水平自动伸缩)、AHPA(Advanced Horizontal Pod Autoscaler,高级预测弹性伸缩)、脚本或其他控制器同时修改同一个字段,否则扩缩结果会互相覆盖。PoolAutoscaler 与 SandboxSet 必须位于同一命名空间。
场景一:按可用容量自动补池
此场景适用于请求量难以准确预估、但希望稳定获得低领取延迟的业务。例如业务通过 E2B API 不断创建 Sandbox、执行代码或命令、完成后释放 Sandbox。每次领取都会消耗预热池中的可用 Sandbox;容量策略据此补充未被领取的 Sandbox。
步骤一:通过 SandboxSet 创建预热池
若已创建预热池,可直接复用现有 SandboxSet。以下为最小示例,各字段含义见注释;请将标注“必须替换”的字段改为当前集群已验证的值。
将以下内容保存为 sandboxset.yaml。
apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet metadata: name: sandbox-pool # SandboxSet 名称,步骤二的 PoolAutoscaler 通过此名称引用;可按需修改 namespace: default # 部署命名空间;PoolAutoscaler 必须与它同 namespace spec: replicas: 2 # 初始预热池大小;应用 PoolAutoscaler 后由其接管,可按成本设小一些 scaleStrategy: maxUnavailable: "30%" # 建议配置:兼作启动预算,启动失败/超时数达到该值时暂停继续扩容 runtimes: - name: agent-runtime # 注入 envd 兼容运行时,步骤三的 E2B 代码执行/文件/命令能力依赖它 template: spec: containers: - name: sandbox image: <YOUR-SANDBOX-IMAGE> # 必须替换:集群内可拉取的 Agent Sandbox 运行时镜像 resources: requests: # 调度申请资源,影响预热池单实例成本和可放置的节点范围 cpu: "1" memory: 1Gi limits: # 资源上限;按实际运行时需要调整,过大浪费预热成本,过小影响启动 cpu: "1" memory: 1Gi创建预热池并查看状态。
kubectl apply -f sandboxset.yaml kubectl get sandboxset sandbox-pool -n defaultruntimes: agent-runtime是步骤三 E2B 验证的必要条件(run_code、文件读写、命令执行均依赖注入的 envd 运行时)。运行时注入机制及其对sandbox-injection-configConfigMap 的依赖,请参见为 Agent Sandbox 配置 Sidecar 容器自动注入。
步骤二:配置 PoolAutoscaler
以下策略按比例维护预热池:目标可用比例为 50%,使用默认容差 10%,近期平均可用比例低于 40% 时扩容,高于 60% 时缩容,两者之间不调整。百分比水位随池规模弹性伸缩,适合负载波动的业务。
将以下内容保存为 pool-autoscaler.yaml。
apiVersion: agents.kruise.io/v1alpha1 kind: PoolAutoscaler metadata: name: sandbox-pool-autoscaler # PoolAutoscaler 名称,仅用于标识和后续 kubectl 查询,可按需修改 namespace: default # 必须与目标 SandboxSet 同 namespace spec: scaleTargetRef: apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet # 仅支持 SandboxSet,不可修改 name: sandbox-pool # 步骤一中创建的 SandboxSet 名称 minReplicas: 2 # 预热池下限;百分比目标需满足缩容可达性,见下方说明 maxReplicas: 50 # 预热池上限;按业务峰值并发量与集群容量设置 capacityPolicy: targetAvailable: "50%" # 目标可用(未被领取的)Sandbox 占副本数的比例,随池规模弹性伸缩 # tolerance 未设置时默认为 10%,与目标合并后形成 40%~60% 的不调整区间 scaleUp: stabilizationWindowSeconds: 60 # 扩容稳定窗口,即连续两次扩容的最小间隔;设小可加快补池,但过小会导致扩容过于频繁 scaleDown: stabilizationWindowSeconds: 300 # 缩容稳定窗口,即连续两次缩容的最小间隔;拉长可避免夜间流量波动频繁回收预热池创建 PoolAutoscaler 并查看状态。
kubectl apply -f pool-autoscaler.yaml kubectl get poolautoscaler sandbox-pool-autoscaler -n default
minReplicas 和 maxReplicas 始终生效,所有策略计算出的副本数都会被限制在这个范围内。targetAvailable、tolerance 和 minReplicas 的取值共同决定空闲预热池能否收缩到 minReplicas,配置规则参见本文容量策略调优说明。
稳定窗口的取值建议保持缩容长于扩容(默认 60 秒对 300 秒,上述示例也保持了这一关系):快速扩容可及时补齐预热池、保障领取延迟,缓慢缩容可避免瞬时流量回落时回收预热容量造成容量抖动。
步骤三:使用 E2B 业务流量验证
以下单文件脚本模拟真实业务流量:每个并发循环从预热池领取一个 Sandbox,执行代码、读写文件、执行命令,短暂持有后释放。预热池的扩缩容状态可通过步骤四的命令另行观察。
准备工作:
本地已安装 Python 3.9 及以上版本,并已配置目标集群的 kubeconfig(用于 kubectl 观察状态)。
安装 E2B SDK(版本须与
ack-sandbox-manager组件兼容):pip install e2b-code-interpreter。准备可访问的 E2B 服务域名、API Key;集群使用自签证书时,还需准备 CA 证书。
将脚本保存为 poolautoscaler-verify.py。
#!/usr/bin/env python3
"""Generate E2B business traffic against a PoolAutoscaler-managed pool.
Usage:
E2B_API_KEY='<YOUR-E2B-API-KEY>' \
E2B_DOMAIN='<YOUR-E2B-DOMAIN>' \
SSL_CERT_FILE='<YOUR-CA-FILE>' \
python poolautoscaler-verify.py --template sandbox-pool
"""
import argparse, os, sys, threading, time
from concurrent.futures import ThreadPoolExecutor
stop = threading.Event()
def business_loop(loop_id, template, hold, deadline):
"""One worker: claim a sandbox, run business calls, hold, then release."""
from e2b_code_interpreter import Sandbox
seq = 0
while time.monotonic() < deadline and not stop.is_set():
seq += 1
sandbox = None
try:
# no timeout: the SDK timeout is the sandbox lifetime, not a create wait
sandbox = Sandbox.create(template=template)
sandbox.run_code(f"print('loop={loop_id} seq={seq}')")
path = f"verify-{loop_id}-{seq}.txt"
content = f"loop={loop_id} seq={seq}\n"
sandbox.files.write(path, content)
assert sandbox.files.read(path) == content, "file content mismatch"
assert sandbox.commands.run(f"cat {path}").stdout == content
stop.wait(hold) # simulate the business holding the sandbox
sandbox.kill()
except Exception as exc:
if sandbox is not None:
try:
sandbox.kill() # release the claimed sandbox before backing off
except Exception:
pass
print(f"loop {loop_id} seq {seq} failed: "
f"{type(exc).__name__}: {exc}", file=sys.stderr, flush=True)
stop.wait(5) # back off before the next attempt
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--template", default="sandbox-pool",
help="SandboxSet name, i.e. the E2B template")
parser.add_argument("--concurrency", type=int, default=10,
help="simultaneous business sandboxes; each consumes one pool slot")
parser.add_argument("--duration-seconds", type=int, default=300)
parser.add_argument("--hold-seconds", type=int, default=30,
help="how long each loop holds its sandbox before releasing")
args = parser.parse_args()
if not os.getenv("E2B_API_KEY"):
parser.error("E2B_API_KEY must be set")
deadline = time.monotonic() + args.duration_seconds
print(f"load: {args.concurrency} loops x {args.duration_seconds}s, "
f"hold={args.hold_seconds}s (Ctrl+C stops early)", flush=True)
try:
with ThreadPoolExecutor(max_workers=args.concurrency) as pool:
futures = [pool.submit(business_loop, i, args.template,
args.hold_seconds, deadline)
for i in range(args.concurrency)]
for future in futures:
future.result()
except KeyboardInterrupt:
print("interrupted; waiting for in-flight sandboxes to settle...", flush=True)
finally:
stop.set()
return 0
if __name__ == "__main__":
main()运行脚本(另开一个终端执行步骤四的观察命令,可实时看到扩容):
E2B_API_KEY='<YOUR-E2B-API-KEY>' \
E2B_DOMAIN='<YOUR-E2B-DOMAIN>' \
SSL_CERT_FILE='<YOUR-CA-FILE>' \
python poolautoscaler-verify.py \
--template sandbox-pool \
--concurrency 10 \
--duration-seconds 300 \
--hold-seconds 30参数说明:
--concurrency:并发领取数。建议不超过池内稳态可用数(由minReplicas与targetAvailable共同决定):超过会击穿预热池,首次数据面调用可能返回 503(属预期现象,稍后重试即可),正常补池约需 20~30 秒。--hold-seconds:每个 Sandbox 的业务持有时长;越长则单位时间领取次数越少。--duration-seconds:压测总时长,建议不小于扩容稳定窗口(默认 60 秒)的 3 倍,以观察至少两轮扩容。
预期现象:压测期间使用步骤四的命令观察,currentCapacity.available 下降、desiredReplicas 逐步抬升,说明容量策略检测到领取消耗并补充预热池。池被击穿时 create 虽返回 running,但数据面可能尚未就绪,首次调用返回 503 属预期现象,稍后重试即可。
验证缩容(可选):流量结束后,手动调低 targetAvailable 并观察预热池收敛。
kubectl patch poolautoscaler sandbox-pool-autoscaler -n default \
--type merge -p '{"spec":{"capacityPolicy":{"targetAvailable":"10%"}}}'
kubectl get sandboxset sandbox-pool -n default -w预热池应逐步缩至 minReplicas(示例为 2)。验证完成后,将 targetAvailable 改回原值即可。
步骤四:观测扩缩容节奏与启动保护
kubectl get poolautoscaler sandbox-pool-autoscaler -n default -o yaml
kubectl get sandboxset sandbox-pool -n default -o yaml
kubectl describe poolautoscaler sandbox-pool-autoscaler -n default重点查看 status.currentReplicas、status.desiredReplicas、status.currentCapacity.available 和 status.conditions。这些是最近一次调谐(Reconcile,控制器周期性将实际状态对齐期望状态的过程)的观测值,可能与 SandboxSet 的实时状态存在短暂偏差;可用 Sandbox 数为 0 时,status.currentCapacity.available 字段不显示。扩缩容动作与异常原因会以事件形式记录在 PoolAutoscaler 对象上,常见事件参见本文常见事件。
容量策略基于近期一段观察时间内的平均可用数量做决策,以平滑瞬时波动;首次扩缩容可以立即执行,后续按稳定窗口节奏执行:扩容稳定窗口默认 60 秒,缩容稳定窗口默认 300 秒,可通过 stabilizationWindowSeconds 调整(参见本文参数配置约束说明)。扩容稳定窗口的默认值已包含 Pending 超时的安全余量;配置更大的值时以配置值为准。
当 SandboxSet 当前 generation 的 ScalingLimited=True 时,PoolAutoscaler 暂停继续扩容,避免在启动失败或 Pending 超时已耗尽预算时继续提高目标;缩容不受此限制。正在创建的 Sandbox 的创建并发由 SandboxSet 控制,PoolAutoscaler 不直接管理 Pod。限流的触发条件、恢复方式与排查步骤参见本文故障排查:扩容限流的触发与恢复。
调参建议:从小范围配置起步——较小的 minReplicas、maxReplicas 和较长的缩容稳定窗口——结合启动成功率、领取延迟及预热成本逐步调整。若需临时观察或人工接管,可暂停自动扩缩容(恢复时设为 false 或删除该字段):
kubectl patch poolautoscaler sandbox-pool-autoscaler -n default \
--type merge -p '{"spec":{"suspend":true}}'步骤五(可选):删除 PoolAutoscaler
不再需要自动扩缩容时(例如业务下线或改为固定规模),可删除 PoolAutoscaler。删除后,SandboxSet 和现有 Sandbox 均会保留,SandboxSet 副本数维持在删除前的值,不会自动缩容;如需回收预热池,需再手动调整 spec.replicas 或删除 SandboxSet。
删除 SandboxSet 会级联删除该预热池内的全部 Sandbox,包括已被业务领取、仍在运行的 Sandbox,业务会话会随之中断,且删除后不可恢复。建议先按下述顺序回收预热池:先将 spec.replicas 调小或置为 0,确认池内 Sandbox 均已被业务释放后,再删除 SandboxSet。
kubectl delete poolautoscaler sandbox-pool-autoscaler -n default场景二:按时间提前预热
此场景适用于高峰时间明确的业务,例如每个工作日 09:00 前会有大量用户创建开发环境。Cron 策略会在高峰开始前直接设定预热池目标,避免等到可用 Sandbox 耗尽后再扩容。
以下示例在工作日 08:30 将预热池设为 30 个副本,20:00 调整为 5 个副本。
将以下内容保存为 pool-autoscaler-cron.yaml。
apiVersion: agents.kruise.io/v1alpha1 kind: PoolAutoscaler metadata: name: sandbox-pool-schedule # 仅用于标识,可按需修改 namespace: default # 必须与目标 SandboxSet 同 namespace spec: scaleTargetRef: apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet # 仅支持 SandboxSet name: sandbox-pool # 必须替换:已创建的 SandboxSet 名称 minReplicas: 2 # 平台下限;Cron 目标也会被限制在该范围内 maxReplicas: 50 # 平台上限;需覆盖所有 Cron 策略中最大的 targetReplicas cronPolicies: - name: weekday-peak # 策略名,同一 PoolAutoscaler 内必须唯一 timeZone: Asia/Shanghai # 不设置时默认使用 controller 所在时区,建议显式指定 schedule: "30 8 * * 1-5" # 五段 Cron:分 时 日 月 星期;此处为工作日 08:30 targetReplicas: 30 # 触发时直接把预热池设为 30,需不超过 maxReplicas - name: weekday-offpeak timeZone: Asia/Shanghai schedule: "0 20 * * 1-5" # 工作日 20:00 缩回夜间规模 targetReplicas: 5创建 PoolAutoscaler 并查看状态。
kubectl apply -f pool-autoscaler-cron.yaml kubectl get poolautoscaler sandbox-pool-schedule -n default
cronPolicies 使用五段 Cron 表达式:分、时、日、月、星期。未设置 timeZone 时使用 controller manager 进程的时区。当 Cron 计划时间点触发时,会立即将副本数调整为该策略的 targetReplicas,且不受容量策略稳定窗口限制;最终副本数仍受 minReplicas 和 maxReplicas 限制,扩容同样受 SandboxSet 启动保护限制(参见本文故障排查:扩容限流的触发与恢复)。
若同时配置容量策略,则未触发 Cron 时按容量策略补池,两次 Cron 触发之间,副本数由容量策略按可用容量水位持续调整,可能将副本数调离 Cron 目标(包括向下),Cron 目标并非持续生效的容量下限。Cron 策略直接设定目标副本数,不受容量策略水位和缩容可达性规则约束,但仍会遵守扩容限流:Cron 抬升目标时若 SandboxSet 启动预算耗尽,同样会被阻塞并等待预算恢复。需要 Cron 时段内的持续保底容量时,用 minReplicas 表达(始终生效);避免将 Cron 目标设置在容量策略期望水位之下,否则副本数会在两个目标之间反复调整。
故障排查:扩容限流的触发与恢复
扩容限流是 SandboxSet 的启动保护机制:当同一时间存在过多启动失败或长期 Pending 的 Sandbox 时,暂停进一步提高副本数,避免在异常状态下制造更多无法启动的 Sandbox。PoolAutoscaler 读取该信号并暂停扩容。
触发条件
SandboxSet 的 spec.scaleStrategy.maxUnavailable 同时作为启动预算;未设置时默认为当前副本数(相当于 100%,即需全部实例启动异常才触发限流)。注意它与 updateStrategy.maxUnavailable(滚动更新用,默认 20%)是不同字段。处于创建阶段的 Sandbox 按以下两类计数占用预算:
Failed:Ready condition 为
False且 reason 为StartContainerFailed、PodCreateFailed或Unschedulable,即明确的启动失败(容器启动失败、镜像或配置错误、创建 API 失败、调度失败如节点资源不足或底层调度错误等)。TimedOut:长期停留在
Creating/ResourcePending状态,且创建时间超过 Pending 超时阈值(默认 50 秒)仍未 Ready。该计数在 SandboxSet 的 status message 与事件中显示为Timeout。
镜像拉取失败 ImagePullBackOff不计入 Failed,而是超过 Pending 阈值(默认 50 秒)后计入 Timeout,此时 Pod 的 Ready condition reason 仍为 PodReady。
当 Failed + TimedOut >= 启动预算 时,SandboxSet 写入如下状态,同时发出 Warning 级 ScalingLimited 事件。
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
name: sandbox-pool
namespace: default
status:
conditions:
- type: ScalingLimited
status: "True"
reason: StartupBudgetExhausted
message: '2 of 2 startup slots are blocked: Timeout=1, Failed=1'PoolAutoscaler 检测到该 condition 后:
暂停扩容:
status.desiredReplicas不再抬升,即使可用数量已低于下水位;等待期间周期性发出 Normal 级ScaleBlocked事件。缩容不受影响:上水位触发的缩容照常执行。
容错处理:仅当 SandboxSet 报告的是当前 generation 的显式
True才阻塞;condition 缺失、陈旧或为Unknown时按无信号处理,扩容照常,避免升级或首次调谐期间误阻塞。
注意区分两个同名 condition:SandboxSet status 中的 ScalingLimited 表示启动预算耗尽;PoolAutoscaler 自身的 ScalingLimited(参见本文CRD 字段说明)表示期望副本数触及 minReplicas/maxReplicas 边界,两者含义不同。
恢复方式
恢复不需要人工干预,满足任一条件后预算自动释放:
失败的 Sandbox 被删除(手动删除或业务侧清理),或其 Pod 恢复
Running且 Ready 变为True;Pending 超时的 Sandbox 完成启动进入
Running,或被删除。
当 Failed + TimedOut 降回预算以下,SandboxSet 下一次调谐会将 ScalingLimited 改回 False,PoolAutoscaler 随即恢复扩容并继续补池。
排查与应对
镜像拉取失败通常表现为 Timeout 计数偏高而 Failed 为 0(message 形如「Timeout=N, Failed=0」)。应结合 ImagePullBackOff 的 kubectl describe pod 事件确认是否为镜像地址/凭证问题,不要只依据 Failed 计数排查。
常见事件
PoolAutoscaler 在每次调谐时将扩缩容动作与异常原因记录为自身对象的事件,常用查看方式:
# 查看 PoolAutoscaler 的事件列表
kubectl describe poolautoscaler sandbox-pool-autoscaler -n default
# 按对象筛选事件
kubectl get events -n default --field-selector involvedObject.name=sandbox-pool-autoscaler事件(Reason) | 级别 | 含义与应对 |
| Normal | 副本数已上调,message 附带调整前后的数值与决策原因,例如可用数量低于下水位( |
| Normal | 副本数已下调,message 附带调整前后的数值与决策原因,例如可用数量高于上水位,或缩容被 |
| Normal | 一次扩缩容被抑制:目标仍在对应方向的稳定窗口冷却期内(message 形如 |
| Warning | 无法读取目标 SandboxSet。检查 |
| Warning | 期望副本数计算失败,通常由策略配置非法导致,对照本文参数配置约束说明核对 |
| Warning | 向 SandboxSet 写入新副本数失败,例如 API 冲突或 Webhook 拒绝。控制器会自动重试,持续出现时需排查。 |
SandboxSet 自身在启动预算耗尽时会在其对象上发出 Warning 级 ScalingLimited 事件,与 PoolAutoscaler 侧的 ScaleBlocked 事件成对出现,详见本文故障排查:扩容限流的触发与恢复。
容量策略调优说明
容量策略根据“目标值 + 容差”计算上下水位:
targetAvailable为绝对值(如10)时:下水位 = 目标值 - 容差,上水位 = 目标值 + 容差。targetAvailable为百分比(如"60%")时:以近期平均副本数为基准,先将目标与容差的百分比合并,再向上取整,即下水位 =ceil(平均副本数 × (目标 - 容差)%),上水位 =ceil(平均副本数 × (目标 + 容差)%)。tolerance未设置时默认为10%。目标是百分比时按百分比合并;目标是绝对值时,默认容差为该目标值的 10% 向上取整(例如目标为 10 时容差为 1,目标为 15 时容差为 2)。
平均可用数量低于下水位时扩容,并补足到目标值附近;高于上水位时缩容;位于两者之间时不调整。
避免将 targetAvailable 配置为 "100%":可用数量最多等于副本数,永远不会严格高于上水位,因此无论容差如何配置,空闲预热池都永不缩容、只增不减。若确实希望池规模只增不减,再考虑使用 100% 目标。
确保空闲预热池能收缩到 minReplicas
容量策略应保证空闲预热池能够收缩到 minReplicas,否则预热池会停留在 minReplicas 之上,空闲资源无法回收到预期下限。判定方法是检查最后一步缩容:当预热池副本数为 minReplicas + 1 时,上水位必须不大于 minReplicas,这一步缩容才能触发。
绝对值目标
T与解析后的容差D(含默认容差):需满足T + D <= minReplicas。满足时,空闲预热池的稳定规模就是minReplicas。百分比目标
p%与百分比容差q%(含默认容差):需满足p + q <= 100 × minReplicas / (minReplicas + 1)。百分比水位随预热池缩小而降低,空闲时会逐步收敛到minReplicas。百分比目标配绝对容差
D:在minReplicas + 1个副本处评估,需满足ceil((minReplicas + 1) × p%) + D <= minReplicas。绝对目标
T配百分比容差q%:容差按ceil(T × q%)解析,需满足T + ceil(T × q%) <= minReplicas。
常见配置的效果如下:
minReplicas | targetAvailable | tolerance | 在 minReplicas+1 个副本处的上水位 | 效果 |
1 |
| 默认( | 1 | 可从 2 个副本缩到 1 个 |
1 |
| 默认( | 2 | 上水位为 2,停留在 2 个副本 |
1 |
|
| 1 | 固定保底 1 个可用 Sandbox |
1 |
| 默认( | 2 | 默认容差将上水位抬高到 2,停留在 2 个副本 |
2 |
| 默认( | 2 | 可从 3 个副本缩到 2 个(即场景一示例) |
1 |
| 任意(含 |
| 可用数最多等于副本数,永不高于上水位,空闲池永不缩容 |
4 |
|
| 4 | 可从 5 个副本缩到 4 个 |
场景一演示了百分比目标的配置方式:水位随池规模弹性伸缩,适合负载波动的业务。需要固定规模的预热池时,可改用绝对值目标并设置 tolerance: 0,同时让 minReplicas 不小于目标值。无论哪种方式,都请按上述规则核对 minReplicas。
如果预热池长期停留在高于 minReplicas 的规模且 status.conditions 无异常,通常是上述规则未满足:此时可调低 targetAvailable 或 tolerance,或调高 minReplicas,然后观察 status.desiredReplicas 与 status.currentCapacity.available 是否逐步收敛。
参数配置约束说明
创建或更新 PoolAutoscaler 时,Webhook 会校验以下规则;违反时请求被拒绝(HTTP 422)并返回具体原因。
通用约束
字段 | 约束 |
| 仅支持 SandboxSet。 |
| 必填,指向同命名空间内已存在的 SandboxSet;当 SandboxSet 不存在时,创建不会拦截,仅产生 |
| 必填且大于 0。 |
| 大于等于 0,且不能大于 |
| 至少配置一项,否则没有任何策略驱动扩缩容。 |
同命名空间内唯一性 | 一个 SandboxSet 只能由一个 PoolAutoscaler 管理。 |
容量策略约束
字段 | 约束 |
| 绝对值必须 |
| 必须同时设置 |
| 格式约束同 |
| 不设置时默认 60 秒;显式设置必须在 60 到 3600 秒之间。 |
| 不设置时默认 300 秒;显式设置必须在 60 到 3600 秒之间。建议将缩容稳定窗口设置得长于扩容稳定窗口(默认已保持 300 秒对 60 秒的关系):快速扩容可及时补齐预热池、保障领取延迟,缓慢缩容可避免流量瞬时回落时频繁回收预热池,保证集群整体容量稳定。 |
缩容可达性虽然不是当前版本的硬性校验,但配置不当会导致预热池无法缩至 minReplicas,建议按本文确保空闲预热池能收缩到 minReplicas 的规则核对。
cronPolicies 的校验规则(最多 20 条、name 唯一、五段合法 Cron 表达式、合法时区、targetReplicas >= 0)已在本文CRD 字段说明中标注,此处不再重复。
CRD 字段说明
PoolAutoscaler 是 Agent Sandbox 提供的自定义资源定义(Custom Resource Definition,CRD),本节说明其字段的含义与约束。
字段 | 说明 |
| 待管理的 SandboxSet 引用; |
| 预热池副本下限和上限。 |
| 目标可用 Sandbox 数,可填绝对值或百分比,例如 |
| 目标允许偏差,可填绝对值或百分比;未设置时默认为 |
| 扩容稳定窗口,即连续两次扩容之间的最小间隔。显式设置范围为 60 到 3600 秒,默认 60 秒。 |
| 缩容稳定窗口,即连续两次缩容之间的最小间隔。显式设置范围为 60 到 3600 秒,默认 300 秒。建议长于扩容稳定窗口,避免快速缩容导致预热池容量抖动。 |
| 定时策略列表,最多 20 条,Webhook 校验: |
| 设为 |
| 目标 SandboxSet 最近观测到的当前副本数。 |
| PoolAutoscaler 最近计算出的期望副本数。 |
| 最近观测到的可用 Sandbox 数量。 |
|
|
| 每条 Cron 策略最近一次成功执行的时间。 |