欢迎光临
我们一直在努力

沙盒(三):Firecracker、Jupyter Kernel、E2B、AIO、k8s-sigs、Agent-Sandbox

沙盒系列文章:

  • 沙盒(一):介绍、原理、AppArmor、DevContainer、GitHub Codespaces、GitPod、Ona、Theia、DevPod、Open VS Code
  • 沙盒(二)开源项目汇总:Coder、CodeSandbox、Distrobox

进入AI、LLM时代,沙盒技术也迎来不少变革。AI时代的沙盒不是传统意义上"限制型"的沙箱,而是一个全新的基础设施层:它既要提供极致的隔离安全,又要支持毫秒级的启动速度;既要兼容多语言运行时,又要暴露简洁的REST/gRPC API供AI Agent调用;既要能在云端弹性扩缩,又要能自托管到私有网络。

Firecracker

官网,AWS开源(GitHub,35.2K Star,2.5K Fork)轻量级虚拟化运行环境,基于Rust语言编写、极简VMM(Virtual Machine Monitor),可在AWS云上和本地环境中使用。Firecracker MicroVM同时具备传统虚拟机的安全性和工作负载隔离能力以及容器的速度和资源利用率。

与QEMU、KVM这种庞然大物不同,Firecracker只做一件事:快速启动轻量级microVM。去掉传统虚拟机模拟器中的一切非必要组件(ACPI、BIOS、PCI设备模拟等),只保留最核心的设备模型:virtio-net、virtio-blk、serial console。

工作示意图 在这里插入图片描述

关键特性:

特性数值说明
最小内存 5MB 比同类方案低1-2个数量级
启动时间 125ms 从创建到SSH就绪
微VM开销 <1% 相较于裸金属(bare-metal)的性能损失
安全边界 jailer 独立chroot+cgroup+seccomp

传统虚拟机启动慢,主要是因为BIOS/UEFI初始化、内核解压、设备枚举、systemd初始化等耗时。Firecracker优化三方面:

  • 精简内核:使用定制的小型Linux内核,去掉大量不需要的驱动和模块
  • 无bootloader:Firecracker直接将内核加载到内存,跳过GRUB等引导加载器
  • 最小化设备模型:只模拟virtio-net和virtio-blk,减少设备枚举时间
  • 每个microVM启动时都会通过jailer进程设置:

    • chroot:每个VM被限制在自己的文件系统根中
    • cgroup:CPU/内存/网络带宽都有严格上限
    • seccomp-bpf:限制系统调用白名单

    配置示例:

    {
    "vcpu_count": 2,
    "mem_size_mib": 256,
    "ht_enabled": false,
    "boot_args": "console=ttyS0 reboot=k panic=1 pci=off",
    "drives": [
    {
    "drive_id": "rootfs",
    "path_on_host": "/srv/jailer/firecracker/rootfs.ext4",
    "is_root_device": true,
    "is_read_only": false
    }
    ],
    "network_interfaces": [
    {
    "iface_id": "eth0",
    "host_dev_name": "tap0"
    }
    ]
    }

    运行在为Firecracker优化过的Amazon裸金属EC2服务器上的MicroVM是多租户容器服务的理想选择,可为最新的微服务或无服务器架构的现代应用提供方便、敏捷的开发和部署环境。

    推荐阅读:深度解析AWS Firecracker原理篇–虚拟化与容器运行时技术

    Jupyter Kernel

    即Jupyter内核,提供编程语言支持的核心组件,就是编译器。Jupyter默认使用IPython作为其内核,支持Python,IPython内核提供强大Python交互式计算环境。此外,Jupyter还支持其他内核,如R、Julia等,意味着,在Jupyter中可使用许多其他语言。

    虚拟环境是Python环境的副本,独立于系统全局Python环境。通过虚拟环境,可在不同项目中使用不同的库和库版本,避免冲突。在Jupyter中,可将虚拟环境添加为Kernel,从而使用该虚拟环境来运行代码:

    # 激活虚拟环境
    conda activate myenv
    # 安装ipykernel
    conda install ipykernel
    # 将虚拟环境添加为Kernel
    python -m ipykernel install –user –name myenv –display-name "My Environment"

    E2B

    官网,End-to-End Bytes缩写,AI Agent领域最知名的云沙盒平台之一,使用Python语言,基于Firecracker,为Agent提供安全沙盒化执行环境,让LLM生成的代码在一个完全隔离的微型虚拟机中运行。

    使用HashiCorp Nomad作为调度器,Consul作为服务发现,组合优势:

    • 轻量级调度:Nomad比k8s更轻,单二进制部署
    • 批量作业优化:沙盒本质上是短生命周期批量作业
    • 资源打包:Nomad可更高效地将microVM packing到物理机

    并没有为每种语言实现独立引擎,而是利用Jupyter内核作为统一的语言执行通道:

    #mermaid-svg-jnSv4OpAEwrGg0vw{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jnSv4OpAEwrGg0vw .error-icon{fill:#552222;}#mermaid-svg-jnSv4OpAEwrGg0vw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jnSv4OpAEwrGg0vw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jnSv4OpAEwrGg0vw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jnSv4OpAEwrGg0vw .marker.cross{stroke:#333333;}#mermaid-svg-jnSv4OpAEwrGg0vw svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jnSv4OpAEwrGg0vw p{margin:0;}#mermaid-svg-jnSv4OpAEwrGg0vw .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw .cluster-label text{fill:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw .cluster-label span{color:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw .cluster-label span p{background-color:transparent;}#mermaid-svg-jnSv4OpAEwrGg0vw .label text,#mermaid-svg-jnSv4OpAEwrGg0vw span{fill:#333;color:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw .node rect,#mermaid-svg-jnSv4OpAEwrGg0vw .node circle,#mermaid-svg-jnSv4OpAEwrGg0vw .node ellipse,#mermaid-svg-jnSv4OpAEwrGg0vw .node polygon,#mermaid-svg-jnSv4OpAEwrGg0vw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jnSv4OpAEwrGg0vw .rough-node .label text,#mermaid-svg-jnSv4OpAEwrGg0vw .node .label text,#mermaid-svg-jnSv4OpAEwrGg0vw .image-shape .label,#mermaid-svg-jnSv4OpAEwrGg0vw .icon-shape .label{text-anchor:middle;}#mermaid-svg-jnSv4OpAEwrGg0vw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jnSv4OpAEwrGg0vw .rough-node .label,#mermaid-svg-jnSv4OpAEwrGg0vw .node .label,#mermaid-svg-jnSv4OpAEwrGg0vw .image-shape .label,#mermaid-svg-jnSv4OpAEwrGg0vw .icon-shape .label{text-align:center;}#mermaid-svg-jnSv4OpAEwrGg0vw .node.clickable{cursor:pointer;}#mermaid-svg-jnSv4OpAEwrGg0vw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jnSv4OpAEwrGg0vw .arrowheadPath{fill:#333333;}#mermaid-svg-jnSv4OpAEwrGg0vw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jnSv4OpAEwrGg0vw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jnSv4OpAEwrGg0vw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jnSv4OpAEwrGg0vw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jnSv4OpAEwrGg0vw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jnSv4OpAEwrGg0vw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jnSv4OpAEwrGg0vw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jnSv4OpAEwrGg0vw .cluster text{fill:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw .cluster span{color:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jnSv4OpAEwrGg0vw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jnSv4OpAEwrGg0vw rect.text{fill:none;stroke-width:0;}#mermaid-svg-jnSv4OpAEwrGg0vw .icon-shape,#mermaid-svg-jnSv4OpAEwrGg0vw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jnSv4OpAEwrGg0vw .icon-shape p,#mermaid-svg-jnSv4OpAEwrGg0vw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jnSv4OpAEwrGg0vw .icon-shape .label rect,#mermaid-svg-jnSv4OpAEwrGg0vw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jnSv4OpAEwrGg0vw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jnSv4OpAEwrGg0vw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jnSv4OpAEwrGg0vw :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}#mermaid-svg-jnSv4OpAEwrGg0vw .container>*{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:2px!important;}#mermaid-svg-jnSv4OpAEwrGg0vw .container span{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:2px!important;}#mermaid-svg-jnSv4OpAEwrGg0vw .module>*{fill:#e3f2fd!important;stroke:#0d6efd!important;stroke-width:1px!important;}#mermaid-svg-jnSv4OpAEwrGg0vw .module span{fill:#e3f2fd!important;stroke:#0d6efd!important;stroke-width:1px!important;}#mermaid-svg-jnSv4OpAEwrGg0vw .kernel>*{fill:#d1e7dd!important;stroke:#198754!important;stroke-width:1px!important;}#mermaid-svg-jnSv4OpAEwrGg0vw .kernel span{fill:#d1e7dd!important;stroke:#198754!important;stroke-width:1px!important;}

    E2B Sandbox (microVM)

    Jupyter Gateway

    WebSocket (Jupyter Kernel Protocol)

    IPython

    IJava

    gophernotes

    ITypeScript

    gRPC 协议适配层(统一语言接口,屏蔽内核差异)

    Jupyter内核已经是一个非常成熟的REPL协议,天然支持代码执行、状态保持、变量查看、中断等功能。E2B只需在Jupyter之上封装一层gRPC接口,即可快速支持多种语言。

    除提供SaaS平台,采用按需计费模式:

    • Sandbox Session:按沙盒存在时间收费(美元/分钟)
    • 存储:snapshot持久化额外收费
    • Team Plan:提供自定义镜像和团队管理功能

    此外,在GitHub开源社区维护一系列项目:

    • awesome-ai-agents:29K Star,3.1K Fork,收录一系列自治Agent
    • E2B:13K Star,950 Fork,主体项目
    • fragments:6.3K Star,867 Fork,用于构建应用的Next.js模板
    • Code-Interpreter:2.4K Star,218 Fork,代码解释器,即Python、JS/TS SDK
    • open-computer-use,2.1K Star,246 Fork,参考AI浏览器技术栈:Browser Use、Computer Use、Mobile Use

    优点:

    • Firecracker microVM提供硬件级隔离,安全性一流
    • 125ms启动,接近容器的启动速度
    • 多语言支持成熟(Python/JS/Java/Go/Ruby)
    • SDK设计简洁,AI Agent集成方便
    • Jupyter内核协议成熟稳定

    缺点:

    • Firecracker内核虚拟化在各云环境的兼容性不同
    • 长任务场景下成本较高(按分钟计费)
    • IPython内核在大型输出时内存占用高

    实战

    E2B提供Python和JavaScript两大SDK。

    通过pip安装:pip install e2b

    Python SDK示例:

    from e2b import Sandbox

    # 创建Python沙盒
    sandbox = Sandbox(template="base")
    # 执行代码
    code = """
    import math
    result = math.factorial(100)
    print(f"100! = {result}")
    """

    execution = sandbox.run_code(code)
    print(execution.logs.stdout)
    # 创建文件
    sandbox.files.write("/tmp/data.txt", "hello e2b")
    # 读取文件
    content = sandbox.files.read("/tmp/data.txt")
    # 安装包
    sandbox.commands.run("pip install requests")
    # 清理
    sandbox.close()

    通过npm安装:npm install e2b

    JavaScript SDK示例:

    import { Sandbox } from 'e2b';

    const sandbox = await Sandbox.create({ template: 'base' });
    const { stdout } = await sandbox.runCode('print("Hello from E2B!")');
    console.log(stdout);
    await sandbox.kill();

    OpenSandbox

    另起一篇,参考阿里开源沙盒项目OpenSandbox。

    AIO

    论文,官网,AIO Sandbox,Python语言编写、开源(GitHub,5.3K Star,475 Fork) 一体化(all-in-one)的代理沙箱环境,将浏览器、Shell、文件、MCP操作和VSCode服务器集成在Docker容器中。基于云原生轻量级沙箱技术构建,为AI代理和开发人员提供统一安全的执行环境。

    架构图

    #mermaid-svg-SM5tarwuzkNzYaCJ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SM5tarwuzkNzYaCJ .error-icon{fill:#552222;}#mermaid-svg-SM5tarwuzkNzYaCJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SM5tarwuzkNzYaCJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SM5tarwuzkNzYaCJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SM5tarwuzkNzYaCJ .marker.cross{stroke:#333333;}#mermaid-svg-SM5tarwuzkNzYaCJ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SM5tarwuzkNzYaCJ p{margin:0;}#mermaid-svg-SM5tarwuzkNzYaCJ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ .cluster-label text{fill:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ .cluster-label span{color:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ .cluster-label span p{background-color:transparent;}#mermaid-svg-SM5tarwuzkNzYaCJ .label text,#mermaid-svg-SM5tarwuzkNzYaCJ span{fill:#333;color:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ .node rect,#mermaid-svg-SM5tarwuzkNzYaCJ .node circle,#mermaid-svg-SM5tarwuzkNzYaCJ .node ellipse,#mermaid-svg-SM5tarwuzkNzYaCJ .node polygon,#mermaid-svg-SM5tarwuzkNzYaCJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SM5tarwuzkNzYaCJ .rough-node .label text,#mermaid-svg-SM5tarwuzkNzYaCJ .node .label text,#mermaid-svg-SM5tarwuzkNzYaCJ .image-shape .label,#mermaid-svg-SM5tarwuzkNzYaCJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-SM5tarwuzkNzYaCJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SM5tarwuzkNzYaCJ .rough-node .label,#mermaid-svg-SM5tarwuzkNzYaCJ .node .label,#mermaid-svg-SM5tarwuzkNzYaCJ .image-shape .label,#mermaid-svg-SM5tarwuzkNzYaCJ .icon-shape .label{text-align:center;}#mermaid-svg-SM5tarwuzkNzYaCJ .node.clickable{cursor:pointer;}#mermaid-svg-SM5tarwuzkNzYaCJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SM5tarwuzkNzYaCJ .arrowheadPath{fill:#333333;}#mermaid-svg-SM5tarwuzkNzYaCJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SM5tarwuzkNzYaCJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SM5tarwuzkNzYaCJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SM5tarwuzkNzYaCJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SM5tarwuzkNzYaCJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SM5tarwuzkNzYaCJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SM5tarwuzkNzYaCJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SM5tarwuzkNzYaCJ .cluster text{fill:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ .cluster span{color:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SM5tarwuzkNzYaCJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SM5tarwuzkNzYaCJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-SM5tarwuzkNzYaCJ .icon-shape,#mermaid-svg-SM5tarwuzkNzYaCJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SM5tarwuzkNzYaCJ .icon-shape p,#mermaid-svg-SM5tarwuzkNzYaCJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SM5tarwuzkNzYaCJ .icon-shape .label rect,#mermaid-svg-SM5tarwuzkNzYaCJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SM5tarwuzkNzYaCJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SM5tarwuzkNzYaCJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SM5tarwuzkNzYaCJ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}#mermaid-svg-SM5tarwuzkNzYaCJ .layerBox>*{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:2px!important;stroke-dasharray:4 4!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .layerBox span{fill:#f8f9fa!important;stroke:#adb5bd!important;stroke-width:2px!important;stroke-dasharray:4 4!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .apiNode>*{fill:#e3f2fd!important;stroke:#1976d2!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .apiNode span{fill:#e3f2fd!important;stroke:#1976d2!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .orchestNode>*{fill:#fff3e0!important;stroke:#f57c00!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .orchestNode span{fill:#fff3e0!important;stroke:#f57c00!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .k8sNode>*{fill:#e8f5e9!important;stroke:#388e3c!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .k8sNode span{fill:#e8f5e9!important;stroke:#388e3c!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .routeNode>*{fill:#f3e5f5!important;stroke:#7b1fa2!important;stroke-width:1px!important;}#mermaid-svg-SM5tarwuzkNzYaCJ .routeNode span{fill:#f3e5f5!important;stroke:#7b1fa2!important;stroke-width:1px!important;}

    路由模式

    路径路由: /e2b/v1/sandboxes/{id}

    子域名路由: {id}.sandbox.example.com

    Kubernetes集群

    Sandbox1(E2B 兼容)

    Sandbox2(E2B 兼容)

    SandboxN(E2B 兼容)

    沙盒编排器

    实例管理

    模板管理

    资源调度

    API网关(E2B协议兼容)

    POST /e2b/v1/sandboxes→ 创建沙盒

    GET /e2b/v1/sandboxes/{id}→ 查询沙盒

    POST /e2b/v1/sandboxes/{id}/close→ 关闭

    POST /e2b/v1/sandboxes/{id}/refreshes→ 续期

    支持两种路由模式:

    • 路径路由模式:Path-based Routing,https://sandbox.example.com/e2b/v1/sandboxes/{sandbox_id}
    • 子域名路由模式:Subdomain-based Routing,https://{sandbox_id}.sandbox.example.com

    子域名路由的优势:

    • 每个沙盒有独立的子域名,便于网络策略隔离
    • 减少路径解析开销
    • 更符合RESTful设计规范

    核心API:

    • /v1/sandbox:获取沙盒环境信息
    • /v1/shell/exec:执行shell命令
    • /v1/file/read:读取文件内容
    • /v1/file/write:写入文件内容
    • /v1/browser/screenshot:浏览器截图
    • /v1/jupyter/execute:执行Jupyter代码

    暴露的MCP服务器及其工具能力

    服务可用工具
    browser navigate,screenshot,click,type,scroll
    file read,write,list,search,replace
    shell exec,create_session,kill
    markitdown convert,extract_text,extract_images

    实战

    基于Docker Compose部署:

    version: '3.8'
    services:
    sandbox:
    container_name: aio-sandbox
    image: ghcr.io/agent-infra/sandbox:latest
    volumes:
    – /tmp/gem/vite-project:/home/gem/vite-project
    security_opt:
    – seccomp:unconfined
    extra_hosts:
    "host.docker.internal:host-gateway"
    restart: "unless-stopped"
    shm_size: "2gb"
    ports:
    "127.0.0.1:${HOST_PORT:-8080}:8080"
    environment:
    PROXY_SERVER: ${PROXY_SERVER:-host.docker.internal:7890}
    JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY:-}
    DNS_OVER_HTTPS_TEMPLATES: ${DNS_OVER_HTTPS_TEMPLATES:-}
    WORKSPACE: ${WORKSPACE:-"/home/gem"}
    HOMEPAGE: ${HOMEPAGE:-}
    BROWSER_EXTRA_ARGS: ${BROWSER_EXTRA_ARGS:-}
    TZ: ${TZ:-Asia/Singapore}
    WAIT_PORTS: ${WAIT_PORTS:-}

    执行命令docker compose up -d,没问题的话,将得到沙盒服务器:http://localhost:8080。

    当然也支持通过k8s Yaml文件部署:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: aiosandbox
    spec:
    replicas: 2
    selector:
    matchLabels:
    app: aiosandbox
    template:
    metadata:
    labels:
    app: aiosandbox
    spec:
    containers:
    name: aiosandbox
    image: ghcr.io/agentinfra/sandbox:latest
    ports:
    containerPort: 8080
    resources:
    limits:
    memory: "2Gi"
    cpu: "1000m"

    官方提供Python、TypeScript/JavaScript、Go等语言SDK。

    通过pip安装:pip install agent-sandbox

    Python示例:

    from agent_sandbox import Sandbox

    # 初始化客户端
    client = Sandbox(base_url="http://localhost:8080")
    home_dir = client.sandbox.get_context().home_dir
    # 执行shell命令
    result = client.shell.exec_command(command="ls -la")
    print(result.data.output)
    # 文件操作
    content = client.file.read_file(file=f"{home_dir}/.bashrc")
    # 浏览器自动化
    screenshot = client.browser.screenshot()

    通过npm安装:npm install @agent-infra/sandbox

    TypeScript示例:

    import { Sandbox } from '@agent-infra/sandbox';

    const sandbox = new Sandbox({ baseURL: 'http://localhost:8080' });
    const result = await sandbox.shell.exec({ command: 'ls -la' });
    console.log(result.output);
    const content = await sandbox.file.read({ path: '/home/gem/.bashrc' });
    const screenshot = await sandbox.browser.screenshot();

    安装Go SDK:go get github.com/agent-infra/sandbox-sdk-go

    Go示例省略。

    将网页转换为Markdown格式,并嵌入屏幕截图:

    import asyncio
    import base64
    from playwright.async_api import async_playwright
    from agent_sandbox import Sandbox

    async def site_to_markdown():
    c = Sandbox(base_url="http://localhost:8080")
    home_dir = c.sandbox.get_context().home_dir
    # 浏览器自动下载HTML
    async with async_playwright() as p:
    browser_info = c.browser.get_info().data
    page = await (await p.chromium.connect_over_cdp(browser_info.cdp_url)).new_page()
    await page.goto("https://example.com", wait_until="networkidle")
    html = await page.content()
    screenshot_b64 = base64.b64encode(await page.screenshot()).decode('utf-8')

    # Jupyter,在沙盒内将HTML转换为markdown
    c.jupyter.execute_code(code=f"""
    from markdownify import markdownify
    html = '''
    {html}'''
    screenshot_b64 = "
    {screenshot_b64}"

    md = f"{{markdownify(html)}}\\\\n\\\\n![Screenshot](data:image/png;base64,{{screenshot_b64}})"
    with open('{home_dir}/site.md', 'w') as f:
    f.write(md)
    print("Done!")
    """
    )

    list_result = c.shell.exec_command(command=f"ls -lh {home_dir}")
    print(f"Files in sandbox: {list_result.data.output}")

    return c.file.read_file(file=f"{home_dir}/site.md").data.content

    if __name__ == "__main__":
    result = asyncio.run(site_to_markdown())
    print(f"Markdown saved successfully!")

    官方GitHub还有更多示例代码,如集成Browser Use、LangChain、OpenAI助手等。

    k8s-sigs

    项目主页,使用Go+Python语言开发的开源(GitHub,3K Star,370 Fork)项目,旨在开发k8s的沙箱CRD和控制器。

    架构示意图

    #mermaid-svg-QbWLnLOOp50cOM69{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QbWLnLOOp50cOM69 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QbWLnLOOp50cOM69 .error-icon{fill:#552222;}#mermaid-svg-QbWLnLOOp50cOM69 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QbWLnLOOp50cOM69 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QbWLnLOOp50cOM69 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QbWLnLOOp50cOM69 .marker.cross{stroke:#333333;}#mermaid-svg-QbWLnLOOp50cOM69 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QbWLnLOOp50cOM69 p{margin:0;}#mermaid-svg-QbWLnLOOp50cOM69 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-QbWLnLOOp50cOM69 .cluster-label text{fill:#333;}#mermaid-svg-QbWLnLOOp50cOM69 .cluster-label span{color:#333;}#mermaid-svg-QbWLnLOOp50cOM69 .cluster-label span p{background-color:transparent;}#mermaid-svg-QbWLnLOOp50cOM69 .label text,#mermaid-svg-QbWLnLOOp50cOM69 span{fill:#333;color:#333;}#mermaid-svg-QbWLnLOOp50cOM69 .node rect,#mermaid-svg-QbWLnLOOp50cOM69 .node circle,#mermaid-svg-QbWLnLOOp50cOM69 .node ellipse,#mermaid-svg-QbWLnLOOp50cOM69 .node polygon,#mermaid-svg-QbWLnLOOp50cOM69 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QbWLnLOOp50cOM69 .rough-node .label text,#mermaid-svg-QbWLnLOOp50cOM69 .node .label text,#mermaid-svg-QbWLnLOOp50cOM69 .image-shape .label,#mermaid-svg-QbWLnLOOp50cOM69 .icon-shape .label{text-anchor:middle;}#mermaid-svg-QbWLnLOOp50cOM69 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QbWLnLOOp50cOM69 .rough-node .label,#mermaid-svg-QbWLnLOOp50cOM69 .node .label,#mermaid-svg-QbWLnLOOp50cOM69 .image-shape .label,#mermaid-svg-QbWLnLOOp50cOM69 .icon-shape .label{text-align:center;}#mermaid-svg-QbWLnLOOp50cOM69 .node.clickable{cursor:pointer;}#mermaid-svg-QbWLnLOOp50cOM69 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QbWLnLOOp50cOM69 .arrowheadPath{fill:#333333;}#mermaid-svg-QbWLnLOOp50cOM69 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QbWLnLOOp50cOM69 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QbWLnLOOp50cOM69 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QbWLnLOOp50cOM69 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QbWLnLOOp50cOM69 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QbWLnLOOp50cOM69 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QbWLnLOOp50cOM69 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QbWLnLOOp50cOM69 .cluster text{fill:#333;}#mermaid-svg-QbWLnLOOp50cOM69 .cluster span{color:#333;}#mermaid-svg-QbWLnLOOp50cOM69 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QbWLnLOOp50cOM69 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QbWLnLOOp50cOM69 rect.text{fill:none;stroke-width:0;}#mermaid-svg-QbWLnLOOp50cOM69 .icon-shape,#mermaid-svg-QbWLnLOOp50cOM69 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QbWLnLOOp50cOM69 .icon-shape p,#mermaid-svg-QbWLnLOOp50cOM69 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QbWLnLOOp50cOM69 .icon-shape .label rect,#mermaid-svg-QbWLnLOOp50cOM69 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QbWLnLOOp50cOM69 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QbWLnLOOp50cOM69 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QbWLnLOOp50cOM69 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Extensions

    creates

    creates

    references

    adopts

    adopts sandboxes from

    creates Pod

    pre-warms sandboxes

    User

    SandboxClaim

    SandboxTemplate

    Sandbox

    Pod

    Sandbox Runtime

    SandboxWarmPool

    Agent-Sandbox

    项目主页,使用Go语言开发,完全兼容E2B协议的开源(GitHub,158 Star,15 Fork)项目,目标是提供可自托管的E2B替代方案,所有基于E2B SDK开发的应用,只需切换endpoint即可迁移到Agent-Sandbox。

    架构图

    #mermaid-svg-o1oPKRWJlqBK7YDU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-o1oPKRWJlqBK7YDU .error-icon{fill:#552222;}#mermaid-svg-o1oPKRWJlqBK7YDU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-o1oPKRWJlqBK7YDU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-o1oPKRWJlqBK7YDU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-o1oPKRWJlqBK7YDU .marker.cross{stroke:#333333;}#mermaid-svg-o1oPKRWJlqBK7YDU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-o1oPKRWJlqBK7YDU p{margin:0;}#mermaid-svg-o1oPKRWJlqBK7YDU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU .cluster-label text{fill:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU .cluster-label span{color:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU .cluster-label span p{background-color:transparent;}#mermaid-svg-o1oPKRWJlqBK7YDU .label text,#mermaid-svg-o1oPKRWJlqBK7YDU span{fill:#333;color:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU .node rect,#mermaid-svg-o1oPKRWJlqBK7YDU .node circle,#mermaid-svg-o1oPKRWJlqBK7YDU .node ellipse,#mermaid-svg-o1oPKRWJlqBK7YDU .node polygon,#mermaid-svg-o1oPKRWJlqBK7YDU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-o1oPKRWJlqBK7YDU .rough-node .label text,#mermaid-svg-o1oPKRWJlqBK7YDU .node .label text,#mermaid-svg-o1oPKRWJlqBK7YDU .image-shape .label,#mermaid-svg-o1oPKRWJlqBK7YDU .icon-shape .label{text-anchor:middle;}#mermaid-svg-o1oPKRWJlqBK7YDU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-o1oPKRWJlqBK7YDU .rough-node .label,#mermaid-svg-o1oPKRWJlqBK7YDU .node .label,#mermaid-svg-o1oPKRWJlqBK7YDU .image-shape .label,#mermaid-svg-o1oPKRWJlqBK7YDU .icon-shape .label{text-align:center;}#mermaid-svg-o1oPKRWJlqBK7YDU .node.clickable{cursor:pointer;}#mermaid-svg-o1oPKRWJlqBK7YDU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-o1oPKRWJlqBK7YDU .arrowheadPath{fill:#333333;}#mermaid-svg-o1oPKRWJlqBK7YDU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-o1oPKRWJlqBK7YDU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-o1oPKRWJlqBK7YDU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o1oPKRWJlqBK7YDU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-o1oPKRWJlqBK7YDU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o1oPKRWJlqBK7YDU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-o1oPKRWJlqBK7YDU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-o1oPKRWJlqBK7YDU .cluster text{fill:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU .cluster span{color:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-o1oPKRWJlqBK7YDU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-o1oPKRWJlqBK7YDU rect.text{fill:none;stroke-width:0;}#mermaid-svg-o1oPKRWJlqBK7YDU .icon-shape,#mermaid-svg-o1oPKRWJlqBK7YDU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o1oPKRWJlqBK7YDU .icon-shape p,#mermaid-svg-o1oPKRWJlqBK7YDU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-o1oPKRWJlqBK7YDU .icon-shape .label rect,#mermaid-svg-o1oPKRWJlqBK7YDU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o1oPKRWJlqBK7YDU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-o1oPKRWJlqBK7YDU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-o1oPKRWJlqBK7YDU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}#mermaid-svg-o1oPKRWJlqBK7YDU .agent>*{fill:#f9f!important;stroke:#333!important;stroke-width:3px!important;}#mermaid-svg-o1oPKRWJlqBK7YDU .agent span{fill:#f9f!important;stroke:#333!important;stroke-width:3px!important;}

    Execute Code

    Browse Web

    Terminal Access

    File R/W

    State Persistence

    Shared Storage

    Agent A

    Agent-Sandbox Auto CRUD Sandboxes

    Agent B

    Agent C

    Agent …

    Code Sandbox

    Browser Sandbox

    Computer Sandbox

    Customized Sandbox

    Unified Storage NAS/OSS/S3

    Kubernetes Cluster

    实战

    基于install.yaml文件在k8s集群里安装Agent-Sandbox,需要k8s版本大于等于1.26,install.yaml文件示例

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: agentsandbox
    namespace: agentsandbox
    spec:
    ingressClassName: ingressnginx
    rules:
    host: agentsandbox.yourhost.com
    http:
    paths:
    backend:
    service:
    name: agentsandbox
    port:
    number: 80
    path: /

    执行命令:

    kubectl create namespace agent-sandbox
    kubectl apply -n agent-sandbox -f install.yaml

    没出错的话,可访问http://agent-sandbox.your-host.com提供的API服务,以及http://agent-sandbox.your-host.com/mcp提供的MCP能力。

    支持使用AIO提供的Python SDK连接到API Server。

    赞(0)
    未经允许不得转载:171主机测评 » 沙盒(三):Firecracker、Jupyter Kernel、E2B、AIO、k8s-sigs、Agent-Sandbox
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址