帮你快速理解、总结文档立即下载
文档中心>Agent Runtime>Agent 集群>快速入门>通过 Kubernetes API 运行第一个工作负载

通过 Kubernetes API 运行第一个工作负载

最近更新时间:2026-10-08 17:40:01
本文档已由 AI 辅助审校
我的收藏
如果您正在开发代码助手或数据分析 Agent,通常需要为每个任务准备独立的执行环境,使其能够接收用户文件、运行脚本、保存结果,并在后续任务中继续使用这些文件。如果您的应用已使用 Kubernetes SDK、kubectl 或工作流编排器,可以通过 Kubernetes API 完成这些操作。
本文以“数据分析 Agent 汇总订单文件”为例,完成一次可复现的任务:
1. 创建 Pod 作为脚本执行环境,挂载工作区保存订单和结果。
2. 统计已支付订单数量与金额,记录环境启动耗时。
3. 结束原 Pod,在另一节点创建新 Pod,接着处理原来的文件。
本例提供固定数据和脚本,无需配置模型或调用外部业务系统。实际接入 Agent 时,可将这些操作分别放到应用的“创建环境、上传文件、执行代码、读取结果、释放环境”流程中。kubectl 在这里作为 Kubernetes API 客户端使用。

开始前准备

您需要一个已创建的 Agent 集群,以及可访问集群的 kubeconfig。本机安装 kubectl 和 Python 3;操作账号需要查询节点、RuntimeClass 和 StorageClass,创建及删除测试命名空间,管理其中的 Pod/PVC,以及执行 pods/exec 的权限。
先配置访问,并查看运行环境:
export KUBECONFIG='/absolute/path/to/your/agc-kubeconfig'
kubectl config current-context
kubectl get nodes
kubectl get runtimeclass
kubectl get storageclass
本例使用以下配置。将值替换为自己集群中的名称,并在同一个终端依次执行后续命令:
export AGC_DEMO_NS="agc-orders-$(date +%Y%m%d%H%M%S)"
export AGC_RUNTIME_CLASS='cube'
export AGC_STORAGE_CLASS='awv-btrfs'
export AGC_DEMO_IMAGE='busybox:1.36.1'
kubectl create namespace "$AGC_DEMO_NS"
配置
如何选择
RuntimeClass
选择 Agent 集群中用于运行任务的运行时;本例填写 cube。
StorageClass
选择支持跨节点重新挂载、ReadWriteOncePod 和 fsGroup: 1000 的工作区存储类;本例填写 awv-btrfs。
执行镜像
本例使用 BusyBox 的 Shell、awk 和校验工具;节点需要能够拉取此镜像,也可替换为包含相同工具的企业镜像。
节点
先有一个可调度且支持所选运行时和存储的 Ready 节点;跨节点继续任务还需要第二个这样的节点。
每次实验使用独立命名空间,避免与已有任务重名。下面的 Pod 只运行本例脚本,工作文件保存在 PVC 挂载的 /workspace 中。

第一步:准备工作区和执行环境

将以下命令复制到终端,生成工作区配置:
cat > orders-pvc.yaml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: orders-workspace
namespace: ${AGC_DEMO_NS}
spec:
storageClassName: ${AGC_STORAGE_CLASS}
volumeMode: Filesystem
accessModes: [ReadWriteOncePod]
resources:
requests:
storage: 1Gi
EOF
生成 Pod 配置。Pod 启动后保持运行,便于应用通过 exec 提交任务:
cat > orders-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: orders-runner
namespace: ${AGC_DEMO_NS}
spec:
runtimeClassName: ${AGC_RUNTIME_CLASS}
restartPolicy: Never
automountServiceAccountToken: false
securityContext:
fsGroup: 1000
containers:
- name: runner
image: ${AGC_DEMO_IMAGE}
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 86400"]
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi
volumeMounts:
- name: workspace
mountPath: /workspace
volumes:
- name: workspace
persistentVolumeClaim:
claimName: orders-workspace
EOF
kubectl create --dry-run=server -f orders-pvc.yaml
kubectl create --dry-run=server -f orders-pod.yaml
kubectl create -f orders-pvc.yaml
使用 WaitForFirstConsumer 的存储类时,PVC 此时显示 Pending 是正常的;创建 Pod 后才会开始绑定。请勿在创建 Pod 前一直等待 PVC Bound。

第二步:启动环境并记录等待时间

对业务应用而言,需要等待的是“可以执行代码且工作区可以写入”。将下面脚本保存为 measure-start.py,测量从本机发起创建到确认工作区可写的耗时:
import json
import os
import subprocess
import sys
import time

namespace = os.environ['AGC_DEMO_NS']

def kubectl(*args):
return subprocess.check_output(
['kubectl', '-n', namespace, *args], text=True, timeout=210
)

started = time.perf_counter()
created = json.loads(kubectl('create', '-f', sys.argv[1], '-o', 'json'))
name = created['metadata']['name']
print('pod:', name, file=sys.stderr, flush=True)
kubectl('wait', '--for=condition=Ready', 'pod/' + name, '--timeout=180s')
kubectl('exec', name, '-c', 'runner', '--', '/bin/sh', '-ec',
'echo ready > /workspace/.startup-check; cat /workspace/.startup-check; '
'rm /workspace/.startup-check')
elapsed = time.perf_counter() - started
pod = json.loads(kubectl('get', 'pod', name, '-o', 'json'))
container = next(c for c in pod['status']['containerStatuses'] if c['name'] == 'runner')
print(json.dumps({
'namespace': namespace,
'pod': name,
'node': pod['spec']['nodeName'],
'workspace_ready_seconds': round(elapsed, 3),
'image_id': container.get('imageID'),
'restart_count': container['restartCount'],
}, ensure_ascii=False, indent=2))
执行脚本:
python3 measure-start.py orders-pod.yaml > startup-a.json
cat startup-a.json
成功时会输出 Pod 名称、所在节点、workspace_ready_seconds 和镜像信息。该耗时包含客户端请求、调度、镜像准备、工作区挂载以及 exec 检查;它不是单独的容器启动耗时,也不包含后面的订单统计时间。
若 180 秒内未就绪,脚本会失败并保留 Pod,请参见文末排查方法查看原因,请勿重复创建同名资源。

第三步:上传订单并生成统计结果

下面模拟 Agent 接收一份订单文件,并将准备好的分析脚本放到工作区。只有 paid 订单计入统计,金额单位为元:
kubectl -n "$AGC_DEMO_NS" exec -i orders-runner -c runner -- /bin/sh -s <<'SCRIPT'
set -eu
cat > /workspace/orders.csv <<'CSV'
order_id,status,amount
A001,paid,100
A002,paid,50
A003,cancelled,80
CSV
cat > /workspace/summarize.sh <<'SH'
#!/bin/sh
set -eu
awk -F, 'NR > 1 && $2 == "paid" { count++; amount += $3 }
END { printf "paid_orders=%d\\npaid_amount=%d\\n", count, amount }' \\
/workspace/orders.csv > /workspace/summary.txt
SH
/bin/sh /workspace/summarize.sh
sync
cat /workspace/summary.txt
SCRIPT
预期输出:
paid_orders=2
paid_amount=150
将本次结果和文件校验值保存到本机:
kubectl -n "$AGC_DEMO_NS" exec orders-runner -c runner -- cat /workspace/summary.txt > summary-a.txt
kubectl -n "$AGC_DEMO_NS" exec orders-runner -c runner -- \\
sha256sum /workspace/orders.csv /workspace/summarize.sh /workspace/summary.txt > files-a.sha256 || { echo "读取校验值失败,停止实验" >&2; exit 1; }
test -s files-a.sha256 || { echo "未取得文件校验值,停止实验" >&2; exit 1; }
cat summary-a.txt
至此,您已经完成一个可用的最小任务:创建环境、提交文件和脚本、执行分析、取回结果。如果只需体验第一次执行,可以直接跳到清理步骤。

第四步:换一个节点继续任务

假设上一轮分析结束后,您释放执行环境;后来用户追加订单,需要再次创建环境继续处理原文件。下面主动选择另一个节点,验证工作区能否随任务重新挂载。
先查看当前 Pod 的节点,以及可用节点的 hostname 标签:
kubectl -n "$AGC_DEMO_NS" get pod orders-runner -o wide
kubectl get nodes -L kubernetes.io/hostname
kubectl get runtimeclass "$AGC_RUNTIME_CLASS" -o yaml
选择一个不同于当前节点、状态 Ready 且未标记 SchedulingDisabled 的节点。目标节点必须满足所选 RuntimeClass 的调度条件,并在工作区存储的挂载范围内。将它的 kubernetes.io/hostname 标签值填入:
export AGC_TARGET_HOSTNAME='REPLACE_WITH_NODE_B_HOSTNAME'
python3 - <<'PY'
import json
import os
import subprocess
pod = json.loads(subprocess.check_output(
['kubectl', 'create', '--dry-run=client', '-f', 'orders-pod.yaml', '-o', 'json'], text=True))
pod['metadata']['name'] = 'orders-runner-b'
pod['spec']['nodeSelector'] = {'kubernetes.io/hostname': os.environ['AGC_TARGET_HOSTNAME']}
with open('orders-pod-b.json', 'w') as f:
json.dump(pod, f, indent=2)
PY
kubectl create --dry-run=server -f orders-pod-b.json
仅释放原 Pod,保留 orders-workspace PVC,然后启动新 Pod:
kubectl -n "$AGC_DEMO_NS" delete pod orders-runner --wait=true --timeout=180s
kubectl -n "$AGC_DEMO_NS" get pvc orders-workspace
python3 measure-start.py orders-pod-b.json > startup-b.json
cat startup-b.json
这里是“停止原环境,再挂载工作区启动新环境”,不是正在执行的进程无中断迁移。ReadWriteOncePod 限定同一时刻由一个 Pod 使用此工作区,因此需要先结束原 Pod。

第五步:校验原文件并处理追加订单

新 Pod 不重新上传文件,先检查原来的数据、脚本和结果是否一致:
kubectl -n "$AGC_DEMO_NS" exec orders-runner-b -c runner -- \\
sha256sum /workspace/orders.csv /workspace/summarize.sh /workspace/summary.txt > files-b.sha256 || { echo "读取校验值失败,停止实验" >&2; exit 1; }
test -s files-a.sha256 && test -s files-b.sha256 && diff files-a.sha256 files-b.sha256 || { echo "文件校验失败,停止实验" >&2; exit 1; }
diff 无输出且退出码为 0,说明三个文件的校验值一致。如果不一致,停止后续写入并检查工作区。校验通过后,追加一条 80 元的已支付订单,再执行原脚本:
kubectl -n "$AGC_DEMO_NS" exec orders-runner-b -c runner -- /bin/sh -ec '
printf "%s\\n" "A004,paid,80" >> /workspace/orders.csv
/bin/sh /workspace/summarize.sh
sync
cat /workspace/summary.txt
' > summary-b.txt
cat summary-b.txt
预期输出为 paid_orders=3、paid_amount=230。这说明新环境能够继续读取、修改原文件并执行脚本,不需要重新上传上一轮的工作内容。追加订单这一步只执行一次,重复执行会重复计入该订单。

核对本次体验结果

核对项
预期结果
首轮分析
2 笔已支付订单,合计 150 元,已取消订单不计入。
节点变化
startup-a.json 与 startup-b.json 中的 node 不同。
文件保留
三个文件迁移前后的 SHA-256 一致。
继续分析
追加订单后为 3 笔,合计 230 元。
环境等待时间
两份记录均有 workspace_ready_seconds,容器 restart_count 为 0。
两次耗时只反映这次体验。首次拉取镜像、节点缓存、卷创建和重新挂载都会影响结果,不能直接将两次耗时差解释为加速比例。需要评估并发或性能时,固定镜像、资源规格及缓存条件,单独设计重复采样实验。

清理测试资源

先保留本机的统计结果、启动记录和校验文件,再删除本次测试 Pod:
kubectl -n "$AGC_DEMO_NS" delete pod orders-runner orders-runner-b --ignore-not-found --wait=true --timeout=180s
如果后续还要使用订单文件,保留 PVC。确认测试数据不再需要时,再删除 PVC 和本次独立命名空间:
kubectl -n "$AGC_DEMO_NS" delete pvc orders-workspace --wait=true --timeout=180s
kubectl delete namespace "$AGC_DEMO_NS" --wait=true --timeout=180s
删除 PVC 后是否删除后端数据,取决于 StorageClass 的回收策略。使用 Retain 策略时,还需按存储管理流程处理保留卷。

遇到问题时

kubectl -n "$AGC_DEMO_NS" get pods,pvc -o wide
kubectl -n "$AGC_DEMO_NS" get events --sort-by=.metadata.creationTimestamp
现象
排查方法
Forbidden
核对 kubeconfig 身份及命名空间、Pod、PVC、pods/exec 权限。
Pod Pending
查看调度事件,检查 RuntimeClass 条件、目标节点、资源余量和 PVC 绑定状态。
ImagePullBackOff
检查节点到镜像仓库的网络及镜像权限;私有镜像需配置拉取凭证。
挂载失败或提示卷仍被占用
检查存储组件和原 Pod 的卸载情况,不强制解绑仍在使用的卷。
工作区 Permission denied
检查存储类的 fsGroup 支持及卷目录权限;本例使用 UID/GID 1000。
第二个节点始终无法启动
检查节点是否满足运行时条件、是否安装存储组件,以及卷是否支持在该节点挂载。
校验不一致或统计结果不符
先停止追加数据,核对 PVC 名称、挂载路径及订单追加步骤是否重复执行。
准备接入您自己的 Agent 应用时,可以将本例脚本替换为业务任务,沿用“每次任务创建执行环境、同一工作过程复用工作区、完成后回收计算资源”的流程。