在 Kubernetes 上运行 AI Agent 时,一个直觉方案是“一个 Agent 对应一个 Pod”。但 Agent 的运行方式并不像传统 Web 服务:它们可能突然产生大量请求,执行时间很短,也可能创建子 Agent,或者停下来等待人工审批。把每个逻辑 Agent 固定绑定到一个 Pod,容易造成资源浪费和调度僵化。
kagent 项目提出了一个更值得讨论的方向:Pod 更适合作为长期存在的执行 Worker,而不是每个逻辑 Agent 的身份容器。Agent-substrate 则在 Worker Pod 之上增加控制平面,把逻辑上的 Actor 调度到现有 Worker 上。
为什么“一 Agent 一 Pod”不够合适
传统 Deployment 通常假设实例会持续运行,并且每个实例都承载相对稳定的服务流量。AI Agent 的生命周期却更接近任务:
- Agent 可能只执行一次短任务,随后很长时间没有工作。
- 请求量具有突发性,闲时为每个 Agent 保留 Pod 会浪费 CPU 和内存。
- 一个 Agent 可能根据任务动态创建子 Agent,运行规模难以预先确定。
- Agent 可能等待人工批准、外部事件或工具返回结果,期间并不需要持续占用完整执行环境。
如果每个 Agent 都拥有独立 Pod,系统获得了清晰的隔离边界,但也付出了调度延迟、镜像启动开销和空闲资源成本。更重要的是,Kubernetes 看到的是一组 Pod,而业务真正需要管理的是一组逻辑 Actor 及其任务状态,两者并不完全等价。
把身份和执行环境拆开
可以把系统分成两层:
- Actor:逻辑上的 Agent,拥有身份、配置、会话状态和待执行任务。
- Worker Pod:长期运行的执行进程,负责承载一个或多个 Actor 的实际工作。
- 控制平面:负责排队、调度、唤醒、暂停和恢复 Actor。
这种模型让 Pod 成为可复用的计算资源池。Actor 有任务时被调度到 Worker;任务完成、等待审批或暂时休眠时,Worker 可以继续执行其他 Actor。对于突发负载,系统可以扩展 Worker 数量,而不必为每一个逻辑 Agent 预先创建 Pod。
这并不意味着所有 Agent 都应该共享 Worker。需要强隔离、独立网络策略、不同运行时或高风险工具权限的 Agent,仍然可能适合独占 Pod。关键变化在于:独占 Pod 应该是经过权衡后的调度策略,而不是默认的身份映射。
一个可改造的 Kubernetes 起点
下面的 YAML 是一个最小化的实践示例。它把 Worker 做成长期运行的 Deployment,并通过环境变量声明并发能力。ACTOR_QUEUE、镜像名和资源大小需要替换成实际系统中的配置;示例中的 Actor 调度协议是应用层约定,不是 Kubernetes 内置对象。
apiVersion: apps/v1
kind: Deployment
metadata:
name: agent-worker
spec:
replicas: 2
selector:
matchLabels:
app: agent-worker
template:
metadata:
labels:
app: agent-worker
spec:
containers:
- name: worker
image: example.com/agent-worker:latest
env:
- name: ACTOR_QUEUE
value: agent-actors
- name: MAX_ACTORS_PER_WORKER
value: "8"
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "2Gi"
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
可以用下面的命令部署和检查 Worker:
kubectl apply -f agent-worker.yaml
kubectl rollout status deployment/agent-worker
kubectl get pods -l app=agent-worker -o wide
在这个模型中,控制平面可以向 agent-actors 队列写入类似下面的任务消息:
{
"actor_id": "research-agent-42",
"task_id": "task-2025-001",
"input": "Summarize the latest incident reports",
"resume_token": null,
"requires_human_approval": false
}
Worker 领取消息后加载 Actor 配置,执行任务,并把状态写回持久化存储。若任务需要人工审批,Worker 可以提交等待状态并释放执行槽位;审批完成后,控制平面再把带有 resume_token 的任务重新投递。这样,等待过程不会等同于持续占用一个 Pod。
控制平面需要负责什么
当 Agent 从 Pod 中抽离出来,控制平面就成为系统的核心。它至少需要处理以下问题:
- 任务路由:根据 Actor 能力、租户、工具权限或数据位置选择 Worker。
- 并发限制:避免一个突发 Actor 抢占整个 Worker 的资源。
- 状态恢复:Worker 崩溃后,任务能够重新排队,避免依赖进程内状态。
- 审批暂停:将等待人工的 Actor 标记为挂起,而不是持续运行空闲进程。
- 子 Agent 管理:为动态创建的子 Actor 分配配额、父子关系和生命周期。
- 可观测性:日志、指标和追踪需要同时包含
actor_id、task_id与worker_id。
这里有一个实际边界:Worker 复用会扩大故障和安全影响范围。如果多个 Actor 共享一个进程,未隔离的内存、文件、缓存或凭据都可能导致数据越界。因此,Worker 设计必须明确隔离级别,可以按进程、容器、命名空间或独立 Pod 分层处理。
采用前的检查清单
- Agent 是否大部分时间处于空闲、等待或人工审批状态?
- Agent 的任务是否可以序列化,并在 Worker 重启后恢复?
- 是否已经有可靠的队列、状态存储和幂等机制?
- 不同 Actor 之间需要什么级别的网络、文件系统和凭据隔离?
- Worker 的并发上限能否通过指标验证,而不是凭经验设置?
- 是否能按 Actor 维度追踪延迟、失败、重试和资源消耗?
如果 Agent 是稳定运行的长生命周期服务,或者每个 Agent 都必须拥有强隔离环境,“一 Agent 一 Pod”仍然是合理选择。对于突发、短时、可暂停、可生成子任务的 Agent,优先考虑“Actor 负责逻辑身份,Worker Pod 负责执行资源”的架构,通常更贴近真实工作负载,也给调度和成本优化留下了空间。