Volcano 基准测试脚本体系全解:从集群搭建、拓扑模拟到微秒级调度延迟采集
【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano
导读
本文聚焦 Volcano 仓库 benchmark/scripts 下的 Shell 脚本体系,它构成了 Volcano 性能基准测试框架的可执行主干:通过Makefile统一编排,覆盖 Kind/KWOK 模拟集群的创建、Volcano 与监控组件安装、Gang/Pod 两类调度场景的压测执行、审计日志导出(audit-exporter)与 Prometheus 指标报表采集,以及一键清理。读完本文,你将能完整复现一套针对 Volcano 调度器的基准测试环境,理解每个脚本的职责、输入输出与调用链,并掌握 microsecond 级调度延迟与 Pod 时间戳回退两种指标采集方案。
一、脚本全景:11 个脚本的职责与调用关系
benchmark/scripts/README.md 以一张表格概括了整个脚本体系。下表逐行说明各脚本的职责及对应的 Make 目标(调用方):
| 脚本 | 职责 | 调用方 |
|---|---|---|
common.sh | 共享环境变量、日志函数、require_cmd、wait_for_deployment | 被所有脚本 source |
create-cluster.sh | 创建 Kind 集群,启用审计日志与 NodePort 映射 | make create-cluster |
create-kwok-nodes.sh | 安装 KWOK 控制器并创建模拟节点 | make create-nodes |
build-images.sh | 构建 audit-exporter 镜像并加载进 Kind 集群 | make build-images |
install-volcano.sh | 通过 Helm 安装 Volcano(本地源码或发布版 Chart) | make install-volcano |
install-monitoring.sh | 部署 Prometheus、Grafana、kube-state-metrics、audit-exporter | make install-monitoring |
run-tests.sh | 应用调度器配置、执行 Go 测试、自动采集报表 | make test-config、make test-gang-env |
collect-report.sh | 从 Prometheus 查询 audit-exporter 指标,写 JSON 报表 | run-tests.sh调用;make report |
export-grafana-charts.sh | 通过 Render API 将 Grafana 面板导出为 PNG | make export-charts |
cleanup.sh | 拆除 VCJob、监控、Volcano、KWOK;可选删除集群 | make cleanup、make cleanup-all |
create-hypernodes.sh | 为拓扑感知调度创建 HyperNode CR(在 Volcano 安装后执行) | make create-hypernodes |
cleanup-kwok-nodes.sh | 删除 KWOK 节点与 HyperNode(cleanup.sh的子任务) | cleanup.sh |
这些脚本并非各自孤立,而是按照 benchmark/Makefile 中的目标组织成一条完整流水线:make setup依次执行集群创建→镜像构建→KWOK 节点→Volcano 安装→监控安装(各步骤均可通过USE_EXISTING_CLUSTER、SKIP_KWOK、SKIP_INSTALL_VOLCANO、SKIP_INSTALL_MONITORING跳过),随后make test-gang-env/make test-pod-env/make test-config触发压测。
二、shared 基础:common.sh 的统一设施
common.sh是整个脚本体系的“公共底座”,被所有脚本通过source "$(dirname "$0")/common.sh"引入。它提供了四类设施:
1. 环境变量默认值:所有可调参数都在这里统一收敛,例如CLUSTER_NAME=volcano-benchmark、KWOK_NODE_COUNT=100、CPU_PER_NODE=32、MEMORY_PER_NODE=256Gi、KWOK_VERSION=v0.7.0,以及现有集群模式开关USE_EXISTING_CLUSTER、SKIP_INSTALL_VOLCANO、SKIP_INSTALL_MONITORING、SKIP_KWOK等(见 common.sh)。
2. 路径解析:脚本通过BASH_SOURCE推算出BENCHMARK_DIR(benchmark 根目录)与VOLCANO_ROOT(仓库根目录),从而保证脚本无论从哪个目录被调用都能正确定位配置、清单与 Helm Chart。
3. 日志函数:log_info/log_warn/log_error输出带时间戳的[INFO]、[WARN]、[ERROR]前缀,其中 warn 与 error 走 stderr。
4. 工具函数:require_cmd校验必需命令是否存在(缺失即退出);wait_for_deployment通过kubectl rollout status等待 Deployment 就绪;wait_for_pods_ready通过kubectl wait --for=condition=Ready等待 Pod 就绪(见 common.sh)。
三、环境搭建脚本:集群、节点、镜像与组件安装
3.1 create-cluster.sh:Kind 集群与审计日志
create-cluster.sh负责创建 Kind 集群,关键点在于:
- 渲染 Kind 配置:用
sed将 config/kind-config.yaml 中的__VOLCANO_ROOT__占位符替换为仓库绝对路径(Kind 要求 hostPath 为绝对路径),生成config/.kind-config.rendered.yaml; - 审计日志目录预创建:预先创建
benchmark/logs/,确保 apiserver 审计日志挂载首次启动即成功; - 集群生命周期管理:若同名集群已存在则先删除再创建;创建完成后将 kubeconfig 导出到
benchmark/kubeconfig并等待全部节点 Ready(见 create-cluster.sh)。
3.2 create-kwok-nodes.sh:KWOK 模拟节点与拓扑域
KWOK(Kubernetes WithOut Kubelet)用于低成本模拟大规模节点。create-kwok-nodes.sh的执行逻辑为:
- 检测
kwok-controllerDeployment 是否已存在,不存在则按KWOK_VERSION下载并应用 KWOK 的 CRD、控制器与stage-fast.yaml; - Flat 模式(默认):创建
KWOK_NODE_COUNT个节点,每个节点带有type: kwok标签、kwok.x-k8s.io/node=fake注解、NoSchedule污点,以及通过CPU_PER_NODE/MEMORY_PER_NODE指定的容量(见 create-kwok-nodes.sh); - Topology 模式(
ENABLE_TOPOLOGY=true):按 spine→rack 两级拓扑域均匀分布节点,并打上topology-rack、topology-spine标签;节点数与域配置的对应关系为nodes_per_rack = KWOK_NODE_COUNT / TOPOLOGY_RACKS、racks_per_spine = TOPOLOGY_RACKS / TOPOLOGY_SPINES(见 create-kwok-nodes.sh); - 自定义标签:
KWOK_NODE_LABELS支持逗号分隔的key=value,会附加到所有节点上,用于配合 hypernode-controller 的自动发现模式(例如KWOK_NODE_LABELS="topology-rack=rack-0,topology-spine=spine-0,gpu=A100")。
脚本内置幂等保护:若现有type=kwok节点数已满足需求则直接跳过创建。
3.3 build-images.sh:镜像构建策略
build-images.sh按两种模式构建镜像:
- 默认(发布版):仅构建 audit-exporter 镜像(该镜像未发布到 DockerHub),随后
kind load docker-image载入 Kind 集群; BUILD_VOLCANO=true(本地源码):在仓库根目录执行make images构建vc-scheduler、vc-agent-scheduler、vc-controller-manager、vc-webhook-manager等全部 Volcano 组件镜像,并逐一加载进 Kind(见 build-images.sh)。
Dockerfile 位于 manifests/audit-exporter/Dockerfile,构建上下文为仓库根目录。
3.4 install-volcano.sh:双模式安装与调度器调参
install-volcano.sh支持两种安装模式:
--release <version>:从官方 Helm 仓库安装指定版本(如v1.14.2),并启用agent_scheduler_enable=true、scheduler_config_file=volcano-scheduler-configmap;--local:直接使用仓库内 installer/helm/chart/volcano 本地 Chart 安装,适合验证未发布的源码改动。
安装前脚本会先清理历史残留:删除所有volcano.sh后缀的 CRD、卸载已存在的 Helm release(见 install-volcano.sh)。此外还支持通过--scheduler-config在安装后应用自定义调度器配置并滚动重启volcano-scheduler。
值得关注的是安装时会注入custom.scheduler_kube_api_qps/burst与custom.controller_kube_api_qps/burst四个 Helm 参数,默认值分别为 5000/10000,用于在压测前放大 Volcano scheduler 与 controller-manager 访问 Kubernetes API 的 QPS/Burst 上限,避免客户端限流成为基准测试瓶颈(见 install-volcano.sh)。
3.5 install-monitoring.sh:监控栈与自定义仪表盘
install-monitoring.sh依次完成:
- 应用 installer/volcano-monitoring.yaml 部署 Prometheus、kube-state-metrics 与 Grafana;
- 将 manifests/monitoring/grafana-dashboard.json 作为 ConfigMap 挂载到 Grafana 的
/var/lib/grafana/dashboards/benchmark(通过 strategic patch 实现); - 应用 manifests/audit-exporter/daemonset.yaml 部署 audit-exporter DaemonSet——Prometheus 通过
installer/volcano-monitoring.yaml中已有的kubernetes-service-endpoints抓取任务自动发现它,无需额外改动 Prometheus 配置; - 使用
wait_for_deployment依次等待各组件就绪(见 install-monitoring.sh)。
若AUDIT_EXPORTER_IMAGE被自定义,脚本会用sed替换 DaemonSet 清单中的默认镜像名,支持私有仓库场景。
四、压测执行:run-tests.sh 与测试用例源码
4.1 run-tests.sh 的工作流
run-tests.sh是压测的统一入口,用法为run-tests.sh <scenario> --config=<profile.yaml>,核心流程如下:
- 配置解析:
--config=指定 YAML 配置;--template=则用envsubst将模板中的$JOBS、$REPLICAS、$MIN_AVAILABLE、$PODS、$SCHEDULER_NAME等变量渲染为临时配置(见 run-tests.sh); - Prometheus 探测:记录测试开始前的 Prometheus 时间戳(
time()查询),若 Prometheus 不可达则跳过 audit-exporter 报表(PROM_AVAILABLE=false); - 执行 Go 测试:
cd到仓库根目录执行go test -count=1 -v -timeout 1800s "./benchmark/testcases/<scenario>/..." -run TestFromConfig,输出以tee写入results/test-<scenario>-<时间戳>.log; - 自动采集报表:测试结束后等待 10 秒供 Prometheus 抓取,再以
--before/--after两个时间戳调用collect-report.sh(见 run-tests.sh)。
4.2 Gang 场景的测试源码剖析
Gang 场景测试代码位于 benchmark/testcases/gang/gang_test.go,其结构可作为“新增场景”的参照模板:
VCJobConfig/TaskConfig结构体完整定义了任务模板可配置项:命名空间、MinAvailable、队列名、Job/Task 两级网络拓扑、分区策略、节点选择器等(见 gang_test.go);BuildVCJob基于cases/vcjob-template.yaml用text/template渲染出batch.volcano.sh/v1alpha1的 Job 对象,并为空字段应用默认值(镜像busybox:1.36、命令/bin/sh -c sleep 30,见 constant.go);CreateGangJobs通过workqueue.ParallelizeUntil以BENCHMARK_CREATE_CONCURRENCY(默认 16)并发提交指定数量的 VCJob;RunGangTest依次等待“全部 Pod 创建完成”(5 分钟)与“全部 Pod 被调度”(10 分钟),两个等待分别对应创建吞吐与调度吞吐的验证。
4.3 YAML 配置文件示例
以 testcases/gang/cases/comprehensive.yaml 为例,配置文件同时演示了 Job 级与 Task 级的完整参数,包括:
jobs: 5 jobTemplate: name: gang-comprehensive minAvailable: 10 queue: default # job 级网络拓扑配置 enableNetworkTopology: false networkTopologyMode: hard tasks: - name: master replicas: 1 image: busybox:1.36 cpu: 100m memory: 100Mi enableNodeSelector: false - name: worker replicas: 10 image: busybox:1.36 command: ["/bin/sh", "-c", "sleep 30"] cpu: 50m memory: 50Mi # task 级分区策略(拓扑分组) enablePartitionPolicy: false partitionTotalPartitions: 2 partitionSize: 5 # task 级网络拓扑配置 enablePartitionNetworkTopology: false partitionNetworkMode: soft enableNodeSelector: false五、指标采集:audit-exporter 报表与 Pod 时间戳回退
5.1 collect-report.sh:微秒级延迟报表
collect-report.sh从 Prometheus 查询 audit-exporter 暴露的指标并生成 JSON 报表,其实现有三个亮点:
- 直方图分位数计算:为避免短时间窗下
increase()外推误差,脚本在--before/--after两个时间点分别查询sum by (le) (pod_scheduling_latency_seconds_bucket{namespace="default"}),用 jq 做桶差分后线性插值出 P50/P90/P99(见 collect-report.sh);未提供时间戳时回退到histogram_quantile+increase(...[10m]); - 调度吞吐计算:直接解析本机 apiserver 审计日志文件,筛选
ResponseComplete+create pods/binding+ HTTP 2xx 事件,按stageTimestamp落在时间窗内的数量除以时间窗长度得到“pods/sec”(见 collect-report.sh); - 报表输出:生成
results/report-<时间戳>.json,包含时间窗、P50/P90/P99(秒)、调度总数、吞吐量、Grafana 与 Prometheus 地址,并同时在终端以毫秒打印结果(见 collect-report.sh)。
5.2 两种延迟采集方案的取舍
框架提供两条延迟采集路径:
| 方案 | 精度 | 前置条件 | 适用场景 |
|---|---|---|---|
| audit-exporter(推荐) | 微秒级(metav1.MicroTime) | apiserver 开启审计日志 + 镜像已构建 | 精确延迟分析,Pod 可即时清理 |
| Pod 时间戳回退 | 秒级(metav1.Time) | DRY_RUN=true保留 Pod | 调试、未开启审计日志的环境 |
audit-exporter 之所以被推荐,原因有二:审计事件携带MicroTime精度(而 Pod 对象上的metav1.Time只有秒级);同时pods/binding是通用绑定入口,与具体调度器无关——无论 Pod 由 Volcano、agent-scheduler 还是其他调度器绑定,都能被统计。而 Pod 时间戳方案的局限在于亚秒级延迟会显示为 0ms,且必须搭配DRY_RUN=true使 Pod 在采集时仍然存活。
5.3 启用 apiserver 审计日志(微秒级方案前置)
若在现有集群上使用 audit-exporter,需为 kube-apiserver 增加以下启动参数:
--audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml --audit-log-path=/var/log/kubernetes/kube-apiserver-audit.log --audit-log-maxsize=10240 --audit-log-maxage=7 --audit-log-maxbackup=3审计策略文件位于 third_party/kube-apiserver-audit-exporter/audit-policy.yaml。对于 kubeadm 集群,编辑控制平面节点上的/etc/kubernetes/manifests/kube-apiserver.yaml,在command、volumeMounts与volumes中分别加入审计策略文件与日志目录的挂载,kubelet 会自动重启 apiserver 静态 Pod 完成生效。
5.4 可观测指标一览
框架的指标来自三个来源:
- audit-exporter(调度器无关的微秒级延迟),核心指标包括:
pod_scheduling_latency_seconds(Histogram):Pod 创建到pods/binding创建的时间,user标签标识调度器;batchjob_completion_latency_seconds(Histogram):Job 创建到完成的时间(涵盖batch.Job与batch.volcano.sh/Job);api_requests_total、pod_deleted_total、pod_completed_total(Counter)等;
- Volcano 内部指标:
volcano_session_*、volcano_plugin_*、volcano_action_*等,例如volcano_e2e_job_scheduling_latency_milliseconds(Job 从创建到最后一个 task 被 assume 的时长)、volcano_worker_scheduling_cycle_duration_milliseconds(agent worker 单次调度周期)等; - kube-state-metrics:Pod/Job 生命周期计数。
服务通过 NodePort 暴露:Prometheus:30003,Grafana:30004(admin/admin),仪表盘地址为/d/volcano-benchmark。
六、拓扑感知调度:HyperNode 的创建与三种接线方式
6.1 create-hypernodes.sh 的实现
create-hypernodes.sh在 Volcano 安装完成后执行(前置校验hypernodes.topology.volcano.shCRD 是否存在),按TOPOLOGY_RACKS×TOPOLOGY_SPINES生成两级 HyperNode(见 create-hypernodes.sh):
- Tier-1(rack):每个 rack 一个 HyperNode,通过
labelMatch选择带type: kwok与topology-rack=rack-<i>标签的节点; - Tier-2(spine):每个 spine 一个 HyperNode,通过
exactMatch引用其下属 rack HyperNode。
关键约束:执行时传入的TOPOLOGY_RACKS/TOPOLOGY_SPINES必须与create-kwok-nodes.sh阶段保持一致,否则 HyperNode 的 labelSelector 无法匹配对应节点。
6.2 三种拓扑接线方式
- KWOK 模拟拓扑(默认):
ENABLE_TOPOLOGY=true建节点 → 安装 Volcano →make create-hypernodes建 CRD; - 真实节点自定义拓扑:给真实节点打
topology-rack标签后创建对应 HyperNode。由于脚本的 rack labelSelector 固定包含type: kwok,真实节点需自行补充该标签,或直接手写 HyperNode 清单(如 benchmark/README.md 中topology.volcano.sh/v1alpha1的HyperNode示例); - hypernode-controller 自动发现:仅需给节点打
topology-rack、topology-spine标签,控制器会根据 Volcano ConfigMap 中的 label discoverer 配置自动创建 HyperNode——这要求在使用 create-kwok-nodes.sh 时通过KWOK_NODE_LABELS注入拓扑标签。调度器使用虚拟ClusterHyperNode作为全局根节点,因此只需 rack(tier 1)与 spine(tier 2)两级,无需显式根节点。
七、清理:cleanup.sh 的幂等拆除
cleanup.sh提供两级清理粒度(见 cleanup.sh):
make cleanup:仅清理测试资源(按标签volcano.sh/benchmark=true删除 VCJob 与裸 Pod、删除 PodGroup)、监控栈、KWOK 节点(调用cleanup-kwok-nodes.sh --all)、Volcano(Helm uninstall + 删除 CRD)及本地产物(bin、results、logs、渲染配置);make cleanup-all:在 cleanup 基础上执行kind delete cluster删除整个 Kind 集群(USE_EXISTING_CLUSTER=true时明确跳过,绝不删除外部集群)。
每个子项都遵循SKIP_*开关:SKIP_INSTALL_MONITORING=true时跳过监控清理、SKIP_KWOK=true时跳过 KWOK 清理、SKIP_INSTALL_VOLCANO=true时跳过 Volcano 清理,保证与搭建阶段的选择严格对称。
八、参数速查与两种运行模式
8.1 全局变量速查
| 变量 | 默认值 | 说明 |
|---|---|---|
CLUSTER_NAME | volcano-benchmark | Kind 集群名 |
USE_EXISTING_CLUSTER | false | 跳过 Kind 建集群与镜像构建,使用现有 kubeconfig |
SKIP_INSTALL_VOLCANO | false | 跳过 Volcano 安装(使用集群中已装版本) |
SKIP_INSTALL_MONITORING | false | 跳过监控栈安装 |
SKIP_KWOK | false | 跳过 KWOK 安装与节点创建;运行测试时也需传入以剔除模板中的 KWOKnodeSelector/tolerations |
AUDIT_EXPORTER_IMAGE | volcanosh/kube-apiserver-audit-exporter:dev | audit-exporter 镜像(私有仓库需覆盖) |
KUBECONFIG | ~/.kube/config | kubeconfig 路径 |
KWOK_NODE_COUNT | 100 | KWOK 节点数 |
CPU_PER_NODE | 32 | 每节点 CPU |
MEMORY_PER_NODE | 256Gi | 每节点内存 |
KWOK_VERSION | v0.7.0 | KWOK 控制器版本 |
VOLCANO_VERSION | 空 | Helm 仓库安装的发布版标签(如v1.14.2) |
VOLCANO_*_KUBE_API_QPS/BURST | 5000/10000 | Volcano scheduler/controller 的 API 客户端限流 |
PROM_URL | http://localhost:30003 | Prometheus 地址 |
DRY_RUN | false | 跳过测试后清理(调试或 Pod 时间戳采集) |
Gang 场景参数:JOBS(默认 10)、REPLICAS(默认 100)、MIN_AVAILABLE(默认 100);Pod 场景参数:PODS(默认 500)、SCHEDULER_NAME(默认agent-scheduler)。完整参数(网络拓扑、分区策略、节点选择器等)见 testcases/gang/cases/comprehensive.yaml 与 testcases/pod/cases。
8.2 典型使用流程
Kind 本地集群快速验证:
cd benchmark make setup VOLCANO_VERSION=v1.14.2 # 建集群 + 装 Volcano + 装监控 make test-gang-env JOBS=10 REPLICAS=100 MIN_AVAILABLE=100 make cleanup-all现有集群(裸金属/云托管/自建多节点):
make setup USE_EXISTING_CLUSTER=true SKIP_INSTALL_VOLCANO=true SKIP_INSTALL_MONITORING=true kubectl port-forward svc/prometheus-service -n volcano-monitoring 30003:8080 & make test-gang-env SKIP_KWOK=true JOBS=10 REPLICAS=100 MIN_AVAILABLE=100无审计日志时的延迟回退采集:
DRY_RUN=true make test-gang-env JOBS=10 REPLICAS=100 MIN_AVAILABLE=100 make collect-pod-latency # 结果写入 results/pod-latency-<时间戳>.json make clean-vcjobs # 清理残留8.3 新增测试场景的步骤
框架支持通过以下三步扩展新场景(见 benchmark/README.md 的 "Adding New Scenarios"):
- 创建
testcases/<scenario>/config/,放入scheduler-config.yaml与queue.yaml; - 创建
testcases/<scenario>/*_test.go实现测试逻辑(可参照 gang_test.go 的TestFromConfig约定); - 运行
make setup && make test-config SCENARIO=<scenario> CONFIG=<profile>.yaml。
结语
从common.sh的公共设施,到create-cluster.sh/create-kwok-nodes.sh/install-volcano.sh/install-monitoring.sh的环境搭建四件套,再到run-tests.sh与collect-report.sh组成的“压测+报表”闭环,Volcano 的 benchmark 脚本体系用一组职责单一、可组合、可跳过的脚本,把“在任意规模的模拟集群上量化调度器性能”这件事做成了标准流水线。理解这套脚本,不仅能直接复现本文所述的两类调度场景压测,也能为你自己的调度器性能验证与指标埋点方案提供现成参考。
【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考