<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>OpenDsec 博客</title>
        <link>https://kernflux.github.io/blog/</link>
        <description>OpenDsec 的发布说明、设计取舍和测试记录</description>
        <lastBuildDate>Sun, 25 Oct 2026 08:49:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>© 2026 Yibo Zhou · Kernflux</copyright>
        <item>
            <title><![CDATA[解读 DeepSeek DSec 论文：大规模智能体训练的沙箱（sandbox）基础设施]]></title>
            <link>https://kernflux.github.io/blog/posts/dsec-paper</link>
            <guid>https://kernflux.github.io/blog/posts/dsec-paper</guid>
            <pubDate>Sun, 25 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[DeepSeek DSec 论文解读：支撑智能体强化学习的沙箱（sandbox）平台如何调度、超卖、按需加载镜像和防作弊，以及开源实现 OpenDsec 的不同选择。]]></description>
            <content:encoded><![CDATA[<h1 id="解读-deepseek-dsec-论文-大规模智能体训练的沙箱-sandbox-基础设施" tabindex="-1">解读 DeepSeek DSec 论文：大规模智能体训练的沙箱（sandbox）基础设施 <a class="header-anchor" href="#解读-deepseek-dsec-论文-大规模智能体训练的沙箱-sandbox-基础设施" aria-label="Permalink to &quot;解读 DeepSeek DSec 论文：大规模智能体训练的沙箱（sandbox）基础设施&quot;">&ZeroWidthSpace;</a></h1>
<p>训练会写代码、会用工具的 AI 智能体，强化学习（RL）的每一次 rollout 都要一个独立的沙箱（sandbox）：一个能装依赖、跑命令、读写文件的隔离环境。DeepSeek 2026 年 9 月发布的论文 <em>DeepSeek Elastic Compute (DSec): A Sandbox Infrastructure for Effective Agentic Training at Scale</em>（<a href="https://arxiv.org/abs/2609.22978" target="_blank" rel="noreferrer">arXiv:2609.22978</a>）介绍了他们在生产中使用的 sandbox 平台。</p>
<p>先说结论。这篇论文最值得借鉴的是五点：</p>
<ol>
<li><strong>sandbox 申请的资源大多用不上</strong>：约 90% 的 sandbox 平均只用到申请 CPU 的 5% 以内，所以可以大幅超卖，但要用 CPU 核心调度保护对延迟敏感的任务。</li>
<li><strong>镜像不要整个拉取</strong>：一个 sandbox 实际只会读到镜像的 4%–13%，按需加载比全量拉取快得多。</li>
<li><strong>调度可以很简单</strong>：power-of-k 随机选节点，加上本地的「在途」记录，最终由节点自己决定接不接受。</li>
<li><strong>RL 需要任务级操作</strong>：训练被抢占或结束时，整批暂停、恢复或结束一个任务的所有 sandbox。</li>
<li><strong>要防智能体作弊</strong>：论文记录了真实的 reward hacking 和越权事件，sandbox 需要专门防护。</li>
</ol>
<p>下面逐项展开。我们的开源项目 <a href="https://github.com/Kernflux/opendsec" target="_blank" rel="noreferrer">OpenDsec</a> 就是照着这篇论文实现的，文末说明它在哪些地方做了不同的选择。OpenDsec 与 DeepSeek 没有关联。</p>
<h2 id="规模" tabindex="-1">规模 <a class="header-anchor" href="#规模" aria-label="Permalink to &quot;规模&quot;">&ZeroWidthSpace;</a></h2>
<p>论文给出的生产数字：</p>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th>数字</th>
</tr>
</thead>
<tbody>
<tr>
<td>一个生产单元</td>
<td>约 160 个节点</td>
</tr>
<tr>
<td>每天创建的 sandbox</td>
<td>约 300 万个</td>
</tr>
<tr>
<td>同时运行的 sandbox</td>
<td>超过 38 万个</td>
</tr>
<tr>
<td>创建速率</td>
<td>每秒超过 5,000 个</td>
</tr>
<tr>
<td>单个训练任务</td>
<td>最多 3.2 万个 sandbox</td>
</tr>
<tr>
<td>单个节点（稳定运行）</td>
<td>3,200 个容器，或 800 个 microVM</td>
</tr>
<tr>
<td>RL sandbox 存活时间</td>
<td>p99 超过 3 小时</td>
</tr>
</tbody>
</table>
<p>最后一行常被忽略：sandbox 活得比一次部署久，所以升级节点时不能把它们杀掉。</p>
<h2 id="一套-sdk-四种后端-不做抽象" tabindex="-1">一套 SDK，四种后端，不做抽象 <a class="header-anchor" href="#一套-sdk-四种后端-不做抽象" aria-label="Permalink to &quot;一套 SDK，四种后端，不做抽象&quot;">&ZeroWidthSpace;</a></h2>
<p>DSec 提供四种后端：函数调用（FnCall）、容器、microVM 和完整虚拟机。它们共用一套 SDK，但 SDK <strong>不</strong>试图把后端抽象成同一个接口：调用方明确选择后端，每种后端有自己的参数。理由很实际：容器、microVM 和虚拟机在启动时间、隔离强度、能不能挂 GPU 上差别很大，统一的抽象只会隐藏这些差别。</p>
<h2 id="调度-power-of-k-和节点的最终决定权" tabindex="-1">调度：power-of-k 和节点的最终决定权 <a class="header-anchor" href="#调度-power-of-k-和节点的最终决定权" aria-label="Permalink to &quot;调度：power-of-k 和节点的最终决定权&quot;">&ZeroWidthSpace;</a></h2>
<p>放置 sandbox 用的是经典的 power-of-k choices（论文引用 Mitzenmacher）：从候选节点里随机取 k 个，选负载最低的。它不需要全局精确的状态，却能把负载分得很均匀。</p>
<p>两点细节决定了它在高并发下能不能用：</p>
<ul>
<li><strong>在途记录（in-flight overlay）</strong>：节点的负载是定期汇报的，两次汇报之间刚放上去的 sandbox 看不到。每个调度实例在选中节点时就把这次放置记下来，计算负载时叠加上去，避免一窝蜂打到同一个节点。</li>
<li><strong>最终准入权在节点</strong>：调度只是尽力而为。节点收到请求时按自己当前的容量和内存压力再检查一次，不够就拒绝，调度换一个节点重试。</li>
</ul>
<p>控制面的组件（API 服务、状态收集）都没有持久状态，重启后重新向节点轮询即可恢复。sandbox 的 id 里编码了它所在的节点，路由不用查表。</p>
<h2 id="超卖和-cpu-核心调度" tabindex="-1">超卖和 CPU 核心调度 <a class="header-anchor" href="#超卖和-cpu-核心调度" aria-label="Permalink to &quot;超卖和 CPU 核心调度&quot;">&ZeroWidthSpace;</a></h2>
<p>论文统计约 90% 的 sandbox 平均只用到申请 CPU 的 5% 以内。按申请量分配就会浪费大量机器，所以 DSec 大幅超卖 CPU。</p>
<p>超卖的代价落在对延迟敏感的任务上。只把后台任务设成 <code>SCHED_IDLE</code> 不够：它只管同一个硬件线程上谁先跑，管不了同一物理核另一个超线程上的邻居抢执行单元和缓存。论文的测量是，50% 的干扰负载下，不保护时延迟增加 45.2%，<code>SCHED_IDLE</code> 最多改善 3.4%，加上 Linux 的 CPU 核心调度（core scheduling）后只增加 17.3%。</p>
<p>内存方面，论文同样做了共享和回收：暂停的 sandbox 把内存换出，相同的只读数据在 sandbox 之间共享。</p>
<h2 id="镜像-分层构建-按需加载" tabindex="-1">镜像：分层构建，按需加载 <a class="header-anchor" href="#镜像-分层构建-按需加载" aria-label="Permalink to &quot;镜像：分层构建，按需加载&quot;">&ZeroWidthSpace;</a></h2>
<p>RL 任务的环境种类多、每种用得少，传统的「先把整个镜像拉到节点上」很浪费。DSec 的做法：</p>
<ul>
<li><strong>分层</strong>：环境由 base、workspace、toolkit 等独立版本化的层拼成，换一层不用重建整个镜像。</li>
<li><strong>按需加载</strong>：镜像数据放在 DeepSeek 自己的分布式文件系统 3FS 上，sandbox 用到哪部分数据才读取哪部分。论文统计一个 sandbox 实际只读到镜像的 4%–13%。</li>
<li><strong>效果</strong>：8,192 个容器的突发创建，按需加载用时 35 分钟，全量拉取超过 60 分钟。</li>
<li><strong>构建和运行分开</strong>：构建环境的账号和跑任务的账号分离，跑任务的账号不能往别人会用到的镜像里写东西。</li>
</ul>
<h2 id="为-rl-设计的生命周期" tabindex="-1">为 RL 设计的生命周期 <a class="header-anchor" href="#为-rl-设计的生命周期" aria-label="Permalink to &quot;为 RL 设计的生命周期&quot;">&ZeroWidthSpace;</a></h2>
<p>DSec 和 RL 训练框架是一起设计的：有状态的 rollout 执行在 sandbox 里，GPU 训练可以被抢占，两者分开。为此 sandbox 平台提供：</p>
<ul>
<li><strong>任务级操作</strong>：按任务暂停、恢复、结束全部 sandbox。训练被抢占时整批暂停，回来后整批恢复。</li>
<li><strong>透明恢复</strong>：对一个已暂停的 sandbox 发起任何操作，平台先自动恢复它。</li>
<li><strong>超时回收</strong>：显式结束，或者空闲超时后回收。</li>
<li><strong>嵌套项目和有界委托</strong>：项目可以任意深度嵌套（例如 <code>root/rl/job-42/agent-7</code>），一个身份只能把自己有的权限再委托出去。</li>
</ul>
<h2 id="防作弊和越权" tabindex="-1">防作弊和越权 <a class="header-anchor" href="#防作弊和越权" aria-label="Permalink to &quot;防作弊和越权&quot;">&ZeroWidthSpace;</a></h2>
<p>论文记录了智能体在 sandbox 里的真实「越轨」行为，例如：无限输出写满存储、伪造请求发给 sandbox 内部的管理进程、读取管理进程的日志找答案、覆盖 <code>/bin/bash</code>、用文件系统的 ioctl 破坏元数据、扫描端口找镜像源。</p>
<p>DSec 的防护包括 AppArmor 限制，以及用 eBPF 实现的网络策略：出站默认拒绝，按规则放行。</p>
<h2 id="云上溢出" tabindex="-1">云上溢出 <a class="header-anchor" href="#云上溢出" aria-label="Permalink to &quot;云上溢出&quot;">&ZeroWidthSpace;</a></h2>
<p>本地集群利用率超过 80% 时，DSec 把一部分容器任务放到云上。不是所有任务都能上云，只有镜像在一个去重后约 30 TB 的 EROFS 集合里的任务才行，这个集合覆盖了约 70% 的容器任务。</p>
<h2 id="对自建-sandbox-平台的启示" tabindex="-1">对自建 sandbox 平台的启示 <a class="header-anchor" href="#对自建-sandbox-平台的启示" aria-label="Permalink to &quot;对自建 sandbox 平台的启示&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><strong>按实际用量而不是申请量规划容量</strong>，然后用核心调度保护延迟敏感的任务。</li>
<li><strong>镜像体积不是瓶颈，读多少才是</strong>：先上按需加载，再优化存储。</li>
<li><strong>简单的随机调度够用</strong>，前提是节点有最终准入权、调度实例记得自己刚放了什么。</li>
<li><strong>从第一天起就设计任务级操作和暂停</strong>，RL 训练一定会被抢占。</li>
<li><strong>把智能体当作不可信的程序</strong>：输出有上限、网络默认拒绝、评测和智能体分开。</li>
</ul>
<h2 id="opendsec-开源的实现-以及不同的选择" tabindex="-1">OpenDsec：开源的实现，以及不同的选择 <a class="header-anchor" href="#opendsec-开源的实现-以及不同的选择" aria-label="Permalink to &quot;OpenDsec：开源的实现，以及不同的选择&quot;">&ZeroWidthSpace;</a></h2>
<p><a href="/">OpenDsec</a> 按论文的架构实现了 IAM、调度、状态收集、节点、SDK 和镜像库，并在两台 384 线程的裸金属节点上做了生产验证。下面几处我们做了不同的选择：</p>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th>DSec 论文</th>
<th>OpenDsec</th>
</tr>
</thead>
<tbody>
<tr>
<td>主力后端</td>
<td>容器；microVM 用于需要更强隔离的场景</td>
<td>Firecracker microVM：不共享宿主内核，能做内存快照。容器留给 GPU 和没有 KVM 的机器</td>
</tr>
<tr>
<td>fork 和暂停</td>
<td>任务级暂停和恢复</td>
<td>同样支持，另外可以连同内存 fork 运行中的 microVM（<code>fork(count=N)</code>），适合树搜索</td>
</tr>
<tr>
<td>网络策略</td>
<td>eBPF</td>
<td>nftables 加内置 DNS 代理，语义相同：默认拒绝，按域名、地址、端口放行，运行中可改</td>
</tr>
<tr>
<td>镜像存储</td>
<td>3FS</td>
<td>任何共享文件系统：NFS、CephFS、JuiceFS</td>
</tr>
<tr>
<td>兼容性</td>
<td>自己的 SDK</td>
<td>自己的 SDK，加上 E2B 兼容网关</td>
</tr>
</tbody>
</table>
<p>几个对照论文做的实测（项目的裸金属测试机，2 × AMD EPYC 9Y24）：</p>
<ul>
<li><strong>CPU 核心调度</strong>：50% 干扰负载下，延迟增加从不保护时的 18.0% 降到 2.1%（<code>SCHED_IDLE</code> 加核心调度）；100% 干扰负载下从 81.0% 降到 10.0%。方向与论文一致。</li>
<li><strong>密度</strong>：单台 384 线程的节点一次突发创建 5,120 个 microVM，用时 37 秒；两个节点一次突发创建 8,192 个容器，全部成功。</li>
<li><strong>防作弊</strong>：论文列出的事件逐条对照处理，例如每条命令每路输出最多记录 64 MB，智能体会话用普通用户。</li>
</ul>
<p>此外，OpenDsec 自带 fleet 服务，分批滚动升级和修改配置，运行中的 sandbox 不受影响。</p>
<p>还没做的：没有做按需加载与全量拉取的对比实验，GPU 还没有在真实硬件上测过。</p>
<h2 id="常见问题" tabindex="-1">常见问题 <a class="header-anchor" href="#常见问题" aria-label="Permalink to &quot;常见问题&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="dsec-是开源的吗" tabindex="-1">DSec 是开源的吗？ <a class="header-anchor" href="#dsec-是开源的吗" aria-label="Permalink to &quot;DSec 是开源的吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>论文介绍的是 DeepSeek 内部的系统，没有附带代码。OpenDsec 不是 DeepSeek 的代码，而是我们按论文独立实现的开源项目（服务端 AGPL-3.0，SDK Apache-2.0），与 DeepSeek 没有关联。</p>
<h3 id="dsec-用的是容器还是虚拟机" tabindex="-1">DSec 用的是容器还是虚拟机？ <a class="header-anchor" href="#dsec-用的是容器还是虚拟机" aria-label="Permalink to &quot;DSec 用的是容器还是虚拟机？&quot;">&ZeroWidthSpace;</a></h3>
<p>都有。DSec 提供函数调用、容器、microVM 和完整虚拟机四种后端，以容器为主力，由调用方按任务选择。</p>
<h3 id="为什么-rl-训练需要专门的-sandbox-平台" tabindex="-1">为什么 RL 训练需要专门的 sandbox 平台？ <a class="header-anchor" href="#为什么-rl-训练需要专门的-sandbox-平台" aria-label="Permalink to &quot;为什么 RL 训练需要专门的 sandbox 平台？&quot;">&ZeroWidthSpace;</a></h3>
<p>RL 一个任务就可能同时要上万个 sandbox，每个都要装依赖、跑测试、存活几个小时，而且训练随时可能被抢占。通用的容器平台一般没有任务级暂停、大规模突发创建和防作弊这些能力。</p>
<h3 id="sandbox-可以超卖多少" tabindex="-1">sandbox 可以超卖多少？ <a class="header-anchor" href="#sandbox-可以超卖多少" aria-label="Permalink to &quot;sandbox 可以超卖多少？&quot;">&ZeroWidthSpace;</a></h3>
<p>论文统计约 90% 的 sandbox 平均只用到申请 CPU 的 5% 以内。OpenDsec 默认把 CPU 超卖 8 倍，并用 CPU 核心调度保护对延迟敏感的 sandbox。具体比例取决于你的负载。</p>
<h3 id="什么是-reward-hacking-sandbox-怎么防" tabindex="-1">什么是 reward hacking，sandbox 怎么防？ <a class="header-anchor" href="#什么是-reward-hacking-sandbox-怎么防" aria-label="Permalink to &quot;什么是 reward hacking，sandbox 怎么防？&quot;">&ZeroWidthSpace;</a></h3>
<p>reward hacking 指智能体不解决问题，而是钻评测的空子拿奖励，比如读取评测日志里的答案、改掉系统命令。常见的防护是让智能体碰不到评测的东西：智能体和评测用不同的用户、限制输出、网络默认拒绝。</p>
<h3 id="不训练模型-只想给-ai-智能体一个执行代码的-sandbox-有用吗" tabindex="-1">不训练模型，只想给 AI 智能体一个执行代码的 sandbox，有用吗？ <a class="header-anchor" href="#不训练模型-只想给-ai-智能体一个执行代码的-sandbox-有用吗" aria-label="Permalink to &quot;不训练模型，只想给 AI 智能体一个执行代码的 sandbox，有用吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>有用。论文里的超卖、按需加载和防越权对任何「运行不可信代码」的场景都适用。OpenDsec 也可以直接作为 AI 智能体的代码执行沙箱，并兼容 E2B SDK，见<a href="/blog/posts/self-hosted-e2b.html">自建 E2B</a>。</p>
<h2 id="延伸阅读" tabindex="-1">延伸阅读 <a class="header-anchor" href="#延伸阅读" aria-label="Permalink to &quot;延伸阅读&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li>论文：<a href="https://arxiv.org/abs/2609.22978" target="_blank" rel="noreferrer">arXiv:2609.22978</a></li>
<li><a href="/docs/concepts.html">OpenDsec 核心概念</a></li>
<li><a href="/docs/compare.html">OpenDsec 与 E2B、Daytona、Modal 对比</a></li>
<li><a href="/docs/quickstart.html">快速开始</a>：在一台 Linux 机器上装好 OpenDsec</li>
</ul>
<p><em>OpenDsec 是 Kernflux 的开源项目，与 DeepSeek 没有关联。文中关于 DSec 的内容均来自上述论文。</em></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[自建 E2B：在自己的服务器上运行 E2B 代码沙箱（sandbox）]]></title>
            <link>https://kernflux.github.io/blog/posts/self-hosted-e2b</link>
            <guid>https://kernflux.github.io/blog/posts/self-hosted-e2b</guid>
            <pubDate>Sun, 25 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[自建 E2B 的两种方法，以及用开源的 OpenDsec 一步步搭建兼容 E2B 的代码沙箱（sandbox）：单机安装、code interpreter、fork 和快照。]]></description>
            <content:encoded><![CDATA[<h1 id="自建-e2b-在自己的服务器上运行-e2b-代码沙箱-sandbox" tabindex="-1">自建 E2B：在自己的服务器上运行 E2B 代码沙箱（sandbox） <a class="header-anchor" href="#自建-e2b-在自己的服务器上运行-e2b-代码沙箱-sandbox" aria-label="Permalink to &quot;自建 E2B：在自己的服务器上运行 E2B 代码沙箱（sandbox）&quot;">&ZeroWidthSpace;</a></h1>
<p><a href="https://e2b.dev" target="_blank" rel="noreferrer">E2B</a> 是 AI 智能体最常用的代码执行沙箱（sandbox）之一：智能体生成的代码在一个隔离的 Firecracker microVM 里运行，不少智能体框架都支持 E2B。但 E2B 主要是托管云服务，代码和数据要发到 E2B 的云上。数据不能出域、网络离线、或者 sandbox 用量大到托管费用不划算时，就需要自建。</p>
<p>先说结论。自建 E2B 有两条路：</p>
<ol>
<li><strong>E2B 自己的开源运行时</strong>（<a href="https://github.com/e2b-dev/runtime" target="_blank" rel="noreferrer">e2b-dev/runtime</a>，Apache-2.0）。可以在一台机器上自建（Embed）；部署到自己的云账号（BYOC）是企业版功能。</li>
<li><strong>OpenDsec 的 E2B 网关</strong>。<a href="https://github.com/Kernflux/opendsec" target="_blank" rel="noreferrer">OpenDsec</a> 是开源的 sandbox 平台，自带一个提供 E2B API 的网关。用 E2B SDK 写的代码不用改，设置三个环境变量就能跑在你自己的单机或集群上。</li>
</ol>
<p>这篇文章一步步介绍第二条路：单机安装、用 E2B SDK 调用、搭 code interpreter、扩成集群，以及和 E2B 的差别。</p>
<h2 id="第一步-单机安装" tabindex="-1">第一步：单机安装 <a class="header-anchor" href="#第一步-单机安装" aria-label="Permalink to &quot;第一步：单机安装&quot;">&ZeroWidthSpace;</a></h2>
<p>需要一台 Linux x86_64 机器（在 Ubuntu 24.04 上验证过），有 systemd 和 cgroup v2。要用 microVM（和 E2B 一样的 Firecracker），还需要 <code>/dev/kvm</code>：裸金属，或者开启了嵌套虚拟化的云主机。</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -i</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                                    # 以下都用 root</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> make</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> python3-venv</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -fsSL</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://go.dev/dl/go1.27.3.linux-amd64.tar.gz</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tar</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -C</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /usr/local</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -xz</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> clone</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://github.com/kernflux/opendsec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> opendsec</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">deploy/quickstart.sh</span></span></code></pre>
</div><p>脚本会编译程序、下载 Firecracker 和 guest 内核，装好全部服务，<strong>其中包括 E2B 网关</strong>（端口 7400），并配好一个叫 <code>base</code> 的模板（Python 3.12）。在一台全新的 8 核虚拟机上全程约 11 分钟，大部分时间在编译。</p>
<h2 id="第二步-用-e2b-sdk-调用" tabindex="-1">第二步：用 E2B SDK 调用 <a class="header-anchor" href="#第二步-用-e2b-sdk-调用" aria-label="Permalink to &quot;第二步：用 E2B SDK 调用&quot;">&ZeroWidthSpace;</a></h2>
<p>安装脚本写好的 <code>/root/opendsec-ops/demo.env</code> 里已经有 E2B SDK 需要的三个环境变量：</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">.</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /root/opendsec-ops/demo.env</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">       # 设置 E2B_API_URL、E2B_SANDBOX_URL、E2B_API_KEY</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">python3</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -m</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> venv</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> .venv</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.venv/bin/pip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> e2b</span></span></code></pre>
</div><p><code>E2B_API_KEY</code> 就是 OpenDsec 的 token。之后的代码和用 E2B 云服务时完全一样（用 <code>.venv/bin/python</code> 运行）：</p>
<div class="language-python vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e2b </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sbx </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox.create()                          </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 模板 "base"</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sbx.commands.run(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"python3 -V"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).stdout)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sbx.files.write(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/tmp/a.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"hello"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sbx.files.read(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/tmp/a.txt"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sbx.kill()</span></span></code></pre>
</div><p>在别的机器上调用时，把三个变量里的地址换成这台机器的地址即可：</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> E2B_API_URL</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">网关</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:7400</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> E2B_SANDBOX_URL</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">http://</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">网关</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">:7400</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> E2B_API_KEY</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&#x3C;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">你的 OpenDsec token</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">></span></span></code></pre>
</div><p>JS/TS SDK 同样可用（需要 Node.js 22.19 以上）。</p>
<h2 id="fork、快照和暂停" tabindex="-1">fork、快照和暂停 <a class="header-anchor" href="#fork、快照和暂停" aria-label="Permalink to &quot;fork、快照和暂停&quot;">&ZeroWidthSpace;</a></h2>
<p>在 microVM 上，fork、快照和暂停都<strong>连同内存</strong>保存，运行中的进程会延续下去：</p>
<div class="language-python vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e2b </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox.create(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">timeout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">300</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">src.files.write(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"/tmp/state"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"v1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">forks </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> src.fork(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">count</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)                       </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 运行中 sandbox 的两个副本</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">snap </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> src.create_snapshot()                    </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 快照</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">again </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox.create(snap.snapshot_id)        </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 从快照创建</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 超时时暂停而不是结束；connect 时恢复</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox.create(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">timeout</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">60</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">lifecycle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">{</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"on_timeout"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"pause"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"auto_resume"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">True</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">s2 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox.connect(s.sandbox_id)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">for</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">in</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> [src, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">forks, again, s2]:</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    x.kill()</span></span></code></pre>
</div><p>fork 适合智能体的树搜索，或者从一个装好依赖的环境展开大量 RL rollout。</p>
<h2 id="第三步-搭-code-interpreter" tabindex="-1">第三步：搭 code interpreter <a class="header-anchor" href="#第三步-搭-code-interpreter" aria-label="Permalink to &quot;第三步：搭 code interpreter&quot;">&ZeroWidthSpace;</a></h2>
<p>E2B 的 code interpreter（<code>run_code</code>，返回结果、图表和 pandas 表格）需要一个专门的模板。OpenDsec 用 E2B 开源的 code-interpreter 服务构建它：一个已经运行着该服务和 Python Jupyter 内核的 microVM 的内存快照，所以创建后立刻就能执行代码。</p>
<p>构建时 sandbox 要从网上安装软件包，所以机器需要能访问 apt 源和 PyPI。仍在 <code>opendsec</code> 目录下：</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -fsSL</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://codeload.github.com/e2b-dev/code-interpreter/tar.gz/refs/heads/main</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tar</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -xz</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">.</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /root/opendsec-ops/env</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">                        # 管理员 token：要往 root 项目发布镜像</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.venv/bin/pip</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> ./sdk/python</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">.venv/bin/python</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> deploy/e2b/build-code-interpreter.py</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> code-interpreter-main/template</span></span></code></pre>
</div><p>这会构建镜像 <code>root/code-interpreter:v1</code>。然后在 <code>/root/opendsec-ops/opendsec.json</code> 的 <code>e2b.templates</code> 里加一个模板：</p>
<div class="language-json vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"code-interpreter-v1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: {</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"image"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"root/code-interpreter:v1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"backend"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"microvm"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"cpu"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">"memory_mb"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">2048</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
</div><p>下发配置并重启：</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> OPENDSEC_OPS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">/root/opendsec-ops</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">deploy/prod/opendsecops</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> push-config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> all</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">deploy/prod/opendsecops</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> restart</span></span></code></pre>
</div><p>之后调用方安装 <code>e2b-code-interpreter</code> 就能用：</p>
<div class="language-python vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">from</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> e2b_code_interpreter </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">sbx </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Sandbox.create(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"code-interpreter-v1"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">print</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(sbx.run_code(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">"6 * 7"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).text)               </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D"># 42</span></span></code></pre>
</div><h2 id="速度" tabindex="-1">速度 <a class="header-anchor" href="#速度" aria-label="Permalink to &quot;速度&quot;">&ZeroWidthSpace;</a></h2>
<p>2026-10-23 在项目的裸金属测试机（AMD EPYC 9Y24）上，经网关在 Firecracker microVM 上测得：</p>
<table tabindex="0">
<thead>
<tr>
<th>操作</th>
<th>耗时</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Sandbox.create()</code>，模板 <code>base</code>（2 vCPU、1 GB、冷启动）</td>
<td>p50 166 ms</td>
</tr>
<tr>
<td>创建后的第一条命令</td>
<td>p50 12 ms</td>
</tr>
<tr>
<td><code>Sandbox.create(&quot;code-interpreter-v1&quot;)</code>（2 GB 内存快照）</td>
<td>约 250 ms</td>
</tr>
<tr>
<td>第一次 <code>run_code</code></td>
<td>约 40 ms</td>
</tr>
<tr>
<td><code>fork(count=2)</code></td>
<td>约 100–150 ms</td>
</tr>
<tr>
<td><code>create_snapshot()</code></td>
<td>约 40–70 ms</td>
</tr>
<tr>
<td><code>Sandbox.create(snapshot_id)</code></td>
<td>约 65–85 ms</td>
</tr>
</tbody>
</table>
<h2 id="扩成集群" tabindex="-1">扩成集群 <a class="header-anchor" href="#扩成集群" aria-label="Permalink to &quot;扩成集群&quot;">&ZeroWidthSpace;</a></h2>
<p>单机够用就不用往下看。sandbox 多了以后，OpenDsec 可以扩成多机集群（<a href="/docs/cluster.html">部署文档</a>），E2B 网关也随之扩成多个副本：</p>
<ol>
<li>在集群配置的 <code>e2b</code> 一节列出各网关的地址、sandbox 放进哪个项目，以及模板。</li>
<li>给节点加上 fleet 角色 <code>e2b=&lt;序号&gt;</code>。</li>
<li>前面放一个负载均衡：TCP 7400，健康检查用 HTTP 9467 <code>/readyz</code>。</li>
</ol>
<p>网关自己不保存状态，每次调用都用调用方的 token 发给 OpenDsec，所以权限、配额和审计记录照常生效。</p>
<h2 id="和-e2b-云服务的差别" tabindex="-1">和 E2B 云服务的差别 <a class="header-anchor" href="#和-e2b-云服务的差别" aria-label="Permalink to &quot;和 E2B 云服务的差别&quot;">&ZeroWidthSpace;</a></h2>
<p>完整列表见 <a href="/docs/e2b.html">E2B 兼容</a>，主要的几条：</p>
<table tabindex="0">
<thead>
<tr>
<th></th>
<th>E2B</th>
<th>OpenDsec 网关</th>
</tr>
</thead>
<tbody>
<tr>
<td>模板</td>
<td>用 E2B 的模板构建生成</td>
<td>管理员在配置里把模板名对应到 OpenDsec 的镜像；没有模板构建 API</td>
</tr>
<tr>
<td>sandbox 端口</td>
<td>可以开放公开访问</td>
<td>必须带 token（SDK 自动带上）</td>
</tr>
<tr>
<td>只保存文件系统的暂停</td>
<td>支持</td>
<td>拒绝（400）：暂停总是保留内存</td>
</tr>
<tr>
<td>只保存文件系统的快照</td>
<td>支持</td>
<td>microVM 上拒绝（400）；容器的快照本来就只有文件系统</td>
</tr>
<tr>
<td>code interpreter 的语言</td>
<td>Python、JavaScript、R、Java、Bash</td>
<td>Python</td>
</tr>
<tr>
<td>不支持</td>
<td></td>
<td>目录监听、签名文件地址、MCP、volume</td>
</tr>
</tbody>
</table>
<p>做不到的选项会返回 400，而不是悄悄忽略，所以程序不会在没拿到所要设置的情况下运行。</p>
<h2 id="选-e2b-自建还是-opendsec" tabindex="-1">选 E2B 自建还是 OpenDsec <a class="header-anchor" href="#选-e2b-自建还是-opendsec" aria-label="Permalink to &quot;选 E2B 自建还是 OpenDsec&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><strong>E2B 自建（Embed）</strong> 适合一台机器就够用、想用 E2B 自己代码的场景；部署到自己的云账号（BYOC）是 E2B 企业版的功能。</li>
<li><strong>OpenDsec</strong> 适合需要多机集群、离线部署、RL rollout 那样的大规模突发创建，或者除了 E2B SDK 还想用容器、QEMU 虚拟机和任务级暂停的场景。代价是 E2B 兼容还有上面列出的缺口，项目还是 0.x 版本。</li>
</ul>
<p>更多对比见 <a href="/docs/compare.html">OpenDsec 与 E2B、Daytona、Modal 对比</a>。</p>
<h2 id="常见问题" tabindex="-1">常见问题 <a class="header-anchor" href="#常见问题" aria-label="Permalink to &quot;常见问题&quot;">&ZeroWidthSpace;</a></h2>
<h3 id="e2b-可以自建吗" tabindex="-1">E2B 可以自建吗？ <a class="header-anchor" href="#e2b-可以自建吗" aria-label="Permalink to &quot;E2B 可以自建吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>可以。E2B 的运行时是开源的（Apache-2.0），可以在一台机器上自建；部署到自己的云账号是企业版功能。另一种方式是用 OpenDsec 的 E2B 网关，在自己的单机或集群上提供 E2B SDK 调用的 API。</p>
<h3 id="用-opendsec-需要改-e2b-的代码吗" tabindex="-1">用 OpenDsec 需要改 E2B 的代码吗？ <a class="header-anchor" href="#用-opendsec-需要改-e2b-的代码吗" aria-label="Permalink to &quot;用 OpenDsec 需要改 E2B 的代码吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>不需要。设置 <code>E2B_API_URL</code>、<code>E2B_SANDBOX_URL</code> 和 <code>E2B_API_KEY</code> 三个环境变量，把 SDK 指向网关即可。用到网关不支持的功能（例如目录监听）时会返回明确的错误。</p>
<h3 id="支持-e2b-的-code-interpreter-吗" tabindex="-1">支持 E2B 的 code interpreter 吗？ <a class="header-anchor" href="#支持-e2b-的-code-interpreter-吗" aria-label="Permalink to &quot;支持 E2B 的 code interpreter 吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>支持，用 <code>deploy/e2b/build-code-interpreter.py</code> 构建模板后即可使用 <code>run_code</code>，包括结果、日志、错误、图表和 pandas 表格。目前只支持 Python 内核。</p>
<h3 id="没有-kvm-的云主机能用吗" tabindex="-1">没有 KVM 的云主机能用吗？ <a class="header-anchor" href="#没有-kvm-的云主机能用吗" aria-label="Permalink to &quot;没有 KVM 的云主机能用吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>能。没有 <code>/dev/kvm</code> 时安装脚本只装容器，E2B 网关的 <code>base</code> 模板也用容器后端。这时 fork 和快照只保留文件系统，code interpreter 模板需要 microVM。</p>
<h3 id="能完全离线部署吗" tabindex="-1">能完全离线部署吗？ <a class="header-anchor" href="#能完全离线部署吗" aria-label="Permalink to &quot;能完全离线部署吗？&quot;">&ZeroWidthSpace;</a></h3>
<p>能。OpenDsec 提供离线安装包（<code>deploy/offline</code>），我们在不能上网的虚拟机上验证过安装和使用 E2B SDK，见<a href="/docs/install.html">安装</a>。</p>
<h3 id="自建要花多少钱" tabindex="-1">自建要花多少钱？ <a class="header-anchor" href="#自建要花多少钱" aria-label="Permalink to &quot;自建要花多少钱？&quot;">&ZeroWidthSpace;</a></h3>
<p>OpenDsec 是免费的开源软件（服务端 AGPL-3.0，SDK Apache-2.0），只需要你自己的机器。</p>
<h2 id="延伸阅读" tabindex="-1">延伸阅读 <a class="header-anchor" href="#延伸阅读" aria-label="Permalink to &quot;延伸阅读&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><a href="/docs/e2b.html">E2B 兼容：支持的功能和差别</a></li>
<li><a href="/docs/quickstart.html">快速开始</a></li>
<li><a href="/docs/cluster.html">多机集群部署</a></li>
<li><a href="/blog/posts/dsec-paper.html">解读 DeepSeek DSec 论文</a>：OpenDsec 的设计来源</li>
</ul>
<p><em>OpenDsec 与 E2B 没有关联，只是实现了 E2B SDK 调用的 API。文中关于 E2B 的情况来自它的文档和代码仓库，核对日期 2026-10-25。</em></p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[在全新的机器上验收开源版：22 个问题]]></title>
            <link>https://kernflux.github.io/blog/posts/fresh-machine-acceptance</link>
            <guid>https://kernflux.github.io/blog/posts/fresh-machine-acceptance</guid>
            <pubDate>Sat, 24 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[开源之前，我们按 README 在全新的 Ubuntu 24.04 虚拟机上把用户会用到的每个功能走了一遍，发现并修复了 22 个问题，其中 2 个是严重问题。]]></description>
            <content:encoded><![CDATA[<h1 id="在全新的机器上验收开源版-22-个问题" tabindex="-1">在全新的机器上验收开源版：22 个问题 <a class="header-anchor" href="#在全新的机器上验收开源版-22-个问题" aria-label="Permalink to &quot;在全新的机器上验收开源版：22 个问题&quot;">&ZeroWidthSpace;</a></h1>
<p>OpenDsec 的自动测试一直在我们自己的开发机和生产集群上跑，全部通过。但开发机上什么都装好了，生产集群也是一步步调出来的。新用户拿到的是一台全新的机器和一份 README。所以开源之前，我们换成新用户的视角，在全新的 Ubuntu 24.04 虚拟机上，按文档把用户可能用到的每个功能走了一遍。</p>
<h2 id="测了什么" tabindex="-1">测了什么 <a class="header-anchor" href="#测了什么" aria-label="Permalink to &quot;测了什么&quot;">&ZeroWidthSpace;</a></h2>
<table tabindex="0">
<thead>
<tr>
<th>场景</th>
<th>做法</th>
</tr>
</thead>
<tbody>
<tr>
<td>单机</td>
<td>按 README 安装，跑示例、SDK 功能测试、54 项管理命令检查，重启后恢复，卸载</td>
</tr>
<tr>
<td>没有 KVM</td>
<td>只装容器</td>
</tr>
<tr>
<td>E2B</td>
<td>E2B 官方 Python SDK（同步、异步）、JS SDK、code interpreter、快照和网络</td>
</tr>
<tr>
<td>离线</td>
<td>在不能上网的虚拟机上用离线包安装，离线使用 E2B SDK</td>
</tr>
<tr>
<td>多机集群</td>
<td>3 台管控、3 台计算、NFS 和 HAProxy，按文档部署、交给 fleet、加机器、滚动升级、改配置、维护、备份、监控</td>
</tr>
<tr>
<td>故障</td>
<td>压测中硬重启管控节点、杀掉 IAM leader</td>
</tr>
<tr>
<td>Kubernetes</td>
<td>单节点 k3s</td>
</tr>
</tbody>
</table>
<h2 id="两个严重问题" tabindex="-1">两个严重问题 <a class="header-anchor" href="#两个严重问题" aria-label="Permalink to &quot;两个严重问题&quot;">&ZeroWidthSpace;</a></h2>
<p><strong>新版 Ubuntu 内核上，microVM 恢复全部失败。</strong> Ubuntu 24.04 当前的 6.8.0-147 内核会杀掉用 <code>CLONE_INTO_CGROUP</code> 放进一个「执行过 <code>cgroup.kill</code>」的 cgroup 的进程。OpenDsec 暂停 microVM 时会结束 VM 进程，恢复时在原来的 cgroup 里启动新进程，于是每次恢复都失败。我们的生产机器内核旧一些，所以一直没碰到；一旦升级内核就会出现。现在结束进程改成先冻结 cgroup 再逐个发送 SIGKILL，不再用 <code>cgroup.kill</code>，并加了一个在受影响内核上会失败的回归测试。</p>
<p><strong>管控节点重启时，少量调用报 <code>unknown edge</code>。</strong> watcher 重启后，要等计算节点重新登记（最多 10 秒）才知道它们；这段时间里 apiserver 会把这些节点当成不存在。压测中硬重启一台管控节点，3,911 次调用里有 3 次失败。现在 watcher 启动时先从其他副本拿到已知节点，apiserver 也会把暂时看不到的节点保留 2 分钟。同样的硬重启，修复后 0 失败。</p>
<h2 id="其他问题" tabindex="-1">其他问题 <a class="header-anchor" href="#其他问题" aria-label="Permalink to &quot;其他问题&quot;">&ZeroWidthSpace;</a></h2>
<p>剩下 20 个大多是新用户第一次就会碰到的：</p>
<ul>
<li><strong>安装</strong>：新机器上没有 <code>make</code>，安装脚本编译到一半才报错；新 Ubuntu 上缺 <code>python3-venv</code>，README 里的 Python 步骤失败；全新的云镜像没有软件包索引，要先 <code>apt update</code>。</li>
<li><strong>命令行</strong>：<code>opendsecctl exec</code> 丢了参数里的引号，<code>python3 -c '...'</code> 会出错；<code>--help</code> 不能用；批量创建不打印新建的 ID；导入一个不存在的本地文件时，会去 Docker Hub 下载。</li>
<li><strong>E2B</strong>：单机安装没有 E2B 网关；在默认禁止外网的集群上，E2B sandbox 连不了外网，而 E2B 默认是允许的。</li>
<li><strong>运维</strong>：<code>opendsecops restart</code> 漏掉了 E2B 网关；磁盘告警用固定阈值，200 GB 以下的机器全都会报；Kubernetes 上 apiserver 没有权限写镜像库。</li>
<li><strong>性能</strong>：我们推荐的 NFS 4.1 不支持找稀疏文件的空洞，跨节点从内存快照创建要读完整个内存文件，用时 141 秒；换成 4.2 后是 62 秒。文档已改成 4.2，<code>store-check</code> 遇到 4.1 会提醒。</li>
</ul>
<p>每一项都写在 <a href="https://github.com/Kernflux/opendsec/blob/main/CHANGELOG.md" target="_blank" rel="noreferrer">CHANGELOG</a> 里。</p>
<h2 id="没测到的" tabindex="-1">没测到的 <a class="header-anchor" href="#没测到的" aria-label="Permalink to &quot;没测到的&quot;">&ZeroWidthSpace;</a></h2>
<p>真实 GPU、ARM 机器、多节点 Kubernetes，以及 Ubuntu 24.04 以外的发行版。如果你在这些环境上用 OpenDsec，遇到问题请<a href="https://github.com/Kernflux/opendsec/issues" target="_blank" rel="noreferrer">提 issue</a>。</p>
<h2 id="体会" tabindex="-1">体会 <a class="header-anchor" href="#体会" aria-label="Permalink to &quot;体会&quot;">&ZeroWidthSpace;</a></h2>
<p>开发机上的全量测试证明的是「代码在我们的机器上是对的」，证明不了「用户照着文档能用起来」。两个严重问题都和环境有关：一个是更新的内核，一个是生产集群里不会出现的重启时机。在全新的机器上按文档走一遍，能发现开发机上永远发现不了的问题。</p>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OpenDsec 开源了]]></title>
            <link>https://kernflux.github.io/blog/posts/opendsec-open-source</link>
            <guid>https://kernflux.github.io/blog/posts/opendsec-open-source</guid>
            <pubDate>Sat, 24 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[照 DeepSeek 的 DSec 论文实现的 sandbox 基础设施，现在以 AGPL-3.0 开源：Firecracker microVM、连同内存的 fork、按任务暂停，兼容 E2B 的 SDK。]]></description>
            <content:encoded><![CDATA[<h1 id="opendsec-开源了" tabindex="-1">OpenDsec 开源了 <a class="header-anchor" href="#opendsec-开源了" aria-label="Permalink to &quot;OpenDsec 开源了&quot;">&ZeroWidthSpace;</a></h1>
<p>今天我们把 OpenDsec 的代码公开在 <a href="https://github.com/Kernflux/opendsec" target="_blank" rel="noreferrer">GitHub</a> 上。它是一套给强化学习训练和会执行代码的智能体用的 sandbox 基础设施：在你自己的机器上，成批地创建、暂停、复制和销毁隔离的执行环境。</p>
<h2 id="为什么做它" tabindex="-1">为什么做它 <a class="header-anchor" href="#为什么做它" aria-label="Permalink to &quot;为什么做它&quot;">&ZeroWidthSpace;</a></h2>
<p>智能体的强化学习训练要同时跑成千上万个 rollout，每个 rollout 都要一个能装依赖、跑测试、访问网络的隔离环境。训练会被抢占，环境要能整批暂停；同一个状态要试多种走法，环境要能连同内存一起复制。</p>
<p>DeepSeek 在论文 <a href="https://arxiv.org/abs/2609.22978" target="_blank" rel="noreferrer"><em>DeepSeek Elastic Compute (DSec)</em></a> 里详细描述了他们为此建的系统。OpenDsec 照这篇论文实现：无状态的 apiserver、带多级项目和配额的 IAM、汇总调度状态的 watcher、power-of-k 调度和节点上的最终准入，以及分层镜像、默认拒绝的网络策略和按任务暂停。论文没有说明的地方由我们自己决定，仓库里的 <a href="/docs/spec.html">SPEC</a> 逐条标注了哪些来自论文、哪些是我们的选择。</p>
<p>OpenDsec 是独立项目，与 DeepSeek 没有关系，也不包含其代码。</p>
<h2 id="它能做什么" tabindex="-1">它能做什么 <a class="header-anchor" href="#它能做什么" aria-label="Permalink to &quot;它能做什么&quot;">&ZeroWidthSpace;</a></h2>
<ul>
<li><strong>快</strong>：Firecracker microVM 冷启动约 0.1 秒，从内存快照创建约 55 毫秒，暂停后恢复约 50 毫秒。</li>
<li><strong>fork</strong>：<code>fork(count=N)</code> 连同内存复制一个正在运行的 VM，源 VM 只停顿约 10 毫秒。同一节点上的副本共享内存页，64 个副本并发恢复约 0.2 秒。</li>
<li><strong>规模</strong>：单个 384 线程的节点一次突发创建 5120 个 microVM，用时 37 秒。</li>
<li><strong>兼容 E2B</strong>：按 E2B SDK 写的程序换三个环境变量就能跑在你自己的机器上，E2B 官方 Python 和 JS SDK 的验收检查全部通过。</li>
<li><strong>能运维</strong>：组件之间 mTLS，IAM 用 Raft 多副本；fleet 分批滚动升级，失败自动回退；支持离线安装。升级任何组件都不影响运行中的 sandbox。</li>
</ul>
<p>这些数字都是在我们自己的裸金属机器上测的，测量方法写在 SPEC 里。</p>
<h2 id="试一试" tabindex="-1">试一试 <a class="header-anchor" href="#试一试" aria-label="Permalink to &quot;试一试&quot;">&ZeroWidthSpace;</a></h2>
<p>一台装了 Ubuntu 24.04 的 Linux 机器，约 10 分钟：</p>
<div class="language-sh vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">sudo</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -i</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> update</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">apt</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> install</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -y</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> make</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> python3-venv</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -fsSL</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://go.dev/dl/go1.27.3.linux-amd64.tar.gz</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> tar</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -C</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> /usr/local</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> -xz</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> clone</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> https://github.com/kernflux/opendsec</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> &#x26;&#x26; </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> opendsec</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">deploy/quickstart.sh</span></span></code></pre>
</div><p>详细步骤见<a href="/docs/quickstart.html">快速开始</a>，多机集群和离线安装见<a href="/docs/deploy.html">部署方式</a>。</p>
<h2 id="许可" tabindex="-1">许可 <a class="header-anchor" href="#许可" aria-label="Permalink to &quot;许可&quot;">&ZeroWidthSpace;</a></h2>
<p>服务端是 AGPL-3.0；Python SDK、Go 客户端和 API 定义是 Apache-2.0，调用 OpenDsec 的程序不受 AGPL 约束。闭源修改、作为服务对外提供而不公开修改，或者需要企业版的单点登录和审计导出，可以申请<a href="/docs/license.html">商业授权</a>。</p>
<h2 id="接下来" tabindex="-1">接下来 <a class="header-anchor" href="#接下来" aria-label="Permalink to &quot;接下来&quot;">&ZeroWidthSpace;</a></h2>
<p>当前是 0.x 版本，1.0 之前接口可能调整。还没有验证过的有：Ubuntu 24.04 以外的发行版、真实 GPU、多节点 Kubernetes。欢迎在 GitHub 上提 issue 和 PR。</p>
]]></content:encoded>
        </item>
    </channel>
</rss>