llm-wiki wiki · sources 2026-06-12

原文:raw/substrate-architecture-analysis.md · 仓库:https://github.com/agent-substrate/substrate · 分析版本 HEAD a3f4474

一句话定位

Agent Substrate 是一个建立在 kubernetes 之上的高密度 Agent Runtime / Sandbox substrate:Kubernetes 只负责声明式容量和基础设施,Actor 的高频生命周期、resume/suspend、worker 分配和路由唤醒由 Substrate 自己的 Redis/ValKey 控制面、Envoy ext_proc router、atelet node supervisor 和 gVisor ateom worker 承担。

它补的是 agent-sandboxagentcube 之间更底层、更激进的一层:不是“创建一个有状态 sandbox”,而是把大量 idle actor multiplex 到较少 warm worker 上,通过 golden snapshot、runtime snapshot、DNS/router 唤醒和 gVisor restore 降低激活延迟。官方 architecture 文档也明确标注“Much of this architecture is aspirational”,所以要把愿景和当前代码实现分开看。

核心架构图

┌──────────────────────────────────────────────────────────────────────────────┐
│ Users / higher-level agent frameworks                                        │
│                                                                              │
│  HTTP request to <actor-id>.actors.resources.substrate.ate.dev               │
│  kubectl ate create/resume/suspend/logs                                      │
└───────────────────────────────┬──────────────────────────────────────────────┘
                                │
                                ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ atenet router                                                                │
│                                                                              │
│  CoreDNS stub domain → Envoy → ext_proc                                      │
│  parse actor id from host → ResumeActor(actor_id) → rewrite :authority       │
│  to worker pod IP:80                                                         │
└───────────────────────────────┬──────────────────────────────────────────────┘
                                │ gRPC Control API
                                ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ ateapi control plane                                                         │
│                                                                              │
│  Control service: CreateActor / ResumeActor / SuspendActor / DeleteActor     │
│  SessionIdentity service: mint stable JWT / mTLS cert for migrating actor    │
│  Redis/ValKey: actor:<id>, worker:<ns>:<pool>:<pod>, lock:actor:<id>         │
│  ActorWorkflow: idempotent resume/suspend steps + forward recovery           │
└───────────────┬──────────────────────────────────────────────┬───────────────┘
                │ Kubernetes informers / CRD listers           │ gRPC AteomHerder
                ▼                                              ▼
┌──────────────────────────────────────┐        ┌──────────────────────────────┐
│ atecontroller                         │        │ atelet DaemonSet             │
│                                      │        │                              │
│ WorkerPool → privileged ateom pods   │        │ fetch verified runsc         │
│ ActorTemplate → golden actor         │        │ pull images / build OCI      │
│ golden actor resume → wait → suspend │        │ upload/download snapshots    │
│ status.goldenSnapshot = snapshot URI │        │ call ateom over Unix socket  │
└──────────────────────────────────────┘        └──────────────┬───────────────┘
                                                               │ gRPC Ateom
                                                               ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ ateom-gvisor worker pod                                                      │
│                                                                              │
│  privileged pod, one active actor at a time                                  │
│  link-local veth: pod netns ateom0 ↔ actor netns eth0                        │
│  nftables DNAT/MASQ compatibility bridge                                     │
│  runsc create/start/checkpoint/restore pause + app containers                │
└──────────────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ Object storage snapshots                                                     │
│                                                                              │
│  gs:// or s3:// prefix                                                        │
│  checkpoint.img.zstd / pages.img.zstd / pages_meta.img.zstd                  │
└──────────────────────────────────────────────────────────────────────────────┘

模块分层

层 / 模块 职责
CRD / public API 定义 WorkerPoolActorTemplate 和 actor lifecycle gRPC API;K8s CRD 承载低频配置,gRPC 承载高频 actor 操作。
K8s controller WorkerPool 物化为 privileged ateom Deployment;把 ActorTemplate 驱动成 golden actor → golden snapshot → Ready。
Control plane / DB 对外提供 Control / SessionIdentity gRPC;用 Redis/ValKey 存 actor/worker 状态和 lock;用 workflow step 实现 resume/suspend forward recovery。
Node supervisor 每节点/每 worker 管理 runsc、镜像拉取、OCI bundle、snapshot 上传下载,并转调 ateom。
Sandbox herder privileged worker pod 内的 gVisor 控制进程,串行调用 runsc create/start/checkpoint/restore,管理 actor netns/veth/nftables。
Router / DNS 用 CoreDNS stub domain + Envoy xDS + ext_proc,把 actor hostname 转成 ResumeActor 调用和 worker pod IP 转发。

关键边界:kubernetes API 不存每个高频 actor transition;WorkerPool/ActorTemplate 是声明式配置,Actor/Worker 的运行状态在 Redis/ValKey,真正 runsc 操作在 worker pod 本地完成。

关键数据流

ActorTemplate 到 golden snapshot

ActorTemplate CR created
        │
        ▼
atecontroller ActorTemplateReconciler
        │  PhaseInitial
        ▼
ateapi.CreateActor(goldenActorID)
        │
        ▼
status.phase = ResumeGoldenActor
        │
        ▼
ateapi.ResumeActor(goldenActorID)
        │  no actor snapshot + no golden snapshot
        ▼
atelet.Run → ateom.RunWorkload → runsc create/start
        │
        ▼
wait 20s
        │
        ▼
ateapi.SuspendActor(goldenActorID)
        │
        ▼
atelet.Checkpoint → ateom.CheckpointWorkload → upload checkpoint files
        │
        ▼
ActorTemplate.status.goldenSnapshot = snapshot URI
ActorTemplate.status.phase = Ready

请求唤醒和路由

HTTP request
Host: <actor-id>.actors.resources.substrate.ate.dev
        │
        ▼
CoreDNS stub domain routes to atenet-router
        │
        ▼
Envoy RequestHeaders ext_proc
        │
        ▼
parseActorID(host)
        │
        ▼
singleflight ResumeActor(actor-id)
        │
        ▼
ateapi resume workflow
        │
        ├─ LoadActorForResume
        ├─ AssignWorker
        ├─ CallAteletRestore / Run
        └─ FinalizeRunning
        │
        ▼
actor.ateom_pod_ip returned
        │
        ▼
mutate :authority to <worker-ip>:80
        │
        ▼
Envoy dynamic_forward_proxy forwards request

Resume / Suspend workflow

ResumeActor(actor-id)
        │
        ▼
Acquire lock: lock:actor:<id>
        │
        ▼
Load actor + ActorTemplate
        │
        ▼
Find existing assigned worker or random free worker
        │
        ▼
Update worker(actor_id=...) then actor(status=RESUMING, worker fields)
        │
        ▼
if actor.last_snapshot: atelet.Restore(last_snapshot)
else if template.goldenSnapshot and !boot: atelet.Restore(goldenSnapshot)
else: atelet.Run(template spec)
        │
        ▼
Update actor(status=RUNNING)

SuspendActor(actor-id)
        │
        ▼
Acquire lock: lock:actor:<id>
        │
        ▼
Load actor + ActorTemplate
        │
        ▼
Mark actor SUSPENDING + in_progress_snapshot
        │
        ▼
atelet.Checkpoint(snapshot URI)
        │
        ▼
Free worker, move in_progress_snapshot → last_snapshot,
clear worker fields, status=SUSPENDED

设计决策与哲学

关键组件深入解读

ateapi ActorWorkflow

ActorWorkflow 是当前源码里最能体现 Substrate 设计哲学的部分。它不是写一个大函数完成 resume/suspend,而是把流程拆成可跳过的步骤:resume 依次加载 actor、分配 worker、调用 atelet restore/run、最终置 running;suspend 依次加载 actor、标记 suspending、调用 atelet checkpoint、释放 worker 并提交 snapshot。

这个拆法服务于两个现实约束:actor 与 worker 状态跨 Redis Cluster key,不可能用一个强事务同时修改;调用 atelet/ateom/runsc 是外部副作用,失败可能发生在任意位置。因此 workflow 采用“状态已写入就能被下一次请求识别并继续”的模型。

atelet + ateom-gvisor

ateletateom 的分工很清楚:atelet 是 node supervisor,接收 ateapi 的 Run/Checkpoint/Restore 请求;ateom 是 worker pod 内的 gVisor herder,真正执行 runsc。atelet 负责下载/校验 runsc、拉 OCI image、展开 rootfs、生成 OCI config、下载/上传 checkpoint zstd 文件。ateom 负责创建 interior network namespace、建立 veth、安装 nftables、执行 runsc create/start/checkpoint/restore。

当前实现假设一个 worker pod 同时只运行一个 active actor;ateom 的 mutex 和 nftables 表清理逻辑都体现了这一点。