进阶 docs.cubesandbox.com 2026-10-08 23:44:25 · 7 阅读
第27章 S3 持久卷(S3 Volume)
S3 持久卷(S3 Volume) 给沙箱一个跨生命周期持久化的存储:创建一个 Volume → 挂到沙箱里读写 → 沙箱销毁后数据仍在 → 下次再挂回来继续用。后端是任意 S3 兼容对象存储(AWS S3、腾讯云 COS、Cloudflare R2、MinIO……),CubeSandbox 默认安装已自带一个 MinIO 作为后端。默认安装(one-click / Helm 默认值)已经配好了。 安装脚本会自动起一个 MinIO,并把 S3 Volume 插件、凭证、CubeMaster/Cubelet 配置全部接好。你不需要手动编辑 volume-s3.conf,也不需要装插件 —— 直接跳到 用法 即可。只有当你想把后端换成外部 S3(AWS S3、腾讯云 COS、R2、自建 MinIO 等)时,才需要看 接入外部 S3。它能做什么 能力说明跨沙箱持久化沙箱销毁后 Volume 数据保留,下次创建沙箱再挂回来继续读写多沙箱共享同一个 Volume 可被多个沙箱同时挂载只读挂载每个挂载可单独设只读,适合共享模型/数据集任意 S3 兼容后端默认捆绑 MinIO;也可换 AWS S3、腾讯云 COS、Cloudflare R2 等凭证不进沙箱凭证只在宿主机上,沙箱内只看到一个文件系统用法 1. 安装 SDK bashpip install 'cubesandbox>=0.6.0'用 cubesandbox,不要用官方 e2b SDK官方 e2b Python SDK 会把请求硬编码发到 e2b.cloud 后端,不能用于 CubeSandbox。请使用 cubesandbox。2. 配置环境变量 在能访问 CubeAPI 的开发机上:bashexport CUBE_API_URL=http://:3000
export CUBE_TEMPLATE_ID=
# 远程读写已挂载 Volume 时必需(数据面经由 CubeProxy)
export CUBE_PROXY_NODE_IP=
# 集群开启鉴权时:
# export CUBE_API_KEY=3. 创建 Volume 并挂到沙箱 pythonfrom cubesandbox import Sandbox, Volume
vol = Volume.create("my-data", driver="s3") # 默认安装下省略 driver 也走 S3
print("volume_id:", vol.volume_id)
with Sandbox.create(volume_mounts={"/workspace": vol}) as sb:
sb.files.write("/workspace/hello.txt", "from S3 volume")
print(sb.files.read("/workspace/hello.txt")) # → from S3 volume
# 沙箱销毁后数据仍在;下次再挂回来,文件还在
with Sandbox.create(volume_mounts={"/workspace": vol}) as sb:
print(sb.files.read("/workspace/hello.txt"))
# 真正删除 Volume(后端数据被清空,不可恢复)
Volume.destroy(vol.volume_id)volume_mounts 是 {沙箱内路径: Volume} 的映射,一次可挂多个。沙箱销毁不会删 Volume 数据;只有 Volume.destroy() 才会清空。只读挂载 / 多沙箱共享 pythonfrom cubesandbox import VolumeMount
vol = Volume.create("shared-dataset", driver="s3")
with Sandbox.create(volume_mounts={"/data": VolumeMount(vol, read_only=True)}) as sb:
sb.files.read("/data/model.bin")配合跨机快照使用 S3 Volume 的数据位于共享对象存储,因此沙箱在其他节点恢复时可以重新 Attach。它与 VM Snapshot backend 是两套独立配置:使用 --backend s3 构建沙箱模板,并等待 Snapshot 的 remote_status 变为 ready。在每个候选 Cubelet 节点配置相同的 s3 Volume driver、CUBE_S3_* 连接信息和 s3fs 依赖。FromSnap 先从 VM Snapshot 包恢复 VM/rootfs 状态,再 Attach 已有 Volume ID。Volume 数据不会回到快照时刻;恢复后的沙箱看到当前内容。如果 Volume 已删除、目标节点缺少 driver,或者 S3 Attach 失败,沙箱创建会在 VM 启动前失败。VM 兼容性和跨机调度条件见跨机快照。接入外部 S3 默认安装用内置 MinIO。想换成外部 S3(AWS S3、腾讯云 COS、R2、自建 MinIO 等),按你的部署方式改对应的"源"——安装器会自动生成 volume-s3.conf,不要手动编辑该文件(它会被重写)。one-click 部署 在 .one-click.env(或 env.example)里关掉内置 MinIO、填 CUBE_S3_*,重跑 install.sh,它会写出 volume-s3.conf:bashCUBE_SANDBOX_MINIO_ENABLED=0
CUBE_S3_ENDPOINT=https://s3.example.com
CUBE_S3_ACCESS_KEY_ID=...
CUBE_S3_SECRET_ACCESS_KEY=...
CUBE_S3_BUCKET=cube-volumes
# CUBE_S3_REGION=us-east-1
# CUBE_S3_S3FS_EXTRA_OPTS=-ouse_path_request_style计算节点不部署 MinIO,把控制节点回填的 CUBE_S3_* 拷过去即可:bash# 在控制节点执行,把输出拷贝到计算节点 .env
grep '^CUBE_S3_' /usr/local/services/cubetoolbox/.one-click.env缺失时仅告警并继续安装,S3 卷插件将不可用。详见 one-click README · 内置 MinIO 与 S3 Volume 插件。Helm 部署 在 values 里关掉 chart MinIO、填 volumeS3.*(或用 volumeS3.existingSecret 指向已有 Secret),helm upgrade 后 chart 会渲染 volume-s3.conf Secret:yamlminio:
enabled: false
volumeS3:
endpoint: https://s3.example.com
accessKeyId: ...
secretAccessKey: ...
bucket: cube-volumes
# region: us-east-1
# extraOpts: -ouse_path_request_style详见 chart values.yaml 的 volumeS3 段。从零手动部署(非 one-click / 非 Helm) 手动部署插件、手写 volume-s3.conf 的完整步骤见 examples/volume/s3/README.zh.md;腾讯云 COS 的建桶、取密钥指引(基于独立的 cos 驱动插件,而非本插件)见 examples/volume/cos/README.zh.md。常见后端 提供方ENDPOINTREGIONAWS S3https://s3..amazonaws.com桶所在地域腾讯云 COShttps://cos..myqcloud.com桶所在地域(如 ap-guangzhou)Cloudflare R2https://.r2.cloudflarestorage.comautoMinIOhttp://:9000任意值常见问题 S3 Volume 和 Host Mount 有什么区别? Host Mount 把节点上已有的目录绑定进沙箱,节点本地、适合共享现成数据。S3 Volume 是用户级持久卷(e2b Volume API),由插件按需创建/销毁、跨沙箱生命周期管理、后端是对象存储。两者互补:Host Mount 适合"节点上已有目录",S3 Volume 适合"每个用户/任务一个独立持久卷"。省略 driver 会怎样?为什么默认走 S3? Volume.create(...) 省略 driver 时,CubeMaster 取 volume_plugins 列表的第一项。默认安装现已把 s3 排在第一,所以省略 driver 即走 S3。显式写 driver="s3" 仍推荐——在多后端集群里意图更清晰,也避免有人把 cos 调到前面后行为悄悄变化。沙箱销毁后数据还在吗?Volume 的生命周期是怎样的? 在。Volume 的挂载/卸载由引用计数驱动,你不需要手动管挂载点:操作行为Volume.create在后端建一个 volumes// 前缀沙箱挂载(refCount 0→1)Cubelet 用 s3fs 把该前缀挂到宿主机,再透传进 microVM沙箱挂载(refCount >0)复用已有挂载,不重复 mount沙箱销毁(refCount >1)仅减计数,不卸载沙箱销毁(refCount →0)fusermount -u 卸载,后端数据保留Volume.destroy删除整个 volumes// 前缀,不可恢复删除 Volume 会怎样?为什么有时返回 409? Volume.destroy 会清空后端整个 volumes// 前缀,不可恢复。有沙箱仍持有该 Volume 时 API 会拒绝并返回 409——先销毁所有使用它的沙箱再删。注意节点崩溃后引用计数可能失真(集群级计数归零但某节点仍持有挂载),删除前请确认。桶必须提前创建吗? 不必。Create 会先 head-bucket,桶不存在时自动创建;桶已存在则直接用,不需要 s3:CreateBucket 权限。故障排查 现象排查方向unknown driver: s3CubeMaster volume_plugins 没注册 s3,或没重启no plugin registered for driver "s3"Cubelet 没注册同名插件,或没重启attach 失败 s3fs mount failed宿主机 ls /dev/fuse 是否存在;凭证/ENDPOINT 是否正确InvalidAccessKeyId / SignatureDoesNotMatch密钥错、缺桶权限,或 REGION 与 Endpoint 期望的 SigV4 地域不符桶名含点号s3fs 默认 virtual-hosted 寻址,带点的桶名会 TLS 失败。改用无点桶名,或在 conf 里设 S3FS_EXTRA_OPTS=-ouse_path_request_style(MinIO 通常也需要)SDK 写入失败没设 CUBE_PROXY_NODE_IP;或 CubeAPI/模板未就绪Volume.create 没走 s3省略 driver 时取 volume_plugins 第一项;默认安装下第一项是 s3。若你的集群把 cos 调到了前面,请显式写 driver="s3"更多排障与协议细节:Volume 插件开发指南、S3 插件完整指引。