最近在给 AI Agent 接入代码执行能力时,我一直被一个问题困扰:AI 生成的代码到底应该在哪里跑?直接放在宿主机上跑,安全风险太大;放在普通容器里跑,很多容器逃逸和资源耗尽的问题依然存在。网上关于权限控制的文章很多,但真正能解决“人员不可信、代码不可信、状态不可保留”这个组合问题的思路并不多。后来我在调研 microVM 沙箱时看到 microsandbox 这个项目,从设计思路上确实打开了局面。这篇文章就围绕 microsandbox 这类 microVM 运行时展开,聊聊为什么 AI 需要的不是更细的权限管理,而是一个用完就销毁的沙箱,然后完整走一遍环境准备、核心原理、实战接入与排错过程。
如果你正在做 AI Agent、自动化编程助手、代码解释器,或者需要让大模型生成的代码在一个受控环境里运行,这篇文章会比较适合你。读完以后,你会理解 microVM 和普通容器、虚拟机的区别,明白“用完即销毁”这一设计对 AI 场景为什么重要,也能照着文中的示例搭建一套最小可用的沙箱执行链路。
1. 背景与核心概念
1.1 为什么“权限管理”不够用
很多团队在面对 AI 代码执行风险时,第一反应是把权限管理做得更细。比如给模型生成的代码一个普通用户账号,用 RBAC 控制文件访问,再用 seccomp 或 capabilities 限制系统调用。这个思路本身没有错,但在 AI 代码执行场景下存在几个很难绕开的盲区。
第一个盲区是“代码内容不可预知”。AI 生成的代码不是人写完后经过 review 再发布,而是每次动态产生,可能来自用户输入、模型幻觉、第三方依赖的组合。你很难在为每次执行都精确枚举该授予哪些权限。第二个盲区是“系统漏洞依然存在”。即使你配置了严格的权限,一旦内核或运行时存在可被利用的漏洞,攻击者通过 AI 生成的恶意代码同样可能拿到宿主机的权限。第三个盲区是“状态残留”。如果执行环境有持久化目录、后台进程或临时凭证,一次任务结束后这些状态可能留在宿主机上,成为下一次任务的隐患。
所以,在 AI 场景下,我们需要的不只是“给什么权限”,而是“是否给出一个完整、独立、用完即焚的执行空间”。沙箱的意义不是把权限管理做得更完美,而是把不可信代码和宿主环境彻底隔离开,并在任务结束时销毁整个环境。microVM 沙箱就是这类方案里比较典型的一种落地形态。
1.2 容器、虚拟机与微虚拟机怎么选
在讲 microsandbox 之前,先区分三个经常被混在一起的概念:容器、虚拟机、微虚拟机(microVM)。
容器与宿主机共享内核,隔离手段主要依赖 Linux 的 namespace、cgroups、seccomp 等机制。容器启动快、镜像生态成熟,但隔离边界比较薄。如果宿主机内核本身有漏洞,容器内恶意代码有一定概率影响到宿主机。
虚拟机通过硬件虚拟化把 Guest OS 与宿主机内核隔离开,隔离强度更高,但传统虚拟机启动速度慢、资源开销大,不适合每次任务都创建一台完整 VM。
microVM 是面向云原生场景优化的轻量级虚拟机,保留了虚拟机的隔离强度,同时精简掉传统虚拟化中不必要的设备和复杂度。它可以在几百毫秒到一秒左右启动,内存占用也远小于传统虚拟机。microsandbox 正是把 microVM 作为“沙箱容器”的运行时,让每个 AI 任务跑在一个独立的微型虚拟机里。
1.3 microsandbox 是什么
microsandbox 是一个面向短时、不可信任务设计的 microVM 运行时项目。它的核心思路可以概括为:把一次代码执行任务打包成镜像,从一个最小化的 microVM 启动,任务结束后整个 VM 直接销毁,不保留磁盘、网络和进程状态。
这类项目在 GitHub 上已经有相当热度,标题里提到的 8k Star 也说明它确实戳中了很多 AI 开发者的痛点。你不需要在一台机器上提前划分固定资源,也不需要维护一整套虚拟机模板。microsandbox 更像是一个“执行入口”:你提供镜像和资源限制,它负责启动 microVM、注入任务、收集结果,然后清理 VM。
在 AI 场景中,它的价值非常直接:AI Agent 可以不断生成代码、不断试错,每一次试错都使用全新的沙箱环境,得到的错误信息被返回给 Agent 继续迭代,成功后再把结果保留到外部存储。整个过程里,沙箱不保存任何可变状态,也就不会把一次运行中的脏数据带到下一次。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与版本说明
2.1 硬件与内核要求
microsandbox 依赖 KVM(Kernel-based Virtual Machine)来启动 microVM,所以宿主机必须有支持虚拟化的 CPU,并且内核需要加载 KVM 模块。在 Linux 系统中,可以通过下面命令确认 KVM 是否可用:
bash复制ls -l /dev/kvm
如果输出 /dev/kvm 存在,说明当前环境基本满足硬件要求。如果文件不存在,需要先确认 BIOS/固件中的虚拟化开关是否打开,或者检查宿主机是否本身运行在虚拟机中且未开启嵌套虚拟化。
内核版本方面,建议使用较新的 Linux 发行版,比如 Ubuntu 22.04 LTS、Debian 12 或 CentOS Stream 9。不同 microVM 运行时对内核有不同要求,但较新内核通常对 KVM、overlayfs、网络命名空间等特性支持更好。这里不指定唯一版本,因为实际项目中需要按你的宿主机和 microsandbox 版本调整。
2.2 安装基础依赖
为了方便构建镜像和提交任务,建议先安装 Docker 或 containerd,以及 curl、jq、make 等常用工具。以 Ubuntu/Debian 为例,可以先更新软件源再安装:
bash复制sudo apt update
sudo apt install -y curl jq make git docker.io
sudo systemctl enable --now docker
如果你希望在 Kubernetes 集群中接入 microsandbox,还需要安装 kubeadm、kubelet 和 kubectl。这里不展开 Kubernetes 集群搭建过程,只提醒一点:务必保证 kubelet 所在节点也能访问 /dev/kvm,否则沙箱运行时无法在该节点启动 microVM。
2.3 获取 microsandbox 运行时
microsandbox 的具体安装方式应以项目官方文档为准。一般情况下,开源项目会提供编译好的 release 二进制,或者源码构建的入口。拿到二进制后,推荐放到 /usr/local/bin 并赋予可执行权限,下面是一段安装逻辑示例:
bash复制# 请根据官方 release 页面替换实际下载地址
curl -fSL "<官方下载地址>" -o /usr/local/bin/microsandbox
chmod +x /usr/local/bin/microsandbox
microsandbox version
如果项目没有发布二进制,也可以从源码编译。编译前需要确认 Go 或 Rust 工具链版本是否满足项目要求。实际操作时,不要直接照搬网上任意一段安装命令,最好先去官方 README 确认最低版本和依赖项。这里写“版本需要根据项目实际情况调整”,并不是推脱,而是这类运行时项目迭代很快,写死某个版本号反而容易误导读者。
3. 核心原理拆解
3.1 一次沙箱会话的完整生命周期
microsandbox 这类 microVM 运行时的运行流程,可以拆成下面几个步骤。
第一,接收任务。调用方把要执行的代码、参数、资源限制和镜像名称提交给 microsandbox。这个提交动作可以是 CLI 命令、HTTP API 或 CRI 接口。第二,准备镜像。运行时从本地仓库或远程 registry 获取指定镜像,并把它转换成 microVM 需要的根文件系统。第三,启动 microVM。microsandbox 通过 KVM 创建一个新的虚拟机,分配 vCPU、内存、网络等资源,挂载根文件系统。第四,执行任务。任务入口在虚拟机内部启动,输出结果会被转发回调用方。第五,收集结果并销毁。任务正常结束或超时后,microsandbox 收集 stdout、stderr、退出码,然后销毁 VM、释放资源。
“用完即销毁”的关键就在第五步。传统容器执行完还会留下容器层、日志文件、hook 状态;而 microsandbox 的目标是让执行环境与执行任务同生命周期。任务结束,环境就消失。这样即使代码在沙箱里做过什么,也无法影响下一次任务。
3.2 microVM 的隔离层次
microVM 的隔离强度来自硬件虚拟化,而不是单纯靠内核的 namespace。每个 microVM 有自己的虚拟 CPU 和内存,Guest 内核与宿主机内核彼此隔离。Guest 内执行的恶意代码即使拿到了 root 权限,也首先要尝试逃出虚拟化边界,而虚拟化边界本身的攻击面相比容器要小得多。
同时,microsandbox 会尽量精简 guest 设备模型。没有用的设备、端口、驱动都可以不暴露。设备越少,攻击面越小。对于 AI 代码执行这种场景,大部分任务只需要 CPU、内存、基本输入输出和临时文件系统,不需要完整物理设备暴露。
从资源维度看,microVM 还能给每个任务设定严格的 CPU 和内存上限,避免 AI 生成的代码因为死循环或大对象分配拖垮宿主机。这也是“沙箱”区别于普通后台任务调度的重要一点:沙箱不仅要隔离,还要限制资源。
3.3 无持久化状态与临时文件系统
“用完即销毁”在文件系统层面的实现,通常是使用只读根文件系统加临时内存盘或临时磁盘。任务写入的数据默认存放在临时存储中,任务结束,临时存储被卸载和释放。如果任务确实需要对外持久化,应当显式地通过外部接口写回,比如对象存储、数据库或宿主机上的独立目录。
这种设计的最大好处是避免“脏状态”蔓延。AI Agent 在一次执行中可能产生缓存文件、临时脚本、模型权重片段,如果这些内容留在沙箱里,下一个任务就可能读到上一个任务的数据,甚至被恶意任务植入持久化后门。无持久化状态从底层切断了这个风险。
在接入 AI Agent 时,你需要在设计上养成一个习惯:所有需要保留的数据,都要通过任务返回结果或独立的数据通道传递出去。沙箱内部不是数据存储位置,只是计算场所。
3.4 网络最小化原则
许多 AI 代码执行任务并不需要访问外网,比如计算数据统计、解析文本、做单元测试。microsandbox 通常支持将网络设为“无网络”或“受限网络”。无网络意味着虚拟机内没有可用的网络设备,代码无法发起外部连接,也无法反向连接宿主机的其他服务。
如果任务确实需要网络,比如 pip install 依赖或调用内部 API,建议通过白名单或代理方式限定出口。比如只允许访问内网镜像源,其他地址一律拒绝。网络最小化不仅可以减少数据泄露风险,也能显著降低恶意代码建立 C2 通道的概率。
4. 完整实战案例:让 AI Agent 在沙箱中执行代码
4.1 设计一个最小演示任务
我们先明确要做什么:假设你有一个 AI Agent,用户向它提了一句“统计下面这段文本中每个单词出现的次数”,Agent 根据模型生成一段 Python 代码,然后把代码交给沙箱执行。沙箱需要限制 CPU、内存、网络,并在执行完成后返回结果。
为了让案例简单,我们不直接接大模型 API,而是模拟“Agent 生成代码并提交”的过程。你可以把下面的 Python 文件想象成 Agent 内部的一个工具函数,它接收代码字符串和输入数据,把它们打包成沙箱任务。
4.2 构建沙箱内执行镜像
沙箱需要有一个固定入口,读取任务内容和代码,然后执行。这里我们构建一个小镜像,里面只包含 Python 和一个入口脚本。写入口脚本的思路是:把代码从环境变量或文件中读取出来,通过 exec 执行,同时捕获输出。
首先创建项目目录:
bash复制mkdir -p ai-sandbox-demo/executor
cd ai-sandbox-demo
接着创建 executor/executor.py:
python复制#!/usr/bin/env python3
import os
import sys
import json
import textwrap
def main():
# 从环境变量读取任务载荷
payload = os.environ.get("TASK_PAYLOAD", "")
if not payload:
print(json.dumps({"error": "TASK_PAYLOAD is required"}), file=sys.stderr)
return 1
try:
task = json.loads(payload)
except json.JSONDecodeError as exc:
print(json.dumps({"error": f"invalid payload: {exc}"}), file=sys.stderr)
return 1
code = task.get("code", "")
data = task.get("data", {})
# 在受限的名称空间中执行代码
namespace = {"data": data, "result": None}
try:
exec(compile(textwrap.dedent(code), "<sandbox>", "exec"), namespace)
except Exception as exc:
print(json.dumps({"error": f"{type(exc).__name__}: {exc}"}), file=sys.stderr)
return 1
result = namespace.get("result")
print(json.dumps({"result": result}))
return 0
if __name__ == "__main__":
sys.exit(main())
这段代码的作用是:从 TASK_PAYLOAD 环境变量中读取 JSON,JSON 里包含 code 和 data 两部分。code 是 AI 生成的 Python 代码,data 是给代码用的输入数据。执行时,我们把代码放入一个独立命名空间,避免污染主模块。代码可以访问 data,并且应该把最终结果赋给 result 变量。
这里要注意一个问题:exec 执行任意代码并不安全,真正的安全性来自 microVM 沙箱,而不是这段入口脚本。入口脚本的作用是规范执行方式,让 AI 生成的代码有一个统一接口。
然后创建 executor/Dockerfile:
dockerfile复制FROM python:3.11-slim
RUN useradd -m sandboxuser
WORKDIR /app
COPY executor.py /app/executor.py
USER sandboxuser
ENTRYPOINT ["python", "/app/executor.py"]
这个镜像很小,只有 Python 运行环境和入口脚本。使用非 root 用户运行是沙箱里的一道额外防线。构建镜像:
bash复制docker build -t ai-executor:latest ./executor
4.3 配置沙箱资源限制
microsandbox 运行时一般通过配置文件或命令行参数指定资源限制。如果你使用的是 CRI 兼容模式,可以像配置普通容器一样设置 resources;如果你使用的是独立 CLI,通常会有 --cpu、--memory、--network 等参数。
下面是一个沙箱配置示例,实际字段名需要按项目文档调整:
yaml复制sandbox:
image: ai-executor:latest
cpu: 0.5
memory: 256Mi
network: none
timeout: 30s
destroy_on_exit: true
这里限制 CPU 为 0.5 核,内存为 256 MiB,网络为 none,超时 30 秒,任务结束自动销毁。网络设置为 none 最安全,因为它从底层杜绝了恶意代码外联的可能。如果你的 AI 任务需要安装依赖,可以改成只允许访问某个内网源,但不要直接开放公网。
4.4 提交一个任务
现在,模拟 Agent 提交代码。创建一个 submit_task.py 脚本,它把用户指令对应的 AI 生成代码打包成 JSON,再通过 subprocess 调用沙箱 CLI:
python复制#!/usr/bin/env python3
import json
import subprocess
import sys
code = """
from collections import Counter
words = data.split()
result = Counter(words)
"""
data = "hello sandbox hello microvm hello ai"
payload = {
"code": code,
"data": data,
}
# 假设 microsandbox 提供类似 run 的子命令
cmd = [
"microsandbox", "run",
"--config", "sandbox.yaml",
"--env", f"TASK_PAYLOAD={json.dumps(payload)}"
]
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
print("stdout:", proc.stdout)
print("stderr:", proc.stderr)
print("exit code:", proc.returncode)
执行:
bash复制python submit_task.py
预期输出结果包含了词频统计信息,类似 {"result": {"hello": 2, "sandbox": 1, "microvm": 1, "ai": 1}}。如果入口脚本捕获到异常,会在 stderr 输出错误信息,这样 AI Agent 就能拿着错误信息继续修改代码。
再次强调,上面的 microsandbox run 命令属于示意。实际运行时可能提供 HTTP API、Unix Socket 或另外的子命令结构。在接入自己项目时,以官方 README 和 CLI help 为准。
4.5 在 Kubernetes 中接入沙箱运行时
如果你的团队已经在用 Kubernetes,并且 microsandbox 提供了 CRI 兼容的运行时实现,那么你可以用 RuntimeClass 把特定任务调度到沙箱运行时。这样可以让 AI Agent 像创建普通 Pod 一样创建隔离任务。
创建 runtimeclass.yaml:
yaml复制apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: microsandbox
handler: microsandbox
然后创建任务 task.yaml:
yaml复制apiVersion: batch/v1
kind: Job
metadata:
name: ai-task-demo
spec:
template:
spec:
runtimeClassName: microsandbox
restartPolicy: Never
containers:
- name: executor
image: ai-executor:latest
env:
- name: TASK_PAYLOAD
value: '{"code":"from collections import Counter; words = data.split(); result = Counter(words)","data":"hello sandbox hello microvm hello ai"}'
resources:
limits:
cpu: "0.5"
memory: 256Mi
提交任务:
bash复制kubectl apply -f runtimeclass.yaml
kubectl apply -f task.yaml
kubectl wait --for=condition=complete job/ai-task-demo --timeout=60s
kubectl logs job/ai-task-demo
任务完成后,通过 kubectl delete job ai-task-demo 删除 Job。如果 RuntimeClass 指向的运行时支持“用完即销毁”,那么删除 Job 时对应的 microVM 也会被销毁,不会在节点上留下容器状态。
这种方式适合需要接入现有 CI/CD 或 AI 推理平台的团队。它的好处是:AI Agent 不需要知道底层是 microVM,只需要提交一个标准 Kubernetes Job,调度、资源限制、生命周期管理都交给平台处理。
5. 常见问题与排查思路
5.1 高频问题汇总
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
启动沙箱报 /dev/kvm not found |
宿主机未开启虚拟化,或处于嵌套虚拟化未开启状态 | 检查 BIOS 虚拟化开关,确认宿主机 CPU 支持 KVM,必要时调整云厂商实例类型 |
| 任务启动慢 | 镜像过大或首次冷启动需要拉取和转换根文件系统 | 使用更小的基础镜像,提前预拉镜像,开启镜像缓存 |
| 沙箱内无法访问网络 | 配置了 network: none 或网络策略未放行 |
确认任务是否真的需要网络,需要时改为受限 NAT 并配置白名单 |
| 执行超时被终止 | 代码存在死循环或资源消耗过大 | 设置合理 timeout,建议 AI Agent 在生成代码时自带超时保护逻辑 |
| 返回结果丢失 | 入口脚本只捕获 stdout,但任务将结果写入临时文件 | 统一使用 JSON 输出协议,代码只能通过 result 返回结果 |
| 删除 Job 后节点上仍有残留进程 | RuntimeClass 没有真正指向 microVM 运行时,或运行时实现未正确清理 | 检查节点容器运行时配置,确认 runtime handler 已生效,查看运行时日志确认销毁流程 |
| 代码需要安装第三方依赖 | 沙箱内没有外网 | 制作镜像时将依赖安装好,或通过私有镜像源在镜像构建阶段完成 |
上表给出的问题,多数是从实际工程经验里总结出来的。如果你遇到类似报错,建议按这个顺序排查:先确认 /dev/kvm 是否可用,再确认运行时版本和配置是否匹配,然后查看沙箱日志,最后用最小镜像验证基础链路是否畅通。
5.2 排查三步法
第一步,验证宿主机虚拟化。执行 ls -l /dev/kvm,如果没有输出,说明 KVM 不可用。不要跳过这一步,因为 microVM 运行时对 KVM 的依赖是硬性的。
第二步,验证镜像和入口。先在普通 Docker 环境里运行 docker run --rm -e TASK_PAYLOAD='...' ai-executor:latest,确认入口脚本本身没有逻辑错误。普通容器能跑通后,再切到 microsandbox 运行时。这样可以快速区分是代码问题还是运行时问题。
第三步,分析运行时日志。很多沙箱运行时会把 VM 启动日志写到独立的日志文件里。查看日志中是否有网络创建失败、根文件系统挂载失败、设备模型初始化失败等关键词,这些通常是配置错误导致的。
6. 最佳实践与工程建议
6.1 用不可变镜像作为沙箱边界
沙箱镜像应该尽量不可变。不要在任务运行时往镜像里写代码,也不要允许沙箱内部把新镜像推送到 registry。AI Agent 生成的代码应该作为“载荷”传入沙箱,而不是成为镜像的一部分。这样每次执行都从同一个基准镜像启动,可重复性更高,也更难被恶意代码植入持久后门。
制作镜像时,优先选择精简基础镜像。Python 任务可以选择 python:3.11-slim,Node.js 任务可以选择 node:20-alpine 之类的镜像。镜像越小,冷启动越快,攻击面也越小。
6.2 对 AI Agent 的任务协议做统一约束
建议在沙箱入口定义一个统一协议,比如上面案例中的 JSON 协议:code 字段只负责计算逻辑,data 字段只负责输入数据,result 字段只负责输出结果。这样做的好处是,AI Agent 的每一次执行都能被标准化,出问题时也能准确定位是代码逻辑、输入数据还是运行时的问题。
协议要包含错误信息结构。AI Agent 需要拿到可读的异常信息才能自我修正。如果你只把 stderr 原样返回,很多模型不一定理解在哪一行出了什么错。可以在入口脚本里做一层格式化,例如将 NameError、TypeError、ImportError 等常见异常整理成简短描述。
6.3 永远不要信任沙箱内的产物
即使有了 microVM 隔离,也不能把沙箱返回的所有内容都当作安全结果。比如让 AI 生成一个读取文件内容的代码,沙箱内读取的是它自己的虚拟磁盘,而不是宿主机文件;但如果任务被设计成“把宿主机某个目录挂载进沙箱”,那挂载目录的安全性就需要额外评估。
生产环境里,应该默认沙箱内没有宿主机敏感数据。如果需要给沙箱提供外部数据,优先通过标准接口传入,比如 API Token 要按最小权限生成,并且只存在任务生命周期内。任务结束后,Token 要立即失效。
6.4 资源限制与超时缺一不可
microVM 的 CPU 和内存限制能防止资源耗尽,但代码可能因为逻辑错误进入死循环,需要超时机制兜底。建议在运行时层设置任务超时,同时在入口脚本层也实现一层超时控制。双层超时能避免单个任务长时间占用 vCPU。
对 AI 场景,还要注意一个问题:AI Agent 经常会产生一系列连续尝试,每次尝试都启动新沙箱。如果沙箱启动速度太慢,Agent 的迭代体验会非常糟糕。可以把沙箱预热、镜像缓存、轻量 rootfs 等优化结合起来,尽量降低单次启动延迟。
6.5 安全加固建议
在 microVM 沙箱基础上,建议叠加以下加固策略:
- 使用非 root 用户运行任务入口。
- 挂载只读根文件系统,临时目录使用内存盘。
- 默认关闭网络,按需开放白名单。
- 限制系统调用,使用 seccomp profile。
- 对镜像来源做签名校验,不允许随意拉取未知镜像。
- 对沙箱日志做脱敏处理,避免把用户敏感信息写入日志中心。
- 生产环境所有变更先在小规模节点灰度,确认稳定后再全量推广。
这些策略并不复杂,但能明显提升整体安全水位。沙箱不是银弹,只有结合最小权限、镜像校验、网络控制和资源限制,才能形成完整的防御闭环。
6.6 生产环境变更注意事项
如果你要在生产环境引入 microsandbox 或同类运行时,不要直接对全部业务流量切换。先在独立节点池部署一套沙箱运行时,用小流量任务验证启动速度、销毁流程、监控告警是否完善。等指标稳定后,再逐步扩大范围。
同时在配置变更时要保留回滚方案。比如 Kubernetes RuntimeClass 的 handler 修改,可能影响新创建的任务,但不影响已运行的任务。任何时候修改运行时配置,都要提前备份配置并明确回滚步骤。数据库、权限、删除类操作也一样,生产环境必须遵循最小权限和审批流程。
7. 总结与下一步学习建议
到这里,我们已经把 microsandbox 这类 microVM 沙箱运行时的核心思路完整梳理了一遍。关键点有三个:AI 代码执行场景需要的是隔离和销毁,而不是无限细化权限;microVM 在隔离强度和启动速度之间取得了比较好的平衡;沙箱内的一切状态都应该随任务结束而消失,数据只能通过外部通道持久化。
文中的实战案例虽然做了若干简化,但已经覆盖了“容器镜像 + 任务载荷 + 沙箱执行 + 结果返回”的完整链路。如果你的团队正在接入 AI Agent,可以从这个最小闭环开始验证。先跑通一个任务,再逐步加入网络策略、镜像签名、监控告警,最后再考虑大规模调度。
下一步可以继续学习几个方向:Firecracker 和 Cloud Hypervisor 的 microVM 实现细节、Kata Containers 的 CRI 接入方式、Kubernetes RuntimeClass 和设备插件机制,以及 OCI Runtime Spec 底层约束。理解了这些基础,再回头看 microsandbox 的文档和源码,会顺畅很多。
如果这篇文章对你有帮助,可以收藏备用。如果你已经在生产环境接入过类似的 microVM 沙箱,欢迎在评论区聊聊你遇到的坑,这对正在选型的人来说会很有价值。
