帮你快速理解、总结文档立即下载
文档中心>Agent Runtime>Agent 集群>实践教程>测试 Agent 工作负载启动性能

测试 Agent 工作负载启动性能

最近更新时间:2026-10-16 16:50:30
本文档已由 AI 辅助审校
我的收藏
批量创建代码执行环境、扩容办公助手或启动 RL Rollout 任务前,可以先测试 Agent 集群的工作负载启动速度。本教程在同一个计算节点上依次完成预热、串行启动和并行启动测试,比较单个 Pod 的启动延迟、整批就绪时间和运行稳定性。
测试使用配套工具创建模拟 Agent 应用的 Pod,工具已提供可直接使用的镜像和脚本。完成后,您将得到两组可对比的结果,以及每轮测试的配置、日志和事件文件。

测试范围与指标

默认工作负载在普通 Linux 容器中执行 sleep infinity,以 Pod 进入 Ready 状态作为启动完成信号。它用于测量轻量工作负载的启动基线,不包含业务初始化、真实 LLM 请求或任务完成时间。
测试
Pod 数量
提交速率
最多同时提交的创建请求数
用途
预热
1
1 QPS
1
准备镜像与运行环境,不计入正式结果。
串行启动
16
1 QPS
1
建立逐个提交工作负载时的基线。
并行启动
16
16 QPS
16
观察批量启动时的整体耗时与尾延迟。
串行测试是逐个发出创建请求,并不等待前一个 Pod 完成业务或退出。并行测试约在 1 秒内提交 16 个 Pod,也不是所有请求在同一瞬间发出。
重点比较以下指标:
单 Pod 启动延迟:从开始创建 Pod,到测试工具首次观察到该 Pod Ready,记录 P50、P95、P99 和最大值。
整批就绪时间:从批次开始到全部 Pod 就绪,包含按配置速率提交请求的时间。
成功率与稳定性:创建、调度、容器启动和就绪数量是否齐全,以及就绪后 10 秒观察期内是否重启或丢失就绪状态。
计时在集群内的测试工具中完成。Scheduled、ContainersStarted 和 Ready 均是通过 Watch/List 观察到的状态时间,因此结果包含控制面、调度和状态传播的影响,不能当作 Cube 内部沙箱创建接口的纯执行耗时。

开始前准备

使用专用测试集群或隔离测试节点。工具会创建测试命名空间、权限和 RuntimeClass,并为测试工具运行节点添加标签及 NoSchedule 污点;同一集群不要同时运行多套该测试。
通过控制台准备集群和节点池,操作请参见 创建集群和节点池。本教程需要两个不同的节点:一个运行被测工作负载,另一个运行测试工具。
项目
要求
目标节点
状态为 Ready,已启用 Cube 运行时,具有 agc.cloud.tencent.com/cube-ready=true 标签;Kubernetes 可分配 CPU 不低于 16 核。
目标节点剩余容量
能同时容纳 16 个测试 Pod。默认每个 Pod 申请 512m CPU 和 512Mi 内存,还需留出系统开销、临时存储、Pod 槽位、Pod IP 和运行时资源。
测试工具运行节点
状态为 Ready,与目标节点不同;至少剩余 16100m CPU 和约 5 GiB 内存。
操作机
使用能连接集群 API 的 Linux 主机,安装 Bash、Git、kubectl、jq、Mike Farah yq v4 及 GNU coreutils(包含 sha256sum)。
操作权限
使用测试集群管理员身份,允许创建测试资源、权限和 RuntimeClass,以及修改测试工具运行节点标签与污点。
镜像访问
目标节点能拉取工作负载镜像,测试工具运行节点能拉取工具中固定 digest 的测试工具镜像。
标签用于检查已经安装好的运行环境,不要手工补上标签来替代运行时安装。连接配置获取方法请参见 通过 Kubernetes API 访问 Agent 集群。

第一步:下载并校验工具

工具位于 ags-cookbook 的 performance-test-tools 目录,包含运行脚本、清理脚本、工作负载清单和校验文件。本文固定使用 cube-cri-performance-test-tools-v1.0.17 对应的仓库提交,便于重复测试时保持工具一致。
在操作机的 Bash 终端中执行。后续步骤继续使用同一终端,以保留参数和每轮测试 ID。
git clone https://github.com/TencentCloudAgentRuntime/ags-cookbook.git agc-performance-cookbook
cd agc-performance-cookbook
git checkout --detach 46619b344e56b25b317ff7367ee72201f5af7f14
export SCALE_LOAD_DIR="$PWD/benchmarks/agent-cluster/performance-test-tools"
export RESULT_ROOT="$PWD/_output/agc-startup-performance"
检查工具和依赖:
kubectl version --client
jq --version
yq --version
cat "$SCALE_LOAD_DIR/VERSION"
chmod +x "$SCALE_LOAD_DIR/run.sh" "$SCALE_LOAD_DIR/cleanup.sh"
bash -n "$SCALE_LOAD_DIR/run.sh" "$SCALE_LOAD_DIR/cleanup.sh" "$SCALE_LOAD_DIR/sop-functions.sh"
(cd "$SCALE_LOAD_DIR" && sha256sum -c SHA256SUMS)
test -r "$SCALE_LOAD_DIR/manifests/cube-cri-load-simple-pod.yaml"
test -r "$SCALE_LOAD_DIR/manifests/cube-cri-load-runtimeclass.yaml"
确认校验项全部为 OK 后继续。校验失败时重新取得相同提交的完整工具目录,不修改校验文件跳过检查。测试工具以容器镜像交付,脚本已固定其 digest,无需本地构建。

第二步:设置参数并检查节点

替换 kubeconfig 路径及两个节点名称。工作负载镜像需要包含 sleep 命令,并与节点架构兼容;两组测试使用相同镜像。进行多轮或跨日期比较时,建议固定镜像 digest。
export KUBECONFIG='/absolute/path/to/kubeconfig'
export TARGET_NODE='REPLACE_WITH_TARGET_NODE'
export GENERATOR_NODE='REPLACE_WITH_GENERATOR_NODE'
export LOAD_IMAGE='mirror.ccs.tencentyun.com/library/ubuntu:24.04'
export TEST_PODS=16
export SNAPSHOTTER_PROFILE=overlayfs

kubectl config current-context
kubectl cluster-info
kubectl get nodes -o wide
kubectl get node "$TARGET_NODE" "$GENERATOR_NODE" -L agc.cloud.tencent.com/cube-ready
kubectl describe node "$TARGET_NODE"
kubectl describe node "$GENERATOR_NODE"
在节点详情中检查 Allocatable、Allocated resources 和现有 Pod,确认剩余资源满足上表要求。节点标称规格不等于可分配资源,可分配资源也不等于尚未使用的资源。
执行以下检查;任意一项不通过时,先处理节点选择或权限问题,不继续运行测试:
if [[ "$TARGET_NODE" == "$GENERATOR_NODE" ]]; then
echo '目标节点和测试工具运行节点不能相同。' >&2
elif [[ "$(kubectl auth can-i '*' '*')" != yes ]]; then
echo '当前身份没有测试集群管理员权限。' >&2
else
echo '节点选择和管理员权限检查通过,请继续核对节点资源及运行环境。'
fi
初始化测试命令:
source "$SCALE_LOAD_DIR/sop-functions.sh"

第三步:预热

使用与正式测试相同的工作负载模板和镜像,运行一个 Pod。就绪后观察 10 秒,成功后自动清理该轮资源,结果单独保存在本地。
run_warmup_test
看到 Warm-up succeeded. 后再进行正式测试。预热失败时停止,按输出中的目录保存和检查诊断材料。更换目标节点、镜像或工作负载类型后,需要重新预热。
本教程比较预热后的启动表现,不将结果写成首次拉取镜像时的冷启动性能。正式轮次的镜像状态标记不能代替预热步骤。

第四步:串行启动测试

默认工作负载使用 cube-load RuntimeClass,在目标节点上执行 sleep infinity,每个 Pod 的 CPU、内存 requests 与 limits 均为 512m、512Mi。工具自动生成命名空间和唯一 Pod 名称,无需手工修改或提交清单。
按 1 QPS、1 worker 提交 16 个 Pod:
run_serial_test "$TEST_PODS"
成功时会输出摘要并自动清理本轮集群资源,本地结果保留。检查 count、created、scheduled、containersStarted、ready 是否均为 16,随后记录延迟分位值、整批就绪时间、重启与 Warning 情况。
需要再次查看本轮结果时执行:
show_result "$SERIAL_RUN_ID"
确认本轮成功并完成清理后,再进入并行测试。失败时先排查,不跳过失败轮次继续扩大压力。

第五步:并行启动测试

保持目标节点、工作负载镜像和类型不变,确认节点容量已经释放,再执行:
run_parallel_test "$TEST_PODS"
该命令令 count=qps=workers=16,在约 1 秒内提交 16 个 Pod。workers 表示最多同时提交的创建请求数,实际值取决于请求完成速度。成功时同样会输出结果并清理该轮资源。
重新查看结果:
show_result "$PARALLEL_RUN_ID"

第六步:比较结果

show_result 会先校验结果文件的完整性,再输出便于阅读的摘要。按下面的对应关系记录串行与并行两组结果:
检查项
摘要中的字段
如何解读
创建和就绪数量
count、created、scheduled、containersStarted、ready
对照计划数量,不能只统计成功样本而忽略失败任务。
单 Pod 启动耗时
latencyMs.createToReady
记录 P50、P95、P99 和最大值,单位毫秒。
整批环境就绪
batchMs.allReady
包含按速率提交请求的时间,适合衡量整批资源何时可用。
实际请求速率
actualRequestWriteQPS
核对压力是否接近配置速率。
稳定性
restartCount、readyLost
结合 10 秒稳定观察期判断是否存在重启或就绪丢失。
告警与错误
warnings、errors
查看原因和受影响 Pod;最终成功也可能伴随过程中发生的 Warning。
工具判定
success、accepted、slo
同时查看是否配置延迟阈值,不能只凭 accepted=true 推导达到某个速度。
默认教程命令不启用正值延迟 SLO。需要按业务目标判定时,在正式测试前设置 READY_P99_SLO_MS 为所需毫秒阈值,并在结果中核对 slo。该阈值是本次测试目标,不是产品 SLA。

原 SOP 的输出示例

以下仅用于说明如何比较结果,来自原 SOP 的示例输出,不是本次教程新增的实测结果,也不是固定达标值。
检查项
串行:16 Pod,1 QPS
并行:16 Pod,16 QPS
就绪数量
16 / 16
16 / 16
Create → Ready P50
约 325 毫秒
约 410 毫秒
Create → Ready P95 / P99
约 357 / 357 毫秒
约 1295 / 1295 毫秒
Create → Ready 最大值
约 357 毫秒
约 1295 毫秒
整批全部就绪
约 15.34 秒
约 2.23 秒
重启 / 就绪丢失次数
0 / 0
0 / 0
Warning
0
1,原因为 FailedCreatePodSandBox
串行组的整批时间包含约 15 秒的分批提交间隔;并行组更早提交完全部 Pod,因此整批就绪更快,但单 Pod 的尾延迟可能增加。这是同一运行时在两种提交方式下的比较,不能据此推导不同运行时的性能差异。16 个样本的 P99 也不能用于估算大规模长期尾延迟。

保存测试记录

每轮结果位于 $RESULT_ROOT/<run-id>/,重点保存:
文件
用途
batch-summary.json
完整结果摘要;与 show_result 展示结构不同,后者做了字段整理。
run-config.json
本轮节点、镜像、并发、工作负载类型等参数。
pods.jsonl
单 Pod 观测记录。
generator.log
测试工具日志。
warning-events.json
工作负载 Warning 事件。
artifacts.sha256
结果文件校验信息。
同时记录集群及运行时版本、节点规格与架构、测试期间的已有负载和工具版本。需要增加样本量时,在每轮完成清理后重复测试;不要把不同镜像、工作负载类型或缓存条件的样本混在一起。

失败排查与资源清理

现象
优先检查
测试工具 Pod 无法调度
测试工具运行节点剩余 CPU、内存、污点及镜像拉取条件。
工作负载 Pending
目标节点资源、Pod IP、Pod 数量上限、节点选择条件和工作区配置。
FailedCreatePodSandBox
目标节点的 Cube 运行环境、运行时资源和相关事件。
镜像拉取失败
镜像地址、架构、仓库权限和节点网络。
延迟明显增大
镜像是否预热、节点其他负载、实际提交速率及调度和就绪阶段的耗时。
结果校验失败或文件不完整
保留已有目录,检查测试工具退出状态及文件回传,不作为有效性能样本。
提示已有测试资源
先查清资源归属,结束并清理前一轮,不覆盖其他测试。
成功轮次会自动清理;失败、中断或资源残留时,使用对应的精确 run-id 清理。例如清理当前终端中失败的并行轮次:
cleanup_test "$PARALLEL_RUN_ID"
预热和串行轮次分别使用 $WARMUP_RUN_ID、$SERIAL_RUN_ID。终端重开后,从保存的配置或终端记录中取得实际 run-id,重新加载参数与函数后再清理,不猜测或复用 ID。
所有轮次结束且不再有测试 Pod 后,清理共享资源和测试工具运行节点标记:
cleanup_shared_test_resources
工具会检查资源归属和残留 Pod;检查不通过时停止清理,不应通过修改标签绕过。清理后核对测试工具运行节点上的测试标签和污点已经移除。本地 $RESULT_ROOT 不会被删除,集群和节点池也不会被该命令释放;测试环境不再使用时,另按 删除集群 处理。

进阶测试

使用更接近业务的工作负载

默认 simple 类型只有轻量常驻进程。需要观察初始化和健康检查的影响时,使用包含 Node.js 的镜像,并在三步中一致指定 production:
export LOAD_IMAGE='mirror.ccs.tencentyun.com/library/node:22-bookworm-slim'
run_warmup_test --workload-profile production
run_serial_test "$TEST_PODS" --workload-profile production
run_parallel_test "$TEST_PODS" --workload-profile production
以上命令应逐条执行,每一步成功并清理后再继续。该类型包含 init container、主服务、Sidecar、volume、HTTP/TCP 健康检查和 NET_ADMIN,执行前需确认测试环境允许这些权限和资源配置。完整清单位于工具目录的 manifests/cube-cri-load-pod.yaml。
此时 Ready 更接近“服务可以接收请求”,但仍不包含真实模型调用或完整 Agent 任务。其结果应与 simple 分开记录;真正的业务启动指标还需由业务镜像和就绪检查定义。

测试 EROX 镜像加速

基础测试默认使用 overlayfs。测试 EROX 前,先完成镜像加速开通并取得已转换的测试镜像及 digest,请参见 使用镜像加速。将参数替换为实际镜像后重新预热,再依次执行测试:
export SNAPSHOTTER_PROFILE=erox
export LOAD_IMAGE='REPLACE_WITH_EROX_IMAGE@sha256:REPLACE_WITH_DIGEST'
run_warmup_test
run_serial_test "$TEST_PODS"
run_parallel_test "$TEST_PODS"
每一步成功后再继续。切换参数本身不会安装 EROX 或转换镜像。EROX 与 overlayfs 的结果分开记录;镜像身份差异用于诊断,不单独作为该工具的验收条件。

扩大规模

先核算节点剩余资源,再逐级增加 TEST_PODS。默认每个 simple Pod 申请 512m CPU、512Mi 内存和一个 Pod IP,还需检查节点 Pod 数上限及 Cube/NBD 等运行时资源。工具中的 cube-load RuntimeClass 未额外声明资源 overhead,这不代表运行时本身没有资源开销。
每档规模至少重复两轮,保持并行组 count=qps=workers=TEST_PODS。上一档出现失败时先排查;需要更多样本时优先清理后重复测试,不超出单节点剩余承载量。