多机集群部署
本指南介绍如何将单机 Cube Sandbox 部署扩展为多机集群,通过添加计算节点来实现。计算节点只运行沙箱运行时组件(内置 network runtime 的 Cubelet、CubeShim),并向第一台机器上的控制面注册。
生产环境注意
如果您计划在生产环境中使用 Cube Sandbox,请参阅网络加固指南,在将服务暴露到不可信网络之前完成安全加固。
前置条件
添加计算节点前,你必须先通过本地构建部署指南完成控制节点的部署。
架构概览
┌─────────────────────────────────────────┐
│ 控制节点 │
│ CubeMaster, CubeOps, cube-api, │
│ CubeProxy, CoreDNS, MySQL, Redis, │
│ Cubelet (network runtime) │
└──────────────────┬──────────────────────┘
│ /internal/v1/node-agent API
┌───────────┼───────────┐
▼ ▼ ▼
┌────────────┐┌────────────┐┌────────────┐
│ 计算节点 #1 ││ 计算节点 #2 ││ 计算节点 #N │
│ Cubelet ││ Cubelet ││ Cubelet │
│ net runtime││ net runtime││ net runtime│
└────────────┘└────────────┘└────────────┘- 控制节点运行完整技术栈:编排调度(CubeMaster)、节点管理(CubeOps)、API 网关(cube-api)、代理(CubeProxy + CoreDNS)、数据库(MySQL + Redis)、内置 MinIO S3 存储(供 volume 使用),同时自身也作为计算节点。
- 每个计算节点只运行内置 network runtime 的
Cubelet,向控制面CubeOps注册并接收来自CubeMaster的沙箱调度请求。
前置条件
每台计算节点需满足与控制节点相同的硬件和软件要求:
- 物理机或裸金属服务器(不支持嵌套虚拟化)
- x86_64 或 aarch64(ARM64)架构,已启用 KVM(
ls /dev/kvm) - Docker 已安装并运行
- 到控制节点的网络连通性(默认需访问
CubeOps的3010端口进行节点注册;使用内置 MinIO 时还需访问9000端口)
完整要求列表请参阅本地构建部署 — 前置条件。
第一步:准备发布包
使用与控制节点相同的发布包。将其拷贝到计算节点并解压:
tar -xzf cube-sandbox-one-click-<version>.tar.gz
cd cube-sandbox-one-click-<version>第二步:配置环境变量
cp env.example .env编辑 .env,设置以下变量:
ONE_CLICK_DEPLOY_ROLE=compute
CUBE_SANDBOX_NODE_IP=<当前节点IP>
ONE_CLICK_CONTROL_PLANE_IP=<控制节点IP>
# CUBE_S3_*:可选但强烈建议。缺失时仅告警并继续安装,S3 卷插件不可用。
# 取值方式见下方提示。内置 MinIO 时形如:
CUBE_S3_ENDPOINT=http://<控制节点IP>:9000
CUBE_S3_ACCESS_KEY_ID=<取自控制节点>
CUBE_S3_SECRET_ACCESS_KEY=<取自控制节点>
CUBE_S3_BUCKET=cube-volumes
CUBE_S3_S3FS_EXTRA_OPTS=-ouse_path_request_style| 变量 | 说明 |
|---|---|
ONE_CLICK_DEPLOY_ROLE | 计算节点必须设为 compute |
CUBE_SANDBOX_NODE_IP | 当前节点主网卡 IP |
ONE_CLICK_CONTROL_PLANE_IP | 控制节点 IP,自动拼接为 <ip>:3010 作为 CubeOps 节点注册地址 |
CUBE_S3_* | 可选但强烈建议。Volume 插件依赖 S3;缺失时仅告警并继续安装,但 S3 卷插件不可用。取值见下方提示。 |
缺失时仅告警
install-compute.sh 检查 CUBE_S3_ENDPOINT,缺失时打印醒目的黄色警告并继续安装。节点可正常部署,但 S3 卷插件不可用,补齐后重装即可。
从控制节点取 CUBE_S3_* 回填值:
- 在控制节点执行:bash输出为空说明控制节点自身未配 S3。
grep '^CUBE_S3_' /usr/local/services/cubetoolbox/.one-click.env - 把输出逐行拷贝到计算节点
.env。 - 重新执行
sudo ./install-compute.sh。
使用内置 MinIO 时,还需放行计算节点到控制面的 TCP 9000。
如果 CubeOps 使用非默认端口,也可以显式指定:
ONE_CLICK_CONTROL_PLANE_CUBEOPS_ADDR=<控制节点IP>:3010同时设置时,ONE_CLICK_CONTROL_PLANE_CUBEOPS_ADDR 优先级高于 ONE_CLICK_CONTROL_PLANE_IP。
第三步:安装
sudo ./install-compute.sh计算节点安装脚本会:
- 只安装内置 network runtime 的
Cubelet、cube-shim、cube-image、cube-kernel-scf和运行时脚本 - 只启动宿主机进程:
cubelet - 自动把
Cubelet的meta_server_endpoint指向控制面CubeOps - 通过控制面的
/internal/v1/node-agent接口向 CubeOps 注册节点并上报状态
验证部署
健康检查
sudo ./smoke.sh计算节点模式下,quickcheck.sh 会验证:
- 本机
Cubelet及其内置 network runtime 健康状态 - 控制面
CubeOps可达 - 当前节点已出现在控制面的
/internal/v1/nodes/{node_id}中
从控制节点验证
在控制节点上确认计算节点已注册:
curl http://127.0.0.1:3010/internal/v1/nodes返回结果中应包含计算节点的 IP 和健康状态。
配置 CubeMaster 调度评分
多机部署时,应在控制节点的 CubeMaster 配置中设置 scheduler.score。如果未配置评分,CubeMaster 会先过滤可用节点,再按照过滤后的节点顺序进行选择,新的沙箱可能集中到第一个可用节点,直到资源过滤器把流量推到其他节点。
可以将下面这些调度字段合并到 cubemaster.yaml 中已有的 scheduler 段。请保留当前部署已有的 filter、超时、overcommit 和其他 scheduler 配置。
scheduler:
# 保留当前部署已有的 filter、超时、overcommit 和其他 scheduler 配置。
priority_select_num: 3
score:
enable_scorers:
- real_time_weighted_average
resource_weights:
mvm_num: 2
local_create_num: 3
quota_cpu_usage: 1
quota_mem_usage: 1
plugin_conf:
real_time_weighted_average:
weight: 1.0
enable_weight_factors:
- mvm_num
- local_create_num
- quota_cpu_usage
- quota_mem_usage对于多机集群,建议将 scheduler.priority_select_num 设置为大于 1 的值,让 CubeMaster 从评分最高的一组节点中随机选择。随项目提供的默认配置使用 priority_select_num: 1,这意味着评分只会决定下一个沙箱落到哪一个节点,而不会在多个高分节点之间分散放置。小规模集群可以从 3 开始,并根据节点数量继续调整。scheduler.least_select_name 默认值为 random,通常不需要显式设置。
完整的 CubeMaster 调度配置、Cubelet 节点上报、quota / label / 并发对调度的影响,以及新增计算节点后的 template redo 操作,请参阅CubeMaster 调度器配置参考。
更新 cubemaster.yaml 后,请按当前部署方式重启 CubeMaster,让调度器加载新的评分配置。
从客户端连接集群
客户端应用需要 CubeAPI 控制面地址,以及一条通过 CubeProxy 访问沙箱服务的数据面链路。根据客户端类型选择最简单的方式:
| 方式 | 适用场景 | 泛域名 DNS | 额外组件 |
|---|---|---|---|
CubeSandbox SDK + CUBE_PROXY_NODE_IP | Python、Go 和 Node.js SDK | 不需要 | 不需要 |
| CubeProxy 路径模式 | curl、后端服务、通用 HTTP 客户端 | 不需要 | 不需要 |
| 泛域名 DNS | 生产环境、浏览器、SPA、官方 E2B SDK | 需要 | 不需要 |
| E2B 开发 sidecar | 本地没有 DNS,但必须使用官方 E2B SDK | 不需要 | 需要 |
CubeSandbox SDK:直连 CubeProxy
CubeSandbox SDK 可以直接连接指定的 CubeProxy IP,同时保留用于沙箱路由的虚拟 Host,因此不需要配置泛域名 DNS:
export CUBE_API_URL="http://<控制面IP>:3000"
export CUBE_PROXY_NODE_IP="<CubeProxy节点IP>"
export CUBE_PROXY_PORT_HTTP=80
export CUBE_TEMPLATE_ID="<模板ID或别名>"设置后即可正常使用 SDK。控制面请求访问 CubeAPI,数据面请求直接连接 CubeProxy。
通用 HTTP 客户端:路径模式
任意 HTTP 客户端都可以通过 CubeProxy 路径前缀访问沙箱服务:
http://<CubeProxy地址>:<HTTP端口>/sandbox/<sandbox-id>/<容器端口>/<路径>例如:
curl http://10.0.0.5/sandbox/abc123/49999/health路径模式不需要 DNS 或证书配置,并支持 WebSocket 升级。但它不适合使用 /static/app.js 等根绝对路径加载资源的 SPA,此类应用应使用泛域名 DNS。
生产环境和浏览器访问:泛域名 DNS
Host 模式使用 <端口>-<sandbox-id>.<域名> 格式的沙箱域名。需要配置指向 CubeProxy 的泛域名 A 记录:
*.cube.example.com → <CubeProxy公网或内网IP>CubeAPI 必须使用相同的基础域名:
export CUBE_API_SANDBOX_DOMAIN=cube.example.com一键部署内置 CoreDNS,可供本机解析 *.cube.app。它主要用于本地体验;生产环境和多机共享环境应使用托管 DNS 或内网 DNS 服务。/etc/hosts 不支持泛域名记录。
TLS 和 DNS 的完整配置请参阅 HTTPS 证书与域名解析。
官方 E2B SDK 无泛域名 DNS:开发 sidecar
官方 E2B SDK 没有 CubeSandbox SDK 的 IP 直连选项。本地开发环境无法配置泛域名 DNS 时,可以使用 E2B 开发 sidecar 示例:
cd examples/e2b-dev-sidecar
pip install -r requirements.txt
cp env.example .env连接远程集群时配置:
E2B_API_URL="http://<控制面IP>:3000"
CUBE_REMOTE_PROXY_BASE="https://<CubeProxy节点IP>:443"
E2B_API_KEY="<API密钥>"
CUBE_TEMPLATE_ID="<模板ID或别名>"然后运行:
python demo.pyCUBE_REMOTE_PROXY_BASE 必须指向 CubeProxy,不能填写 sidecar 自己的监听地址。集群启用鉴权时,需要使用有效的 API Key。
常用操作
停止计算节点服务
sudo ./down.sh计算节点模式下,该命令只会停止 cubelet,不影响控制面或其他计算节点。
重新安装
直接再次运行 install-compute.sh 即可。安装脚本会自动停止已有部署再进行安装。
查看日志
| 组件 | 日志路径 |
|---|---|
| Cubelet | /data/log/Cubelet/ |
| CubeShim | /data/log/CubeShim/ |
| Hypervisor (VMM) | /data/log/CubeVmm/ |
| 运行时 PID 文件 | /var/run/cube-sandbox-one-click/ |
| 进程标准输出/错误 | /var/log/cube-sandbox-one-click/ |
控制节点的日志路径请参阅本地构建部署 — 查看日志。
配置参考
计算节点使用相同的 .env 文件格式。以下变量与计算节点部署特别相关:
| 变量 | 默认值 | 说明 |
|---|---|---|
ONE_CLICK_DEPLOY_ROLE | control | 计算节点必须设为 compute |
ONE_CLICK_CONTROL_PLANE_IP | 空 | 控制节点 IP,默认拼接为 <ip>:3010 |
ONE_CLICK_CONTROL_PLANE_CUBEOPS_ADDR | 空 | 显式指定 CubeOps 地址,优先级高于 ONE_CLICK_CONTROL_PLANE_IP |
CUBE_SANDBOX_NODE_IP | 10.0.0.10 | 必须修改。 当前节点主网卡 IP |
CUBE_SANDBOX_NETWORK_CIDR | 192.168.0.0/18(取自 config.toml) | cubevs 本地网络 CIDR。需与控制节点一致。格式为 IPv4 CIDR(如 10.100.0.0/18),掩码范围 /16~/24。安装时自动检测宿主机冲突。 |
CUBE_SANDBOX_NETWORK_CIDR_SKIP_CONFLICT_CHECK | 0 | 设为 1 跳过冲突检测(不推荐)。 |
ONE_CLICK_RUN_QUICKCHECK | 1 | 安装后是否执行健康检查 |
CUBE_S3_* | 空 / 由控制面 MinIO 填入 | 可选但强烈建议。Volume 插件依赖 S3,缺失时仅告警、S3 卷插件不可用。从控制节点 /usr/local/services/cubetoolbox/.one-click.env 拷贝(取值方法见上文第二步);ENDPOINT / ACCESS_KEY_ID / SECRET_ACCESS_KEY / BUCKET 无可用默认值。 |
完整配置参考(构建选项、数据库、代理等)请参阅本地构建部署 — 配置参考。
故障排查
计算节点无法连接 CubeOps
检查网络连通性:
curl http://<控制节点IP>:3010/internal/v1/nodes如果失败,请检查:
- 控制节点的防火墙规则(
3010端口需可访问) .env中ONE_CLICK_CONTROL_PLANE_IP或ONE_CLICK_CONTROL_PLANE_CUBEOPS_ADDR的值
节点未出现在控制面
如果 smoke.sh 本地通过但控制面上看不到该节点:
- 检查 Cubelet 日志:
/data/log/Cubelet/ - 确认 Cubelet 配置中的
meta_server_endpoint指向正确的 CubeOps 地址 - 确保
CUBE_SANDBOX_NODE_IP设为可路由的 IP(不是127.0.0.1)
通用故障排查(Docker、KVM、DNS 等)请参阅本地构建部署 — 故障排查。