部署 Substrate Sandbox
本文主要描述在已经部署好 Agent Substrate 的 Kubernetes 集群上执行的完整示例。
先创建一个简单的 HTTP Sandbox Actor,验证完整链路:
Atespace → WorkerPool → ActorTemplate → Actor → Resume → 访问 → Suspend
这里有一个容易忽略的地方:Atespace、ActorTemplate、Actor 是通过 Substrate API 管理的逻辑资源,不是 Kubernetes CRD;WorkerPool 和 SandboxConfig 才是 Kubernetes 资源。 因此不能全部使用 kubectl apply 创建。
0. 检查 Substrate 是否部署正常
先检查核心组件:
kubectl get pods -n ate-system
kubectl get crd | grep -E 'workerpools|sandboxconfigs'
检查 Substrate CLI:
kubectl ate get atespaces
kubectl ate get workers
如果本地还没有 kubectl ate:
go install github.com/agent-substrate/substrate/cmd/kubectl-ate@latest
注意:CLI 版本尽量与集群部署的 Substrate 版本保持一致。
1. 创建 Atespace【租户】
先创建 Kubernetes Namespace:
kubectl create namespace demo-space
现在创建 Substrate 逻辑隔离空间:
kubectl ate create atespace demo-space
查看:
kubectl ate get atespace demo-space
#示例
ATESPACE NAME TEMPLATE STATE WORKER POD WORKER IPS VERSION AGE
demo-space ate-demo-actor ate-demo/demo-template ACTOR_STATE_RUNNING ate-demo/demo-68c995676b-f7tmn 1.1.1.1 3 39h
注意这里有两个同名对象:
| 对象 | 所属系统 | 作用 |
|---|---|---|
Namespace demo-space |
Kubernetes | WorkerPool 等 K8s 资源的命名空间 |
Atespace demo-space |
Substrate | Actor 的逻辑隔离空间 |
它们不是同一个对象,只是为了方便示例使用了相同名称。注意执行ate的参数指定atespace 是用参数-a而不是-n。
2. 创建 WorkerPool【资源池】
这是创建 Actor 之前最重要的准备工作。
WorkerPool 是 Kubernetes CRD,负责提供可以承载 Actor 的 Worker Pod。可以理解为资源池。
创建 workerpool.yaml:
apiVersion: ate.dev/v1
kind: WorkerPool
metadata:
name: demo-pool
namespace: demo-space
labels:
workload: demo-agent
spec:
replicas: 2
# 必须使用与当前 Substrate 部署版本匹配的 Worker 镜像
workerImage: <你的 ateworker-gvisor 镜像>
sandboxClasses:
- name: gvisor
template:
resources:
limits:
cpu: "2"
memory: 2Gi
requests:
cpu: 500m
memory: 2Gi
这里的 workerImage 不能随意填写。应该使用你当前 Substrate 安装时使用的 ateworker-gvisor 镜像,确保版本一致。
应用:
kubectl apply -f workerpool.yaml
检查:
kubectl get workerpool -n demo-space
kubectl get pods -n demo-space -w
预期有两个 Worker Pod 逐渐变成 Running。
WorkerPool 有几个重要概念:
| 配置 | 含义 |
|---|---|
| replicas | 预热 Worker 的数量 |
| workerImage | Worker 内部管理程序的镜像 |
| sandboxClasses | 支持的 Sandbox Runtime |
| template.resources | Worker Pod 的资源配置 |
| metadata.labels | 供 ActorTemplate 的 workerSelector 选择 |
这里要特别注意:WorkerPool 的资源限制决定 Worker 可承载的容量;ActorTemplate 的资源限制决定单个 Actor 申请的资源。两者不是同一个概念。
3. 创建 ActorTemplate【Sandbox模板】
ActorTemplate 用来定义 Actor 运行什么程序、使用什么资源、使用什么 Sandbox Runtime,以及如何保存快照。
这一步需要准备一个容器镜像。
这里推荐直接使用一个自己构建的 HTTP 服务镜像,假设它具有以下行为:
-
容器启动后监听 80 端口。
-
GET /readyz返回 HTTP 200。 -
GET /返回Hello from Agent Substrate。 -
工作目录为
/workspace。
假设你的镜像为:
registry.example.com/agent/demo-server:v1
创建 actor-template.yaml:
metadata:
atespace: demo-space
name: demo-template
# 选择前面创建的 WorkerPool
workerSelector:
matchLabels:
workload: demo-agent
containers:
- name: agent
image: registry.example.com/agent/demo-server:v1
ports:
- containerPort: 80
wakeupProbe:
httpGet:
path: /readyz
port: 80
volumeMounts:
- name: workspace
mountPath: /workspace
resources:
limits:
cpuMillicores: 1000
memoryBytes: 1073741824
snapshotConfig:
storageLocation: gs://YOUR_BUCKET/agent-substrate/demo-space/
sandboxConfig:
sandboxClass: SANDBOX_CLASS_GVISOR
configName: gvisor-default
volumes:
- name: workspace
durableDir: {}
需要替换:
-
registry.example.com/agent/demo-server:v1:替换成你自己的镜像。 -
gs://YOUR_BUCKET/...:替换成当前 Substrate 对象存储插件支持的快照存储路径。这里沿用官方 GCS 示例;如果你部署的是其他存储后端,要使用对应支持的 URI。 -
gvisor-default:确保集群里存在对应的 SandboxConfig。
关于几个关键字段:
| 字段 | 作用 |
|---|---|
| metadata.atespace | ActorTemplate 所属的 Atespace |
| metadata.name | 模板名称 |
| workerSelector | 选择具有对应标签的 WorkerPool |
| containers | Actor 内部运行的容器 |
| resources | Actor 的资源申请 |
| wakeupProbe | 恢复后判断服务是否就绪 |
| snapshotConfig | 配置快照策略和存储位置 |
| sandboxConfig | 选择 Sandbox Runtime |
| durableDir | Actor 独立的持久化数据目录 |
这里使用 durableDir,是为了让 /workspace 中的数据能够在 Actor Suspend/Resume 后保留。
关于快照: 当前示例重点是持久化工作目录。如果你还要求进程内存状态也恢复,需要根据当前 Substrate 版本配置相应的完整内存快照策略。
官方 Counter Demo 提供了完整的 gVisor、DurableDir 和内存快照配置,可以作为进一步参考 substrate/demos/counter。
创建模板:
kubectl ate create actor-template -f actor-template.yaml
查看:
kubectl ate get actor-templates -a demo-space
查看具体模板:
kubectl ate get actor-template demo-template \
-a demo-space \
-o yaml
# status 输出
status:
goldenSnapshotStatus:
goldenTag:
atespace: ate-golden
name: 0afe4a06-1432-424e-9e9c-ca60bb991a17
takeGoldenSnapshotAt: "2026-10-31T11:34:52.168080494Z"
注意
ActorTemplate 创建后,Substrate 默认会创建 Golden Snapshot。Golden Snapshot 是模板的初始快照,不是你创建的每个 Actor 的独立快照。
需要等待模板初始化完成,再创建 Actor。检查模板状态以及 Golden Tag 是否已经生成。
4. 创建 Actor【sandbox逻辑实例】
现在终于可以创建 Actor 了。actor 是sandbox的逻辑实例,类似一个轻量型虚拟机,初始化是未开机状态。
kubectl ate create actor my-agent-001 \
-a demo-space \
--template demo-template
这里:
| 参数 | 含义 |
|---|---|
| my-agent-001 | Actor 名称 |
| -a demo-space | Actor 所属 Atespace |
| --template demo-template | 使用哪个 ActorTemplate |
查看 Actor:
kubectl ate get actors -a demo-space
查看具体 Actor:
kubectl ate get actor my-agent-001 \
-a demo-space \
-o yaml
这里要注意:
创建 Actor 并不等于立即启动 Actor。
CreateActor 主要是在 Substrate 控制面注册一个逻辑 Actor,真正分配 Worker 和恢复 Sandbox 需要执行 Resume,或者通过 Router 的请求触发自动恢复。
5. 启动 Sandbox【Resume Actor】
执行:
kubectl ate resume actor my-agent-001 \
-a demo-space
这时候 Substrate 会完成大致如下流程:
kubectl ate resume actor

查看 Actor 状态:
kubectl ate get actor my-agent-001 \
-a demo-space \
-o yaml
查看 Worker:
kubectl ate get workers
# 输出
NAME POOL STATE ACTORS CPU MEMORY POD AGE
978b42b3-8bed-4b8c-a1b0-957c5b343f76 demo-pool WORKER_STATE_ACTIVE 0/1 0/1 0/2Gi ate-demo-pool/demo-pool-68c995676b-2nrvm 39h
009b30f6-e170-43a0-9b5d-7cfe236e9e9f demo-pool WORKER_STATE_ACTIVE 1/1 1/1 1Gi/2Gi ate-demo-pool/demo-pool-68c995676b-f7tmn 39h
fef5851c-52b1-4805-b7b0-c86af3d53143 demo-pool WORKER_STATE_ACTIVE 0/1 0/1 0/2Gi ate-demo-pool/demo-pool-68c995676b-kcwnz 39h
你应该能看到一个 Worker 被分配给 demo-space/my-agent-001。
6. 通过 Router 访问 Actor
Substrate 不要求你直接访问 Worker Pod IP。
通过 atenet-router 访问:
先转发 Router:
kubectl port-forward \
-n ate-system \
svc/atenet-router 8000:80
另外打开一个终端:
curl -i \
-H "ate-target-actor: demo-space/my-agent-001" \
http://localhost:8000/
预期:
HTTP/1.1 200 OK
Hello from Agent Substrate
这里最重要的是:
ate-target-actor: demo-space/my-agent-001
它告诉 Router 应该把请求路由到哪个 Actor。
Router 不需要知道 Actor 当前在哪一个 Worker Pod 上。
7. 暂停sandbox【Suspend Actor】
这是 Substrate 最值得验证的功能。
先在 Actor 工作目录中创建一个文件:
# 这里假设你的 demo-server 提供了文件操作接口
# 或者通过你自己的 Actor 命令接口写入文件
然后暂停 Actor:
kubectl ate suspend actor my-agent-001 \
-a demo-space
查看状态:
kubectl ate get actor my-agent-001 \
-a demo-space
# 示例
ATESPACE NAME TEMPLATE STATE WORKER POD WORKER IPS VERSION AGE
demo-space ate-demo-actor ate-demo/demo-template ACTOR_STATE_SUSPENDED <none> 5 39h
此时 Actor 应该进入 SUSPENDED 状态,并释放原来占用的 Worker。
kubectl ate get workers
# 输出
NAME POOL STATE ACTORS CPU MEMORY POD AGE
978b42b3-8bed-4b8c-a1b0-957c5b343f76 demo-pool WORKER_STATE_ACTIVE 0/1 0/1 0/2Gi ate-demo-pool/demo-pool-68c995676b-2nrvm 39h
009b30f6-e170-43a0-9b5d-7cfe236e9e9f demo-pool WORKER_STATE_ACTIVE 0/1 0/1 0/2Gi ate-demo-pool/demo-pool-68c995676b-f7tmn 39h
fef5851c-52b1-4805-b7b0-c86af3d53143 demo-pool WORKER_STATE_ACTIVE 0/1 0/1 0/2Gi ate-demo-pool/demo-pool-68c995676b-kcwnz 39h
再次访问:
curl -i \
-H "ate-target-actor: demo-space/my-agent-001" \
http://localhost:8000/
Router 会触发 Actor 恢复,然后将请求转发到新的执行位置。
你可以再查看:
kubectl ate get actor my-agent-001 \
-a demo-space \
-o yaml
kubectl ate get workers
这就完成了 Actor 的创建、启动、访问、暂停和恢复。
8. 完整创建流程汇总
如果前面的准备工作都完成了,后续日常创建 Actor 主要就是下面这些命令:
# 1. 创建 Kubernetes Namespace
kubectl create namespace demo-space
# 2. 创建 WorkerPool
kubectl apply -f workerpool.yaml
# 3. 创建 Atespace
kubectl ate create atespace demo-space
# 4. 创建 ActorTemplate
kubectl ate create actor-template -f actor-template.yaml
# 5. 等待 Golden Snapshot 就绪
kubectl ate get actor-templates -a demo-space
# 6. 创建 Actor
kubectl ate create actor my-agent-001 \
-a demo-space \
--template demo-template
# 7. 启动 Actor
kubectl ate resume actor my-agent-001 \
-a demo-space
# 8. 查看 Actor
kubectl ate get actor my-agent-001 -a demo-space
# 9. 查看 Worker
kubectl ate get workers
# 10. 暂停 Actor
kubectl ate suspend actor my-agent-001 \
-a demo-space
# 11. 删除 Actor
kubectl ate delete actor my-agent-001 \
-a demo-space
参考:
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.