AI Agent 评测需要对大量任务做隔离运行和结果收集。Harbor CLI 的 ACK 环境将每个任务调度为集群中的独立 Pod,支持 OSS 数据集挂载、镜像预构建和结果自动回收。
Harbor(本文指 AI Agent 评测开源框架,非容器镜像仓库 Harbor)通过harbor run在 ACK 集群中为每个评测任务创建独立的 Trial Pod,数据集预先挂载到 Pod 中,逐任务下发和执行。-n控制并发 Trial 数;-n 1(并发度=1)时逐个创建 Trial Pod,前一个任务完成后才启动下一个。CI/CD 等集群内触发场景中,可用 Kubernetes Job 包装harbor run命令(详见下文使用 K8s Job 编排评测)。
环境准备
安装 Harbor CLI
从 GitHub 克隆仓库并通过 pip 安装:
git clone https://github.com/alibaba/harbor.git
cd harbor
pip install -e .
harbor --version配置 kubeconfig
Harbor ACK 环境通过 kubeconfig 连接集群。执行以下命令验证连接:
kubectl cluster-info指定 context 或 kubeconfig 文件时,在 harbor run 命令中传入对应参数:
--ek context=my-ack-context
# 或
--ek kubeconfig=/path/to/kubeconfig创建评测命名空间
评测相关资源(Trial Pod、Secret、PV/PVC 等)统一放在独立命名空间中:
kubectl create namespace harbor-eval其他工具(可选)
挂载数据集
Trial Pod 是临时创建的,数据集和结果目录需要通过外部存储挂载到 Pod 中。正式评测推荐使用 OSS CSI 静态卷,开发调试可直接指定本地路径。
方案一:OSS CSI 静态卷(推荐)
通过 ACK 的 OSS CSI 插件将 OSS Bucket 中的目录挂载到 Pod。创建两组 PV/PVC:数据集卷以只读方式挂载,结果卷以读写方式挂载。两个 PV 共用同一个包含 AccessKey 的 Secret 进行认证。
首先创建包含 OSS AccessKey 的 Secret,供 PV 挂载时认证:
kubectl create secret -n harbor-eval generic oss-secret \
--from-literal=akId=<YOUR-ACCESS-KEY-ID> \
--from-literal=akSecret=<YOUR-ACCESS-KEY-SECRET>数据集卷(只读):
apiVersion: v1
kind: PersistentVolume
metadata:
name: harbor-dataset-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadOnlyMany
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
volumeHandle: harbor-dataset-pv
volumeAttributes:
bucket: my-harbor-bucket
url: oss-cn-hangzhou-internal.aliyuncs.com
otherOpts: "-o ro"
path: "dataset"
nodePublishSecretRef:
name: oss-secret
namespace: harbor-eval
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: harbor-dataset-pvc
namespace: harbor-eval
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 100Gi
volumeName: harbor-dataset-pv
storageClassName: ""结果卷(可写):
apiVersion: v1
kind: PersistentVolume
metadata:
name: harbor-results-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
volumeHandle: harbor-results-pv
volumeAttributes:
bucket: my-harbor-bucket
url: oss-cn-hangzhou-internal.aliyuncs.com
path: "results"
nodePublishSecretRef:
name: oss-secret
namespace: harbor-eval
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: harbor-results-pvc
namespace: harbor-eval
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
volumeName: harbor-results-pv
storageClassName: ""OSS CSI fuse 挂载点写入需要 root 权限。Job Pod 的 securityContext.runAsUser 必须设为 0。
方案二:本地目录(开发调试)
将数据集放在本地,通过 -p 参数指定路径。Harbor 通过 Kubernetes exec API 将任务文件上传到 Trial Pod,无需额外配置。
预构建镜像
每个评测 Task 都有独立的 environment/Dockerfile 和 task.toml。如果 ACR 中没有预构建镜像,harbor run 会在 Trial Pod 内现场构建,耗时且依赖构建环境。建议提前构建镜像并推送到 ACR。
在集群内部署 BuildKit
集群内通常没有 Docker daemon,需部署 BuildKit 作为远程构建后端:
apiVersion: apps/v1
kind: Deployment
metadata:
name: buildkitd
namespace: harbor-eval
spec:
replicas: 1
selector:
matchLabels:
app: buildkitd
template:
metadata:
labels:
app: buildkitd
spec:
containers:
- name: buildkitd
image: moby/buildkit:v0.15.0
args:
- --addr
- tcp://0.0.0.0:1234
- --config
- /etc/buildkit/buildkitd.toml
securityContext:
privileged: true
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: "2"
memory: 4Gi
volumeMounts:
- name: buildkitd-config
mountPath: /etc/buildkit/buildkitd.toml
subPath: buildkitd.toml
- name: registry-auth
mountPath: /registry-auth/
volumes:
- name: buildkitd-config
configMap:
name: buildkitd-config
- name: registry-auth
secret:
secretName: buildkitd-registry-auth
---
apiVersion: v1
kind: Service
metadata:
name: buildkit-service
namespace: harbor-eval
spec:
type: ClusterIP
selector:
app: buildkitd
ports:
- port: 1234
targetPort: 1234配置 buildkitd 认证与镜像加速
BuildKit v0.15.0 不支持通过 CLI 参数配置 registry 认证,需通过配置文件设置。创建 buildkitd.toml ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: buildkitd-config
namespace: harbor-eval
data:
buildkitd.toml: |
[registry."docker.io"]
mirrors = ["mirror.gcr.io"]
[registry."<YOUR-ACR-ADDRESS>"]
config = "/registry-auth/"其中,Docker Hub 镜像源设为 mirror.gcr.io:阿里云 Registry 镜像加速不支持代理第三方仓库(如 swebench),拉取时会返回 insufficient_scope 错误。
创建 ACR 认证 Secret(Docker config 格式):
kubectl create secret generic buildkitd-registry-auth \
--namespace=harbor-eval \
--from-file=config.json=$HOME/.docker/config.json批量构建并推送镜像
使用 harbor admin upload-images 命令扫描数据集中的所有 Task,逐个构建 Dockerfile 并推送到 ACR:
harbor admin upload-images \
-t /path/to/dataset \
-r <YOUR-ACR-ADDRESS> \
--remote-buildkit tcp://buildkit-service:1234 \
--update-config \
--sanitize-image-names \
--skip-unchanged \
-n 4参数 | 说明 |
| 数据集目录路径 |
| ACR 地址 |
| BuildKit 服务地址 |
| 构建完成后将镜像信息写回 |
| 对镜像名称做 ACR 兼容处理 |
| 跳过内容未变化的 Task,支持断点续传 |
| 并行构建数 |
命令执行流程:
读取每个 Task 的 Dockerfile
通过 buildctl 在远端 BuildKit 服务构建镜像
推送到 ACR
将
docker_image、built_content_hash、image_sha256写回task.toml
Docker Hub 对匿名拉取的频率限制为 100 次/6 小时(认证用户为 200 次/6 小时)。大批量构建时容易触发限流(报错 failed to resolve source metadata),请确认已按上文配置 mirror.gcr.io 镜像加速。
500 个 Task 在 -n 4 并行下约需 2~3 小时,建议使用 nohup ... & disown 执行,避免终端断开导致任务中断。
构建完成后验证镜像:
crane digest <YOUR-ACR-ADDRESS>/<image-name>:<tag>task.toml 中的 docker_image 字段
upload-images 成功后,task.toml 的 [environment] 段会自动写入以下字段:
[environment]
docker_image = "registry.cn-hangzhou.aliyuncs.com/<ns>/harbor/<task-name>@sha256:..."
built_content_hash = "abc123..."
image_sha256 = "sha256:..."harbor run 运行时,ACK 环境优先读取 docker_image 直接拉取镜像(秒级),而非集群内现场构建(分钟级)。
运行评测
配置 ACR 拉取凭证
Trial Pod 从 ACR 拉取预构建镜像时需要认证。创建 docker-registry 类型的 Secret:
kubectl create secret docker-registry acr-pull-secret \
--namespace=harbor-eval \
--docker-server=registry.cn-hangzhou.aliyuncs.com \
--docker-username=<账号> \
--docker-password=<密码>在命令行直接传入 --docker-password 会将密码写入 shell 历史,建议在安全环境操作或改用凭证文件。
运行评测任务
以下命令在 ACK 集群中启动评测:Harbor 扫描数据集中的所有 Task,为每个 Task 创建 Trial Pod 并执行评测。-a 和 -m 请替换为实际使用的 Agent 和模型。
harbor run \
-p ./my-dataset \
--env ack \
-n 1 \
--ek namespace=harbor-eval \
--ek registry=registry.cn-hangzhou.aliyuncs.com/<ns>/harbor \
--ek image_pull_secret=acr-pull-secret \
-a qwen-coder \
-m qwen3.7-max \
--no-delete \
-y常用参数说明:
参数 | 说明 |
| 本地数据集路径 |
| 数据集注册表引用,如 |
| 使用 ACK 环境 |
| 并发 Trial 数。 |
| Trial Pod 所在命名空间 |
| ACR 地址。 |
| 拉取镜像所用的 Secret 名称 |
| 使用的 Agent |
| 使用的模型 |
| 评测完成后保留 Trial Pod,便于排查 |
| 跳过确认提示 |
指定节点调度
通过节点选择器将 Trial Pod 调度到特定机型,并覆盖资源配置:
harbor run \
-p ./my-dataset \
--env ack \
-n 1 \
--ek namespace=harbor-eval \
--ek image_pull_secret=acr-pull-secret \
--ek 'node_selector={"node.kubernetes.io/instance-type":"ecs.gn7i-c8g1.2xlarge"}' \
--override-cpus 4 \
--override-memory-mb 8192 \
--override-gpus 1 \
-a qwen-coder \
-m qwen3.7-max \
-y过滤任务
通过以下参数筛选要运行的任务:
-i "task-prefix-*" # 只运行名称匹配的任务
-x "skip-*" # 排除名称匹配的任务
-l 10 # 最多运行 10 个任务传递 Agent 环境变量
通过 --ae 参数将 API Key 等环境变量传入 Trial Pod,供 Agent 调用模型时使用:
--ae ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
--ae DASHSCOPE_API_KEY=$DASHSCOPE_API_KEY使用 YAML 配置文件
参数较多时,将配置写入 YAML 文件集中管理:
# eval-config.yaml
dataset: ./my-dataset # 或填写注册表引用
agent: qwen-coder
model: qwen3.7-max
environment:
type: ack
kwargs:
namespace: harbor-eval
registry: registry.cn-hangzhou.aliyuncs.com/<ns>/harbor
image_pull_secret: acr-pull-secret
service_account: harbor-eval-sa
n_concurrent_trials: 1
agent_env:
- name: ANTHROPIC_API_KEY
value: "${ANTHROPIC_API_KEY}"harbor run -c eval-config.yaml -y使用 ACS Sandbox 模式(可选)
在阿里云 Serverless 容器(ACS)上运行评测,或使用 OpenKruise SandboxSet 预热 Pod 加速 Trial 启动时,启用 Sandbox 模式。
SandboxClaim 模式依赖 OpenKruise CRD(agents.kruise.io/v1alpha1),启用前请确认集群已安装 OpenKruise,且 ServiceAccount 已具备相应的 CRD 权限(详见下文配置 RBAC)。
核心参数:
参数 | 说明 |
| 启用 SandboxClaim 模式,Harbor 自动创建 SandboxSet 预热池 |
| 指定 SandboxSet 使用的镜像(默认取 |
| 预热池大小,建议与 |
| 等待 SandboxClaim 就绪的超时秒数 |
| 为 Sandbox Pod 添加注解(JSON 格式) |
| 为 Sandbox Pod 添加标签(JSON 格式) |
| 向 Sandbox Pod 注入环境变量(JSON 格式) |
在 ACS 上运行示例:
harbor run \
-p ./dataset \
--env ack \
-n 4 \
--ek namespace=harbor-eval \
--ek image_pull_secret=acr-pull-secret \
--ek use_sandbox_claim=true \
--ek sandboxset_replicas=4 \
--ek 'sandbox_annotations={"k8s.aliyun.com/product-on-demand":"acs"}' \
-a qwen-coder \
-m qwen3.7-max \
-y如果不使用 Sandbox 模式,也可通过以下参数将标准 Trial Pod 调度到 virtual-kubelet 节点:
--ek 'node_selector={"type":"virtual-kubelet"}' \
--ek 'tolerations=[{"key":"virtual-kubelet.io/provider","operator":"Exists"}]'使用 K8s Job 编排评测
CI/CD 流水线中,将 harbor run 命令包装到 Kubernetes Job 中,由集群内部触发评测:
apiVersion: batch/v1
kind: Job
metadata:
name: harbor-eval-job
namespace: harbor-eval
spec:
parallelism: 1
completions: 1
backoffLimit: 0
template:
spec:
serviceAccountName: harbor-eval-sa
restartPolicy: Never
securityContext:
runAsUser: 0
containers:
- name: harbor-eval
image: <harbor-cli-image>
command:
- harbor
- run
- -p
- /mnt/oss/dataset
- --env
- ack
- -n
- "1"
- --ek
- namespace=harbor-eval
- --ek
- image_pull_secret=acr-pull-secret
- -a
- qwen-coder
- -m
- qwen3.7-max
- -o
- /mnt/oss/results/harbor-eval
- -y
env:
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
name: api-keys
key: anthropic-api-key
volumeMounts:
- name: dataset
mountPath: /mnt/oss/dataset
readOnly: true
- name: results
mountPath: /mnt/oss/results
volumes:
- name: dataset
persistentVolumeClaim:
claimName: harbor-dataset-pvc
readOnly: true
- name: results
persistentVolumeClaim:
claimName: harbor-results-pvc配置 RBAC
Job Pod 需要通过 ServiceAccount 获得创建 Trial Pod 等操作的权限:
# harbor-eval-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: harbor-eval-sa
namespace: harbor-eval
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: harbor-eval-role
namespace: harbor-eval
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec", "pods/log"]
verbs: ["get", "list", "create", "delete", "watch"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: harbor-eval-rolebinding
namespace: harbor-eval
subjects:
- kind: ServiceAccount
name: harbor-eval-sa
namespace: harbor-eval
roleRef:
kind: Role
name: harbor-eval-role
apiGroup: rbac.authorization.k8s.iokubectl apply -f harbor-eval-rbac.yaml使用 Sandbox 模式时,需为上述 Role 额外添加 sandboxsets、sandboxclaims、sandboxes 的 get/list/create/delete/watch 权限。
查看评测结果
查看 Trial Pod 状态
# 查看所有 Trial Pod
kubectl get pods -n harbor-eval -l app=sandbox
# 查看特定 Pod 的日志
kubectl logs -n harbor-eval <pod-name> --tail=100查看 Job 状态
使用 K8s Job 编排评测时,查看 Job 的执行状态和日志:
kubectl get jobs -n harbor-eval
kubectl describe job harbor-eval-job -n harbor-eval
kubectl logs -l job-name=harbor-eval-job -n harbor-eval --tail=200查看评测结果文件
每个 Trial 的结果目录结构:
harbor-eval/
└── <task-name>/
├── agent/ # Agent 执行日志
├── verifier/ # Verifier 验证结果
├── artifacts/ # 任务产出物
└── results.json # 汇总结果K8s Job 编排时,用 -o /mnt/oss/results 指定输出路径,结果经 OSS CSI fuse 直接写回 OSS,无需额外上传。评测完成后用 ossutil 查看:
ossutil ls oss://my-harbor-bucket/results/harbor-eval/常见问题
Pod 一直处于 Pending 状态
查看 Pod 事件:
kubectl describe pod <pod-name> -n harbor-eval常见原因:
节点资源不足:调整
--override-cpus或--override-memory-mb镜像拉取失败:检查
image_pull_secret和 ACR 地址配置节点选择器不匹配:确认
node_selector中的标签在集群节点上存在
镜像拉取失败
# 确认 ACR 中存在目标镜像
docker manifest inspect <acr-address>/<image>:<tag>
# 确认 Secret 与 Pod 在同一命名空间
kubectl get secret acr-pull-secret -n harbor-evalHarbor CLI 无法连接集群
# 验证 kubeconfig
kubectl cluster-info
# 在 Pod 内确认 RBAC 权限
kubectl auth can-i create pods -n harbor-eval --as=system:serviceaccount:harbor-eval:harbor-eval-sa集群内运行时,kubeconfig 指向的 VPC 内网 IP 可能无法从 Pod CIDR 访问。将 API Server 地址改为集群内 Service 端点:https://kubernetes.default.svc:443。
评测任务超时
任务超时由 task.toml 中的以下字段控制:
[agent]
timeout_sec = 300
[verifier]
timeout_sec = 60如需全局调整,使用顶层 CLI 参数(注意不是 --ek 参数):
--agent-timeout-multiplier 2.0docker_image 字段未生效
确认 Harbor CLI 版本不低于 0.6.5,旧版本不读取 docker_image 字段:
harbor --version相关文档
Harbor CLI 的完整参数说明、环境配置指南和更多使用示例,请参阅 Harbor 开源仓库和Harbor 官方文档。
在 ACR 上使用 Harbor,请参考从自建Harbor同步镜像到ACR企业版。