Skip to main content

OpenKruise Agents v0.6.0 发布:让 Agent Sandbox 更安全、更易运维、更省资源

· 阅读需要 1 分钟

关键词:4 层/7 层网络访问控制 · 凭证注入 · CheckpointRestore · PoolAutoscaler · 自动休眠唤醒

v0.3.0 发布时,我们回答的是这样一个问题:Sandbox 交付给 Agent 之后,如何升级、如何变配、如何归属。那篇文章的路线图以两个承诺收尾 —— 用 TrafficPolicy / SecurityProfile 做网络治理,以及用安全身份集成把平台凭证从 Agent 代码中彻底移出去。

OpenKruise Agents v0.6.0 兑现了这两个承诺,并补齐了围绕它们的运维机制:自 v0.3.0 以来共合并 283 个 PR。本文重点展开的四项能力是:

  • 4 层与 7 层网络访问控制,以及 Token 管理 —— TrafficPolicy 管目的地可达性,SecurityProfile 管单次请求,MCP 工具级 ACL,从 Kubernetes Secret 注入凭证;
  • SandboxUpdateOps 支持 CheckpointRestore 与休眠实例升级 —— 无需手工唤醒即可批量升级休眠集群,且升级过程不丢失文件系统;
  • PoolAutoscaler —— 声明式预热池容量,带水位线与 Cron 定时策略;
  • 自动休眠唤醒 —— 探针驱动的闲置识别、定时唤醒、流量唤醒,让闲置 Sandbox 停止消耗 CPU,无需任何人工干预。

把这四件事放在一起看,就是三类客户价值:安全加固(运行不可信代码的 Agent 不再能想访问哪就访问哪,也永远不持有你的 API Key)、日常运维能力提升(批量升级、弹性伸缩、生命周期自动化从脚本变成声明式),以及成本优化(闲置 Sandbox 休眠、预热池夜间缩容、休眠集群照样能升级)。

本文分三部分:让这一切成为可能的架构变化、四项功能的深入解析、以及价值总结与未来规划。


一、架构发生了什么变化​

如果说 v0.3.0 是一个工作负载层,那么 v0.6.0 是一个自带数据面的工作负载层。完整组件模型见架构文档,一句话概括:流量检查、策略下发、身份凭证都变成了独立的一等组件,而不再是外部插件。

alt

1.1 从四个组件到六个组件​

组件v0.6.0 中的职责
sandbox-manager无状态后端服务,对外提供 E2B 兼容的北向 API,负责 Sandbox 生命周期、配额、以及路由与 Traffic Token 编排
sandbox-controller负责 Sandbox、SandboxSet、SandboxClaim 与预热池等资源的协调,并托管准入 Webhook。v0.6.0 中还承载自动休眠唤醒控制器
sandbox-gateway数据面,基于 Envoy Go Filter 构建。入口网关将用户流量代理到 Sandbox,支持 Host/Path 路由、访问令牌与流量唤醒;出口网关代理 Sandbox 的出向流量,并执行策略化的 7 层出口管控
traffic-control-plane新增。istiod 向网关与 Pod 内代理下发 xDS 配置;**出口策略执行器(EPE)**在出向流量上执行 7 层策略、MCP ACL 与令牌注入
agent-runtimeSidecar,提供 E2B envd 兼容的命令、文件与端口(49983)操作能力
traffic-proxy**新增。**Sidecar,作为 Pod 内出口流量策略的 4 层执行点

其中有两个结论值得记住。第一,出向流量不再是 Pod 自己的事 —— 它在 Pod 内被捕获,经过出口网关路由,由一个能看见完整请求(而不只是 socket)的策略引擎做决策。第二,入口网关可以把 Sandbox 唤醒,这正是流量唤醒得以实现、且不需要外部轮询器的原因。

1.2 策略执行链路​

运行了 traffic-proxy 运行时的 Sandbox,其每一个经网关路由的出向请求都会走同一条链路:

Sandbox application container
-> TrafficProxy in-pod capture
-> egress gateway chosen by egress routing
-> Envoy external processing
-> Egress Policy Enforcer decision
-> external service, or a blocked response

职责划分是刻意设计的:EPE 编译 TrafficPolicy / GlobalTrafficPolicy 并下发给数据面,因此 4 层拒绝在到达网关之前就被丢弃。EPE 只对经网关路由的 HTTP 请求做 7 层检查 —— 直通路径上的流量不会到达 EPE,且 7 层无法推翻 4 层的拒绝结论。

1.4 CRD 数量翻倍​

v0.3.0 提供 6 个 CRD,v0.6.0 提供 12 个:

CRD作用域角色
SandboxNamespaced单个沙箱实例,支持完整生命周期操作
SandboxSetNamespaced管理一批同构 Sandbox,负责维护预热池
SandboxTemplateNamespaced不可变的模板版本快照,用于版本追溯
SandboxClaimNamespaced领取一个空闲 Sandbox 并做后处理(原地换镜像、挂载、原地变配)
CheckpointNamespaced运行时快照(内存和/或 rootfs),可用于 fork 新实例
CommitNamespacedAlpha,需开启 Commit 特性门控。将可写层保存为新镜像并推送到镜像仓库
SandboxUpdateOpsNamespaced一次性批量升级已 Claim 的 Sandbox
PoolAutoscalerNamespaced**新增。**声明式预热池容量与 Cron 定时伸缩
TrafficPolicyNamespaced**新增。**3/4 层出口与入口目的地管控
GlobalTrafficPolicyCluster**新增。**集群级 4 层基线
SecurityProfileNamespaced**新增。**7 层请求检查、MCP ACL、凭证注入、审计
GlobalSecurityProfileCluster**新增。**集群级 7 层基线

1.5 E2B 兼容性向前推进,边界也已写明​

北向 API 依然保持 E2B 兼容,且兼容性矩阵现在明确标注了哪些是部分兼容:

  • pause 完全兼容且为同步语义 —— 请求会阻塞直到 Sandbox 进入 Paused;
  • create 部分兼容 —— 支持网络访问控制,create 链路上的 MCP 集成仍在推进中;
  • network 部分兼容 —— 支持 allowOut、denyOut 与 rules;egressProxy 与 maskRequestHost 会被直接拒绝,而不是静默忽略;
  • 尚不支持:预签名上传/下载 URL、日志、指标、Lifecycle Events、Volumes。

二、四项核心能力详解​

2.1 网络访问控制与 Token 管理​

这是本次版本改动最大的部分,它回答了三个不同的问题:Sandbox 可以访问什么、谁可以访问 Sandbox,以及一个大多数平台都做错了的问题:上游 API Key 到底握在谁手里。

4 层:这个目的地到底可不可达​

TrafficPolicy 选中调用方 Pod,并持有一份有序的出口规则列表。每条规则必须声明 to,可选声明 action(allow 或 reject)与 ports 列表。Peer 支持 fqdn、cidr、service、workload,多个 Peer 之间是 OR 关系。

apiVersion: agents.kruise.io/v1alpha1
kind: TrafficPolicy
metadata:
name: sandbox-egress
namespace: default
spec:
selector:
matchLabels:
app: traffic-sample
egress:
rules:
- action: allow
to:
- service:
name: kube-dns
namespace: kube-system
- action: allow
to:
- fqdn: api.example.com
- action: reject
ports:
- protocol: TCP
port: 443
to:
- cidr: 10.0.0.0/8

有三条语义比语法更重要:

  • **一旦策略选中某个 Pod,未匹配到任何 allow 规则的出向流量就会被拒绝。**策略一旦生效就是白名单;
  • 缺失 Peer 字段的规则会被编译器跳过 —— 它不会构成默认拒绝。to 写错一个字段,策略就会被静默削弱;
  • 务必放行集群 DNS Service,否则域名解析失败,所有 FQDN 规则看起来都像是坏了。

GlobalTrafficPolicy 是集群级等价物,用于平台团队统一持有的基线策略。

7 层:这一次具体请求允许做什么​

SecurityProfile 匹配 HTTP 请求并施加动作。每条规则有唯一的 name、至少一个 match 子句,以及 actions。match 中的多个子句之间是 OR,单个子句内所有已填写字段之间是 AND,domains 为必填。

动作集不大,但哪些是终止性动作是必须记住的部分:

动作是否终止行为
block是返回 statusCode(默认 403)与可选 body,不转发上游,并丢弃待执行的变更
bypass是转发请求并跳过后续所有动作与规则,保留已施加的变更
mcpToolPolicy否按工具名允许或拒绝 MCP JSON-RPC tools/call 请求
headerManipulation否设置或移除明文请求头。取值按字面存储 —— 绝不要用它承载凭证
tokenTransformation否从 Secret 或凭证提供方改写请求凭证。受 failStrategy 约束,默认 Block
audit否异步发送 Webhook 事件,永不改变请求决策

评估顺序是一次归并,而不是命名空间内的局部列表:spec.priority 越小越先(默认 1000),其次按创建时间、名称、命名空间排序。全局与命名空间级 Profile 共用同一顺序,完全相同时全局 Profile 排在前面。匹配不是"首条命中即结束" —— 一条宽泛的早期规则之后,后续规则仍可能命中;只有终止性动作会中断链路。单条规则内部,动作按固定顺序执行:bypass、block、mcpToolPolicy、headerManipulation、tokenTransformation,与 YAML 中的书写顺序无关。

下面是一条有代表性的基线,在任意域名上封禁管理路径:

apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: deny-management-paths
namespace: default
spec:
selector:
matchLabels:
app: traffic-sample
rules:
- name: deny-management-paths
match:
- domains:
- "*"
paths:
- type: Prefix
value: /admin
- type: Prefix
value: /console
- type: Prefix
value: /dashboard
actions:
block:
statusCode: 403
body: '{"error":"management paths are blocked"}'

不过,对 Agent 工作负载价值最高的是 SSRF 防护。被 Prompt 注入的代码几乎总会尝试访问内部服务与云元数据端点:

apiVersion: agents.kruise.io/v1alpha1
kind: GlobalSecurityProfile
metadata:
name: cluster-baseline
spec:
selector:
matchLabels:
app: traffic-sample
priority: 50
rules:
- name: deny-metadata-endpoint
match:
- domains:
- metadata.internal
- "*.internal.company.com"
- "*.corp.net"
actions:
block:
statusCode: 403
body: '{"error":"access to internal services is forbidden"}'

注意 priority: 50 —— 集群基线应当刻意排在租户 Profile 之前,且 GlobalSecurityProfile 不应设置 metadata.namespace。

MCP 工具级 ACL​

当 Agent 与 MCP Server 通信时,域名级管控粒度太粗:真正危险的是某个具体工具。mcpToolPolicy 只管 JSON-RPC 的 tools/call,并精确匹配 params.name;tools/list 与 initialize 会直接放行。

apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: mcp-tool-whitelist
namespace: default
spec:
selector:
matchLabels:
app: traffic-sample
rules:
- name: protect-mcp-tools
match:
- domains:
- mcp.example.com
schemes:
- https
paths:
- type: Prefix
value: /mcp
actions:
mcpToolPolicy:
defaultAction: deny
unsupportedVersionAction: deny
denyResponse:
statusCode: 403
body: MCP tool is not permitted
rules:
- method: tools/call
toolNames:
- read_file
- search_docs
action: allow

规则按文档顺序评估,首条命中即生效;toolNames 为空列表表示匹配该方法下的所有工具名。做白名单请使用 defaultAction: deny —— 若设为 defaultAction: allow,则无法解析的 Body 或无法取到工具名的调用会按设计被放行。执行器会缓冲完整 Body,因此超过 8 MiB 的载荷、JSON-RPC 批量请求、以及不支持的编码都会回落到 defaultAction。当前支持的 MCP 协议版本为 2025-06-18、2025-11-25 与 2026-07-28。

凭证注入:你的 API Key 永远不进入 Sandbox​

这一项会彻底改变你与合规团队的对话方式。凭证存放在 Kubernetes Secret 中,出口代理按请求解析它,并在请求即将离开集群时改写出向请求。工作负载与 Agent 代码自始至终只看得见自己那个占位请求头。

apiVersion: v1
kind: Secret
metadata:
name: example-api-credentials
namespace: agent-demo
type: Opaque
stringData:
apiKey: REPLACE_WITH_YOUR_API_KEY
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: example-api-credentials
namespace: agent-demo
spec:
selector:
matchLabels:
app: agent
rules:
- name: inject-example-api-key
match:
- domains:
- api.example.com
schemes:
- https
paths:
- type: Prefix
value: /v1/
actions:
tokenTransformation:
type: ApiKey
failStrategy: Block
credentialRef:
secret:
name: example-api-credentials
apiKey:
targetHeaders:
names:
- authorization
value:
template: "Bearer {{ .Token }}"

由于解析发生在代理侧,凭证不会出现在 Pod Spec、环境变量或 Sandbox Metadata 中 —— 并且轮转 Secret 无需重启 Sandbox 即可生效。credentialRef.secret.namespace 是可选的:SecurityProfile 回落到自身命名空间,GlobalSecurityProfile 回落到各被选中 Pod 所在命名空间。secret 与 credentialProvider 只能设置其一,targetHeaders.cel 支持动态请求头名,failStrategy 默认为 Block,因此凭证缺失时是 fail closed,而不是把一次未认证调用漏出去。

E2B 原生的网络管控​

不想写 CRD 的团队,可以直接用 E2B SDK 表达网络意图,前提是 Sandbox 运行了 traffic-proxy:

from e2b_code_interpreter import Sandbox

sandbox = Sandbox.create(
template="code-interpreter",
network={
"allow_out": ["api.example.com", "10.0.0.0/8"],
"deny_out": ["0.0.0.0/0"],
},
)

需要记住的不对称之处:allowOut 接受 IP、CIDR 与具体 FQDN(拒绝通配符),而 denyOut 只接受 IP 与 CIDR。因此域名过滤要表达为"白名单 + 拒绝 0.0.0.0/0",且 allow 优先于 deny。rules 承载按域名的请求头改写,它不授予可达性。更新走 PUT /sandboxes/{sandboxID}/network 或 sandbox.update_network(...):省略 rules 保留原有链路,传空对象清空,传非空对象整体替换。

这些管控可以叠加成层次:集群作用域的 GlobalTrafficPolicy 与 GlobalSecurityProfile 设定全局基线,命名空间作用域的 TrafficPolicy 与 SecurityProfile 承载租户级规则,Sandbox 级的内联网络管控则作用于单个 Sandbox —— 从全局、租户到沙箱维度,实现多层次、细粒度的网络访问控制。

不能跳过的护栏​

本节对应的四份手册分别是流量访问控制、E2B 网络访问控制、凭证注入与流量访问令牌轮换。手册对能力边界写得很直白,本文也一样:

  • 管控只覆盖经网关路由的流量。HTTPS 检查还额外要求 TLS 终结、签发 CA 以及工作负载信任该 CA;
  • **以 root 运行、或具备 NET_ADMIN / SYS_ADMIN 能力的容器可以绕过 Pod 内 ACL。**请把这些策略与 Kubernetes NetworkPolicy、主机防火墙或云安全组配合使用 —— 这是纵深防御,不是一堵墙;
  • TrafficProxy 保留端口 15001、15006、15012、15020、15021、15090,并以 UID/GID 1337 运行;
  • 伪造 Host 请求头可以绕过 4 层匹配,而这恰恰是 7 层 Profile 存在的理由;
  • 单 Sandbox 的内联规则(agents.kruise.io/security-rules)在 Selector 命中的 Profile 之后评估;编译失败时保留旧规则或不执行任何规则,并通过 epe_profile_stale 与 epe_profile_unenforced 指标(带 scope="pod")暴露;
  • EPE 是每个经网关请求上的一次网络跳转,请独立于网关为它的 Deployment 做容量规划。

2.2 SandboxUpdateOps:CheckpointRestore 与休眠实例升级​

v0.3.0 引入的 SandboxUpdateOps 只有一种模式:Recreate,即销毁并重建 Pod,因此内存、IP 与 rootfs 可写层全部丢失,preUpgrade / postUpgrade 钩子是你把状态带过去的唯一手段。v0.6.0 立刻补上了用户呼声最高的两件事:一种能保住 rootfs 的模式,以及把休眠 Sandbox 纳入批量升级的能力。这两项都需要 v0.6.0,基础链路自 v0.3.0 起可用。详见 Sandbox 升级。

alt

两种升级模式​

模式Rootfs内存IP是否支持更换业务镜像
Recreate(默认)丢失丢失变化支持
CheckpointRestore保留 —— 升级前打快照,升级后恢复丢失变化不支持

CheckpointRestore 用镜像灵活性换取数据连续性。这条约束是硬性的:CheckpointRestore 下不能更换业务容器镜像 —— 一旦更换,恢复回来的 rootfs 就会被丢弃,而这恰恰是该模式的全部意义。你可以做的是滚动 Sidecar 版本,以及修改任何非镜像字段:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxUpdateOps
metadata:
name: upgrade-sidecar
namespace: default
spec:
updateStrategy:
type: CheckpointRestore
patch:
metadata:
annotations:
agents.kruise.io/upgrade-sidecar: "20260714"

这正是全量升级 agent-runtime 或 traffic-proxy 的标准姿势:不动用户数据,不用写备份脚本,不用安排恢复窗口。如果既要换镜像又要保状态,答案仍然是 Recreate 加钩子 —— 在 preUpgrade 中备份到 OSS 或 NAS,在 postUpgrade 中恢复。

升级休眠中的 Sandbox​

v0.6.0 之前,SandboxUpdateOps 只处理 Running 或 Upgrading 状态的 Sandbox。休眠集群对它完全不可见,于是运维被迫走一套尴尬的手工循环:唤醒、升级、再休眠 —— 这也让休眠池长期成为版本漂移的来源。

stateFilter 解决了这个问题:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxUpdateOps
metadata:
name: upgrade-with-paused
namespace: default
spec:
stateFilter:
states:
- Running
- Paused
selector:
matchLabels:
agents.kruise.io/sandbox-template: my-sandbox-pool
updateStrategy:
maxUnavailable: 10%
patch:
spec:
containers:
- name: sandbox
image: my-registry/sandbox-image:v2

控制器会逐个唤醒休眠 Sandbox、完成升级,然后在 spec.paused 仍为 true 时把它重新休眠。集群的最终形态与初始形态一致 —— 休眠的仍然休眠 —— 因此一次升级不会把一个休眠池悄悄变成一笔账单。

2.3 PoolAutoscaler:把预热池容量变成策略​

预热池是 OpenKruise Agents 能做到亚秒级 Claim 的原因,也是平台账单在周六深夜无人使用时依然上涨的原因。PoolAutoscaler 把池子容量从"一个跑 kubectl scale 的定时任务"变成声明式策略。

先说清楚它做什么:PoolAutoscaler 改写 SandboxSet.spec.replicas。它不采集业务指标,不预测流量,也不自己创建或删除 Pod —— 那些是 SandboxSet 控制器的事。它给你的是基于可用容量的水位线反馈,加上时间驱动的覆写。

容量策略​

apiVersion: agents.kruise.io/v1alpha1
kind: PoolAutoscaler
metadata:
name: sandbox-pool-scaler
namespace: default
spec:
scaleTargetRef:
kind: SandboxSet
name: sandbox-pool
minReplicas: 2
maxReplicas: 50
capacityPolicy:
targetAvailable: "50%"
tolerance: "10%"
scaleUp:
stabilizationWindowSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300

targetAvailable: "50%" 表示伸缩器会把可用 Sandbox 数量维持在总副本数的一半 —— 这个缓冲能在池子回补期间吸收一波 Claim 突发。水位线按 ceil(avgReplicas x (target +/- tolerance)%) 计算,tolerance 默认为 10%。非对称的稳定窗口(扩容快、缩容慢)是预热池的正确默认值:用户对短缺是立刻有感的,而对缓慢缩容毫无感知。

Cron 定时策略​

对于已知的流量形态,Cron 更优 —— 它在突发到来之前触发,而不是事后响应:

apiVersion: agents.kruise.io/v1alpha1
kind: PoolAutoscaler
metadata:
name: sandbox-pool-scaler
namespace: default
spec:
scaleTargetRef:
kind: SandboxSet
name: sandbox-pool
minReplicas: 2
maxReplicas: 50
cronPolicies:
- name: weekday-peak
timezone: Asia/Shanghai
schedule: "30 8 * * 1-5"
targetReplicas: 30
- name: weekday-offpeak
timezone: Asia/Shanghai
schedule: "0 20 * * 1-5"
targetReplicas: 5

Cron 触发时优先级更高,且不受容量策略稳定窗口约束,但仍会被 minReplicas / maxReplicas 夹取。请显式设置 timezone —— schedule 是五段式 Cron,校验允许最多 20 条、名称必须唯一。

调参陷阱​

  • 不要设置 targetAvailable: "100%" —— 那样池子只会增长;
  • 缩容可达性有硬性算术约束。绝对值场景下,target + downTolerance 不得超过 minReplicas;百分比场景下,p + q 不得超过 100 x minReplicas / (minReplicas + 1)。否则该策略永远无法触发缩容,而校验是你唯一的提示;
  • tolerance 必须严格小于 targetAvailable;百分比形式的 target 要求 minReplicas 至少为 1;稳定窗口取值范围为 60 到 3600 秒;
  • 校验失败返回 HTTP 422,包括 scaleTargetRef.kind 不是 SandboxSet、maxReplicas 小于等于 0、或 minReplicas 大于 maxReplicas;
  • spec.suspend: true 可以在不删除对象的前提下暂停伸缩器 —— 故障期间的正确动作;
  • **删除 PoolAutoscaler 会把 spec.replicas 留在最后一个值上。**池子不会自己缩回去。

2.4 自动休眠唤醒​

在 Kubernetes 眼里,一个有活跃用户会话的 Claimed Sandbox,和一个四小时没人敲过键盘的 Claimed Sandbox,长得一模一样。自动休眠唤醒让这个差异变得可观测,并据此采取行动。

该能力通过 SandboxSet 的两个顶层 spec 字段配置 —— probes 与 autoPausePolicy —— 且探针驱动的休眠与定时唤醒需要 sandbox-controller 开启 AutoPauseController 特性门控,该门控默认开启。真实节点上的探针还需要集群安装 OpenKruise(kruise-daemon)并开启 KruiseIntegration 特性门控,否则真实节点的探针 condition 会一直处于 Unknown,自动休眠不会触发;虚拟 kubelet 节点不受影响。入向流量唤醒仅适用于已 Claim Sandbox 的经网关路由请求,并需要网关侧的 enable-wake-on-traffic 与 wake-timeout-seconds(默认 60 秒,超时后调用方收到 503 sandbox wake failed)两个参数。这两个都是网关级配置。

探针:只支持 Exec,靠消息驱动​

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxSet
metadata:
name: openclaw-sbs
namespace: default
spec:
probes:
- name: Active
periodSeconds: 30
timeoutSeconds: 5
exec:
command:
- sh
- -c
- |
if openclaw sessions list --active 900 | grep -q .; then
printf 'active'
else
printf 'inactive'
fi

每个探针需要唯一的 name(它会成为 Condition 类型 agents.kruise.io/<name>)、可选的 containerName(默认取第一个容器),并且只支持 exec —— 不支持 HTTP、TCP。命令不会被 shell 包裹,所以请自己写 sh -c。退出码 0 产生 status: "True",stdout 进入 message;探针失败或超时永不触发休眠或唤醒 —— 这是安全的那一侧。

闲置驱动休眠​

  autoPausePolicy:
probe: Active
pause:
whenProbedIdleState:
probe: Active
messageRegex: "^inactive$"
thresholdDuration: 10m

thresholdDuration 为必填且非负,0 表示首次上报闲置即休眠。这里把窗口算术写清楚,便于做容量规划:探针周期 30 秒、探针命令内部使用 15 分钟不活跃窗口、阈值 10 分钟,那么 Sandbox 会在最后一次真实活动之后约 25 分钟休眠。待执行的休眠计划在 status.schedules 中可见,形如 reason: probedIdle 加 nextPauseTime;随后一次 active 读数会把它清除。

预热池中未被 Claim 的 Sandbox 会执行探针,但不参与休眠决策 —— 池子由 PoolAutoscaler 管理,不由自动休眠管理。

定时唤醒​

有些工作负载的闲置是有时刻表的:只在早上九点有意义的 Notebook、只在夜间跑的 RL Rollout。第二个探针可以打印出下次激活时间,控制器会提前把 Sandbox 唤醒:

  autoPausePolicy:
resume:
whenProbedScheduleTime:
probe: Cron
timeFormat: unix
leadTime: 5m

timeFormat 为 unix(默认,正整数秒)或 datetime(必须带时区的 RFC 3339)。leadTime 默认 5m,可以为 0,不可为负;唤醒发生在任务时间减去提前量的时刻,并以 reason: probedSchedule 加 nextResumeTime 呈现。两个经典 Bug:探针打印的是毫秒(请除以 1000),以及在探针内部把本地业务时间转成时间戳,而不是输出带时区的值。

入向流量唤醒​

这条路径是让休眠对面向用户的 Sandbox 变得安全的关键 —— 休眠后的第一个请求会唤醒 Sandbox,而不是失败:

from e2b_code_interpreter import Sandbox

sandbox = Sandbox.create(
template="code-interpreter",
timeout=600,
lifecycle={
"on_timeout": "pause",
"auto_resume": True,
},
)
host = sandbox.get_host(3000)

唤醒之后,超时倒计时会从唤醒那一刻重新开始,使用创建时的 timeout;小于 5 分钟的正值按 5 分钟处理。sandbox.commands.run(...) 与 sandbox.files.write(...) 同样会触发唤醒。在 CRD 层面,同样的重置语义是 autoPausePolicy.resume.onIngressTraffic.pauseTimeout: 5m,它仅适用于设置了 spec.pauseTime 的 Sandbox —— 若未设置或不大于 0,倒计时不会被重置。onIngressTraffic 本身不会休眠任何东西,它只决定唤醒后的行为。

有三条行为是通用的,否则足以耗掉你一个下午:

  • **请求必须通过鉴权。**未授权的请求返回 401,且 Sandbox 保持休眠 —— 流量唤醒不是一个无需认证的门铃;
  • **唤醒成功可以伴随请求失败。**触发唤醒的那次调用可能返回 503 upstream connect error;若它恰好在 Sandbox 正在转入休眠的中途到达,则返回 503 sandbox wake failed。请检查 Sandbox.status.phase 并重试;
  • 预热池中的 Sandbox 仍归其 SandboxSet 所有,因此对它的请求会返回 502 healthy sandbox not found。

三、客户价值、未来规划与社区共建​

3.1 这个版本为你带来了什么​

v0.6.0 之前v0.6.0 之后
安全加固出向流量是 Pod 自己的事;一个被 Prompt 注入的 Sandbox 可以访问内部服务、云元数据端点,以及 MCP Server 暴露的任意工具。上游 API Key 不得不交给 Agent 运行时。长期有效的不透明令牌让重放暴露窗口等于"永远"TrafficPolicy 提供 3/4 层白名单,SecurityProfile 提供 7 层请求检查,MCP 工具白名单,Global* 集群级基线层,凭证在出口代理侧从 Secret 解析且轮转无需重启,以及短期可轮转的 JWT Traffic Access Token
日常运维能力休眠 Sandbox 对批量升级不可见,休眠集群因此漂移。池子容量是一个调用 kubectl scale 的定时任务。闲置识别是某个人的 Shell 脚本SandboxUpdateOps 通过 stateFilter 覆盖 Running 与 Paused,并通过 CheckpointRestore 保留 rootfs;PoolAutoscaler 让容量声明式化,带水位线与 Cron;自动休眠唤醒把闲置识别变成一个探针
成本优化Claimed Sandbox 无论有没有人用都在烧 CPU,预热池按峰值全天候配置闲置 Sandbox 依据探针证据休眠,并按计划或首个请求唤醒;池子在 20:00 缩容、08:30 扩容;CheckpointRestore 升级与休眠集群升级同时避免了数据丢失与不必要的唤醒开销

3.2 未来规划:社区能力建设​

下一阶段的路线图强调社区能力建设 —— 与其他开源社区协作共建,而不是自研一套封闭的技术栈:

  • 与 Kata 社区合作,共建开源 Checkpoint 能力 —— 基于 Kubernetes 1.37 引入的 PodCheckpoint API,与 Kata 社区协作实现开源的 Checkpoint 能力,摆脱当前依赖特定平台的快照后端;
  • 开源存储方案的按需挂载 —— 基于现有的按需挂载框架,实现 MinIO 等开源存储方案的按需挂载能力;
  • 与开源身份系统集成 —— 例如 Keycloak,让平台认证统一对接你既有的身份提供方。

3.3 社区共建​

OpenKruise Agents 完全在开放社区中构建,本次版本有 27 位新贡献者加入。如果你正在 Kubernetes 上运行 Agent Sandbox,参与塑造路线图最快的方式是提 Issue 或加入社区例会。

OpenKruise Agents v0.6.0 已在 GitHub Release 与各大镜像仓库就绪,欢迎升级体验。期待你的反馈和 Pull Request。