CubeSandbox Kubernetes 实战:从节点预检到第一个 MicroVM 沙箱¶
这篇文章记录一次真实的 CubeSandbox Kubernetes 部署:不只让 Pod 变成 Running,还要让计算节点成功注册、模板完成构建、KVM MicroVM 真正启动、命令能够执行,最后把测试沙箱销毁干净。
实验固定使用官方 v0.7.0。Kubernetes 交付在该版本仍标注 Preview,因此本文是可复现的 PoC 路径,不是直接复制到生产环境的标准答案。部署条件、宿主机权限、PVM 风险和生产阻塞项,参见CubeSandbox Kubernetes 部署条件与生产评估;如果想继续把它作为 OpenClaw / DSH 的企业执行面,参见用 CubeSandbox 增强 OpenClaw 与 DSH。
先给出最终结果:
- Helm release 成功进入
deployed,控制面、三个 StatefulSet 和三组节点 DaemonSet 全部 Ready; - 4 个 PVC 全部绑定,CubeMaster、MySQL、Redis、MinIO 数据均有持久卷;
- 官方 Chart 自带的 8 组 Helm tests 全部
Succeeded; - 一个原生 KVM 计算节点注册为
HEALTHY=true、HOST_STATUS=RUNNING; - 使用官方
sandbox-code镜像构建出READY模板; - 临时沙箱成功进入
running,在 Guest 中执行命令后正常销毁; - 验收结束后沙箱数量回到 0,节点上原有的 KubeVirt 虚拟机继续运行。
本文所有地址、节点名、仓库和凭据都使用公开占位符。<...> 必须替换为自己的环境值。
1. 实验目标与边界¶
本次不是从一台空白服务器开始,而是在一个已有 Kubernetes 集群中选择一台原生支持 KVM 的测试节点,让它同时承载 CubeSandbox 控制面和计算面。
选择这条路径有三个目的:
- 验证 CubeSandbox 能否与现有 Kubernetes、CNI、CSI 和 KubeVirt 工作负载共存;
- 避免 PVM 换宿主机内核和重启,把变量收敛到 Chart、节点初始化、存储和网络;
- 用最小资源跑通完整生命周期,再决定是否建设专用节点池。
实验环境采用以下匿名化规格:
| 项目 | 实验配置 | 说明 |
|---|---|---|
| CubeSandbox | v0.7.0 |
Chart 与组件使用同一版本 |
| Kubernetes | v1.30.x |
高于官方 v1.24+ 下限 |
| 节点架构 | linux/amd64 |
原生 KVM,不使用 PVM |
| 节点内核 | Linux 5.10 | /dev/kvm 可用,KVM 模块已加载 |
| CPU / 内存 | 100+ 逻辑 CPU、250 GiB+ 内存 | 远高于功能验证下限 |
| CNI | Cilium 1.16.x | 本次 smoke test 通过,不等于完整兼容性认证 |
| 控制面存储 | Local LVM StorageClass | 仅适合单节点 PoC,不提供跨节点恢复 |
/data/cubelet |
XFS | CubeSandbox 模板与 CoW 数据目录 |
| 现有工作负载 | KubeVirt VMI | 部署前后都检查运行状态 |
这次没有做以下事情:
- 没有给共享测试节点添加
NoSchedule污点; - 没有添加
cube.tencent.com/allow-pvm-bootstrap=true; - 没有安装 PVM 宿主机内核,没有修改 GRUB,也没有重启节点;
- 没有让 Chart 修改集群 CoreDNS;
- 没有把 WebUI、CubeAPI 或管理端点暴露到公网;
- 没有测试高并发、Pause/Resume、Snapshot、跨节点恢复和生产 SLO。
生产环境应该使用专用节点池,并给计算节点加污点。共享节点只是为了回答“能否跑通”,不是推荐架构。
2. 先理解安装会改动什么¶
CubeSandbox 不是只安装几个普通 Deployment。Chart 会同时交付控制面、入口和宿主机级节点运行时:
| 组件 | Kubernetes 形态 | 主要作用 |
|---|---|---|
| CubeMaster、CubeAPI、CubeOps、WebUI | Deployment | 模板、调度、API、运维和管理页面 |
| MySQL、Redis、MinIO | StatefulSet | 元数据、缓存、模板与快照制品 |
| CubeProxy、Lifecycle Manager | Deployment + Service | 沙箱入站代理和生命周期协调 |
cube-node-installer |
DaemonSet | 安装 Cubelet、Shim、Guest、Kernel 等节点产物 |
cube-node-bootstrap |
privileged DaemonSet | 检查 KVM、XFS、bpffs、cgroup 和宿主目录 |
cube-node |
privileged Big Pod | 运行 Cubelet、CubeEgress 与节点侧沙箱运行时 |
节点组件默认需要 privileged、hostPID、hostPath 和 /dev/kvm。这相当于把一套虚拟化运行时接进宿主机,不应在没有隔离边界和供应链控制的情况下安装到通用多租户集群。
3. 节点预检:先证明宿主机符合条件¶
3.1 Kubernetes 与存储¶
先确认当前上下文、节点、StorageClass 和默认卷容量:
kubectl config current-context
kubectl version
kubectl get nodes -o wide
kubectl get storageclass
kubectl get pv
单节点 PoC 最容易忽略的是控制面 PVC 总量。v0.7.0 Chart 的默认值是:
| PVC | 默认容量 |
|---|---|
| CubeMaster | 20 GiB |
| MySQL | 20 GiB |
| Redis | 10 GiB |
| MinIO | 20 GiB |
| 合计 | 70 GiB |
实验节点的 Local LVM 可分配容量只有约 60 GiB。如果直接使用默认值,四个 PVC 不可能全部成功绑定。因此 PoC 把它们缩小为 5 + 10 + 2 + 10 GiB,共 27 GiB。
这只是功能验证规格。生产环境不应照抄 27 GiB,而要根据模板数量、数据库保留、快照后端、日志和恢复目标重新规划。
3.2 KVM、XFS、bpffs 和 cgroup¶
每台计算节点都要核对:
# KVM 设备
ls -l /dev/kvm
# CPU 虚拟化与 KVM 模块
grep -Eoc '(vmx|svm)' /proc/cpuinfo
lsmod | grep -E '^kvm'
# BPF 文件系统
findmnt /sys/fs/bpf
# Cubelet 数据目录
findmnt -T /data/cubelet
df -h /data/cubelet
# cgroup CPU controller
mount | grep cgroup
验收重点不是“命令有输出”,而是:
/dev/kvm能被打开,而不只是文件存在;kvm_intel或kvm_amd已加载;/data/cubelet最终落在 XFS;- bpffs 已挂载;
- cgroup CPU controller 可用;
- 节点内存明显高于 Chart 的最低检查值;
- 宿主机路由没有占用准备分给 CubeSandbox 的 CIDR。
如果节点本身已经是 XFS,可以直接使用 /data/cubelet。如果根盘不是 XFS,PoC 可让 bootstrap 创建 loopback XFS;生产应使用独立数据盘。
3.3 网络 CIDR¶
Chart 默认的沙箱网络是 172.16.0.0/18。安装前至少比对:
# Pod CIDR
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
# Service CIDR 可从 apiserver 参数或集群配置中查询
kubectl -n kube-system get pods -l component=kube-apiserver -o yaml | grep service-cluster-ip-range
# 节点本地路由
ip -4 route
还要人工核对 VPC、对等网络、VPN 和 IDC 路由。Helm 的 Service CIDR 预检不能发现所有外部路由冲突。
本次实验中:
- Pod 网段属于
10.0.0.0/8; - Service 网段为
10.96.0.0/12; - 节点地址位于另一个
10.0.0.0/8子网; 172.16.0.0/18与已知集群地址不重叠。
这只能证明集群内没有直接冲突,不能替代外部网络团队的路由核对。
3.4 镜像可达性¶
CubeSandbox 的控制面镜像、节点产物镜像和后续模板镜像都必须能被目标环境访问。离线或受限网络应先同步到节点可达的 Registry,并固定版本或 Digest。
本文不展开镜像搬运、重打 tag 和私有仓库操作;这些步骤高度依赖企业网络。安装前只需要确保两件事:
- Kubernetes 节点能拉取 Chart 渲染出的所有镜像;
- CubeMaster 的模板构建链也能访问模板镜像仓库,并信任它的 TLS CA。
第二点很容易漏掉:节点 containerd 能拉取私有镜像,不代表 CubeMaster 内部的 OCI 客户端自动继承相同 CA。后文会单独说明。
4. 固定版本并准备 values¶
4.1 获取与检查 Chart¶
git clone https://github.com/TencentCloud/CubeSandbox.git
cd CubeSandbox
git checkout v0.7.0
helm lint deploy/kubernetes/chart \
-f deploy/kubernetes/chart/values-single-node.yaml \
-f runtime-values.yaml
不要直接用 master 部署后再按某个 Release 的文档排障。Chart、镜像、Guest Kernel 和 CLI 应固定到同一个版本。
4.2 单节点 PoC 的关键 values¶
下面是这次实验使用的公开化版本。密码只放在发布时注入的私密 values 中,不要提交到 Git。
cubeProxy:
advertiseIP: "<node-ip>"
domain: "sandbox.example.test"
configureClusterDNS: false
service:
type: NodePort
nodePorts:
http: 30080
https: 30443
grpc: 30090
admin: ""
ingress:
enabled: false
tls:
mode: selfSigned
persistence:
storageClassName: <storage-class>
controlPlane:
master:
persistence:
size: 5Gi
mysql:
password: "<generated-password>"
rootPassword: "<generated-root-password>"
persistence:
size: 10Gi
redis:
password: "<generated-password>"
persistence:
size: 2Gi
minio:
persistence:
size: 10Gi
bootstrap:
pvmHostKernel:
enabled: false
nodeInit:
dataCubelet:
loopback:
enabled: true
imagePath: /data/cubelet-xfs.img
size: 25G
cubeNode:
pvmGuestKernel:
enabled: false
hostNetwork: false
network:
cidr: "172.16.0.0/18"
cidrSkipConflictCheck: false
几个关键选择:
pvmHostKernel.enabled=false:禁止 Chart 安装 PVM 宿主机内核;pvmGuestKernel.enabled=false:使用普通 BM Guest Kernel;configureClusterDNS=false:不修改集群 CoreDNS;hostNetwork=false:保留默认 Pod 网络,适合 PoC;cidrSkipConflictCheck=false:保留网络冲突保护;- 4 个 PVC 合计 27 GiB:适配本次有限的 Local LVM 空间;
selfSigned+ NodePort:只用于受控测试网络。
cubeProxy.service.type=NodePort 有一个容易误判的细节:即使 admin 的 nodePort 留空,Kubernetes 仍会为 Service 中的 admin 端口自动分配一个 NodePort。Token 认证不能代替防火墙,生产环境不要直接对不可信网络开放这个 Service。
4.3 为什么要同时关闭两个 PVM 开关¶
只设置 cubeNode.pvmGuestKernel.enabled=false 不够稳妥。Chart 还有独立的宿主机 PVM 安装路径:
同时不要给原生 KVM 节点添加:
正式安装前,检查最终渲染结果:
helm template cube deploy/kubernetes/chart \
--namespace cube-system \
-f deploy/kubernetes/chart/values-single-node.yaml \
-f runtime-values.yaml \
| grep -E 'PVM_FEATURE_ENABLED|CUBE_PVM_ENABLE|cube-node-pvm'
预期节点初始化中的 PVM 值为 0,且不生成 cube-node-pvm DaemonSet。
5. 安装:先 dry-run,再写入集群¶
5.1 标记节点¶
单节点 profile 要求同一台机器带控制面与计算面标签:
kubectl label node <node-name> \
cube.tencent.com/cube-control=true \
cube.tencent.com/cube-node=true \
--overwrite
共享 PoC 节点没有添加污点,以免驱逐或阻塞已有业务。生产专用计算节点应添加 NoSchedule 污点,并确认 Chart toleration 与平台策略一致。
5.2 服务端 dry-run¶
本地 helm lint 和 helm template 只能验证模板。支持 server dry-run 的 Helm 版本可以继续执行:
helm upgrade --install cube deploy/kubernetes/chart \
--namespace cube-system \
--create-namespace \
-f deploy/kubernetes/chart/values-single-node.yaml \
-f runtime-values.yaml \
--dry-run=server \
--hide-secret >/dev/null
这一步可以提前发现 API 版本、准入策略、CRD 和部分集群端约束问题,同时避免把 Secret 输出到终端。
5.3 正式安装¶
helm upgrade --install cube deploy/kubernetes/chart \
--namespace cube-system \
--create-namespace \
-f deploy/kubernetes/chart/values-single-node.yaml \
-f runtime-values.yaml \
--wait \
--wait-for-jobs \
--timeout 90m
安装过程中另开终端观察:
正常情况下会依次看到:
- MySQL、Redis、MinIO 和 PVC 就绪;
- CubeMaster、CubeOps、CubeAPI、WebUI、CubeProxy 启动;
cube-node-installer安装节点运行时产物;cube-node-bootstrap检查 KVM、XFS、bpffs、CIDR 和 CubeMaster 连通性;cube-nodeBig Pod 启动并向 CubeOps 注册。
6. 一次真实的启动竞态:什么时候等,什么时候查¶
这次安装在前一分钟出现过以下现象:
- CubeMaster 首次启动时解析不到 MySQL Service;
- CubeOps 和 Lifecycle Manager 因 CubeMaster 尚未 Ready 而重启;
cube-node-bootstrap已通过 KVM、XFS、bpffs 和 CIDR 检查,但最后连不上 CubeMaster;cube-node因等待 node prep 而停在 Init 阶段。
随后 MySQL 和 Service DNS 就绪,CubeMaster 在下一轮重试中启动成功,bootstrap 重新执行后通过,所有组件进入 Ready。
这类现象可以短暂观察,但不能只用“再等等”处理。建议按以下顺序确认:
kubectl get pods,svc,endpoints,pvc -n cube-system -o wide
kubectl logs -n cube-system \
-l app.kubernetes.io/component=cube-node-bootstrap \
-c cube-node-init --tail=200
kubectl logs -n cube-system deploy/cube-master \
-c cube-master --tail=200
kubectl get events -n cube-system --sort-by=.lastTimestamp | tail -50
判断标准:
- 如果依赖 Service 和 Endpoint 已出现,重试次数停止增长,所有 Pod 最终 Ready,可以归类为启动时序;
- 如果持续出现 DNS
NXDOMAIN、PVC Pending、KVM/XFS 检查失败或 ImagePullBackOff,就必须修复根因; - 不要为了让 bootstrap 变绿而关闭 CIDR、KVM、XFS 或内存检查。
排障日志可能包含数据库 URL、密码或管理 Token。公开文章和工单中应先脱敏,生产环境出现泄漏后要轮换凭据。
7. 验收:Pod Ready 之后还要做四层检查¶
7.1 Kubernetes 资源¶
helm status cube -n cube-system
kubectl get deploy,statefulset,daemonset -n cube-system
kubectl get pvc -n cube-system
本次结果:
| 资源 | 结果 |
|---|---|
| Deployment | 7/7 Ready |
| StatefulSet | 3/3 Ready |
| DaemonSet | 3/3 Ready |
| PVC | 4/4 Bound |
7.2 节点注册¶
kubectl exec -n cube-system deploy/cube-cubemastercli -- \
sh -lc 'cubeopscli \
--address "$CUBEOPSCLI_ADDRESS" \
--port "$CUBEOPSCLI_PORT" \
node list'
至少确认:
HEALTHY=true;HOST_STATUS=RUNNING;SCHEDULING_DISABLED=false;- 组件版本都与目标 Release 一致;
- Kernel variant 为
bm,而不是 PVM; - CPU、内存和磁盘指标不是 0。
7.3 官方 Helm tests¶
v0.7.0 实际运行了 8 组测试:
| Test Suite | 验证内容 |
|---|---|
cube-health-test |
CubeMaster、CubeOps、CubeAPI、WebUI、Proxy、Node 健康 |
cube-cubemastercli-test |
CLI 能访问 CubeMaster 和沙箱列表 |
cube-cubeopscli-test |
CLI 能访问 CubeOps 和节点列表 |
cube-mysql-test |
MySQL 存活 |
cube-redis-test |
Redis PONG |
cube-proxy-control-test |
Proxy ClusterIP 控制路径 |
cube-node-image-test |
节点镜像与产物 |
cube-node-runtime-test |
宿主运行时资产 |
本次 8 组全部 Succeeded。
7.4 与现有 KVM 工作负载共存¶
如果测试节点已有 KubeVirt、libvirt 或其它 KVM 消费者,安装后必须重新检查:
本次节点上原有 4 个 KubeVirt VMI 在安装后都保持 Running/Ready,节点也没有新增污点。这只能说明一次低并发 PoC 没有立即冲突,不能证明两套虚拟化平台在资源压力、升级和故障场景下长期兼容。
8. 构建第一个模板¶
CubeSandbox 不能直接把任意 OCI 镜像当成运行中的沙箱。它要先把镜像转换成模板:拉取镜像、解包 rootfs、启动临时 MicroVM、等待 HTTP 探针、制作快照,再把制品分发到计算节点。
使用官方 sandbox-code 镜像:
kubectl exec -n cube-system deploy/cube-cubemastercli -- \
sh -lc 'cubemastercli \
--address "$CUBEMASTERCLI_ADDRESS" \
--port "$CUBEMASTERCLI_PORT" \
tpl create-from-image \
--image <registry>/cube-sandbox/sandbox-code@sha256:<digest> \
--alias k8s-smoke \
--writable-layer-size 1G \
--expose-port 49999 \
--expose-port 49983 \
--probe 49999 \
--probe-path /health \
--node <compute-node>'
私有仓库可使用 --registry-username 和 --registry-password,但不要把密码直接写进 shell history。更稳妥的方式是由 Secret、短期凭据或受控流水线注入。
8.1 私有 Registry CA 的隐藏问题¶
本次第一次模板构建失败在 PULLING:节点 containerd 已能拉取同一仓库,CubeMaster 的原生 OCI 导出流程却报 x509: certificate signed by unknown authority。
原因是两条拉取链路不同:
Kubernetes Pod 镜像
→ kubelet / containerd
→ 节点上的 registry 配置与 CA
CubeSandbox 模板镜像
→ CubeMaster / Cubelet 的 OCI 客户端
→ 容器自己的 CA 信任链
生产解决方案应该是:
- 给 Registry 使用受信任的 HTTPS 证书;或
- 把企业 CA 以 ConfigMap/Secret 或定制镜像方式注入 CubeMaster 与相关模板构建组件;
- 固定镜像 Digest,避免
latest漂移; - 在安装验收里单独测试模板镜像拉取。
不要把关闭 TLS 校验当成长期方案,也不要因为 Kubernetes Pod 能拉取镜像就跳过模板构建测试。
8.2 观察模板状态¶
kubectl exec -n cube-system deploy/cube-cubemastercli -- \
sh -lc 'cubemastercli \
--address "$CUBEMASTERCLI_ADDRESS" \
--port "$CUBEMASTERCLI_PORT" \
tpl list -o wide'
一次成功构建会依次经过:
本次模板最终在唯一计算节点上达到 1/1 ready。
9. 最小业务闭环:Create → Exec → Destroy¶
官方 Helm tests 已经覆盖大量组件健康,但仍要创建一个真实沙箱。
9.1 临时转发 CubeAPI¶
9.2 创建沙箱¶
response="$(curl -sS --fail-with-body \
-X POST http://127.0.0.1:13000/sandboxes \
-H 'Content-Type: application/json' \
-H 'X-API-Key: e2b_000000' \
-d '{
"templateID": "<template-id>",
"timeout": 300,
"autoPause": false
}')"
sandbox_id="$(printf '%s' "$response" | jq -r '.sandboxID')"
printf 'sandbox_id=%s\n' "$sandbox_id"
测试环境中的 CubeAPI 没有额外启用 API Key 校验,但 SDK 和示例客户端仍要求一个非空占位值。生产环境必须接入正式鉴权,不能把这个占位值理解成安全凭据。
9.3 在沙箱中执行命令¶
kubectl exec -n cube-system daemonset/cube-node -c cubelet -- \
cubecli exec "$sandbox_id" sh -lc '
echo cube-smoke-ok
uname -m
uname -r
findmnt -n -o FSTYPE /
'
本次真实输出证明了:
- 沙箱状态为
running; - Guest 架构是
x86_64; - Guest Kernel 与宿主机内核不同;
- rootfs 使用 overlay;
- 命令在隔离环境中成功执行。
9.4 销毁并确认无残留¶
curl -sS --fail-with-body \
-X DELETE "http://127.0.0.1:13000/sandboxes/${sandbox_id}" \
-H 'X-API-Key: e2b_000000'
kubectl exec -n cube-system deploy/cube-cubemastercli -- \
sh -lc 'cubemastercli \
--address "$CUBEMASTERCLI_ADDRESS" \
--port "$CUBEMASTERCLI_PORT" \
cubebox list'
验收结束时 SANDBOX_COUNT 应恢复为 0。自动化脚本应使用 trap 或 finally,确保中途失败也能清理测试沙箱。
10. WebUI:部署后最直观的入口¶
WebUI Service 默认是 ClusterIP。测试环境可以只监听本机回环地址:
浏览器打开:
v0.7.0 首次登录的默认测试账号是 admin / admin。登录后应立即在 Settings 中修改密码。不要把 WebUI 或 CubeOps :3010 直接暴露到公网。
页面中最值得先看的位置:
| 页面 | 能回答的问题 |
|---|---|
| Overview | 当前沙箱数量、资源压力和健康节点数 |
| Nodes | 节点是否 Ready、版本是否一致、是否被隔离 |
| Templates | 模板是否 READY、构建任务在哪个阶段失败 |
| Sandboxes | 沙箱状态、模板、节点与生命周期操作 |
| Versions | Cubelet、Shim、Guest、Kernel、Agent 是否同版 |
| Network | 入口与网络相关配置 |
| Observability | 运行时、模板构建和沙箱健康概览 |
| API Keys | SDK 凭据管理 |
11. 部署完成后,有什么可玩、可测试的¶
把测试分成四级,能避免一开始就上高并发,把基础问题和性能问题混在一起。
11.1 Level 1:功能冒烟¶
目标是证明一条完整路径可用:
- WebUI 登录;
- 节点为
HEALTHY/RUNNING; - 构建一个
sandbox-code模板; - 创建一个沙箱;
- 执行 shell 和 Python;
- 读写临时文件;
- 销毁沙箱并确认数量回到 0。
可以使用 E2B 兼容 SDK:
python -m venv .venv
source .venv/bin/activate
pip install e2b-code-interpreter
export E2B_API_URL=http://127.0.0.1:13000
export E2B_API_KEY=e2b_000000
export CUBE_TEMPLATE_ID=<template-id>
import os
from e2b_code_interpreter import Sandbox
with Sandbox.create(template=os.environ["CUBE_TEMPLATE_ID"]) as sandbox:
result = sandbox.run_code("print(sum(i * i for i in range(10)))")
print(result)
11.2 Level 2:模板与生命周期¶
值得玩的能力:
- 从不同 OCI 镜像构建模板;
- 给模板覆盖 command、args、env 和 probe;
- Pause / Resume;
- 创建 Snapshot;
- 从 Snapshot 创建新沙箱;
- Rollback 与 Clone;
- 模板 alias 与版本升级;
- 模板在多计算节点之间重新分发。
测试时记录:
- Create-to-Running;
- Pause、Resume、Snapshot、Rollback 各阶段耗时;
- 内存状态和文件状态是否按预期保留;
- 模板或 Guest 版本升级后,旧 Snapshot 是否兼容;
- 生命周期失败后是否有 orphan runtime、tap、volume 或元数据。
11.3 Level 3:网络与安全¶
至少验证四条路径:
| 测试 | 期望结果 |
|---|---|
| 沙箱访问公网 | 受 allow_internet_access 控制 |
| 沙箱访问集群/内网 | 默认策略符合预期,不误放行敏感网段 |
| 外部访问沙箱端口 | 通配域名、TLS、HTTP/gRPC Proxy 正常 |
| 动态更新网络策略 | 规则是替换还是合并,行为与文档一致 |
进一步可以测试:
- DNS 继承、搜索域和
ndots; allowOut、denyOut和规则优先级;allow_public_traffic=false与访问 Token;- CubeEgress 代理、审计和凭据注入;
- Cilium/Calico 与 CubeVS eBPF Hook 的共存;
- MTU、NAT、长连接、WebSocket 和 gRPC。
不要在仍能访问生产内网的测试节点上做不受控 Agent 红队实验。网络默认拒绝必须用抓包和目标服务日志验证,不能只看 API 返回成功。
11.4 Level 4:存储、性能与故障¶
存储方面可以测试:
- MinIO/S3 持久卷;
- 销毁沙箱后重新挂载同一卷;
- 多租户卷隔离;
- XFS reflink 与 project quota;
- 数据盘逼近 80% 时的调度和告警;
- Snapshot 后端故障与恢复。
性能方面不要只测平均值:
- 单并发冷启动与热启动;
- 1、10、50、100 并发创建;
- P50、P95、P99 和最大值;
- Create API、调度、Cubelet、Guest probe 分阶段耗时;
- 不同模板大小和 writable layer 大小;
- 每节点沙箱密度、宿主内存开销和 CPU overcommit;
- 大量销毁后的存储与网络资源回收。
故障方面可以测试:
- 隔离/解除隔离计算节点;
- CubeMaster、Redis、MySQL、MinIO 短暂不可用;
- DNS 故障;
- Registry 不可达或 CA 过期;
/data/cubelet空间不足;cube-nodePod 重建;- 节点重启与 Kubernetes 升级;
- 控制面升级与计算面版本漂移。
注意:当 cubeNode.hostNetwork=false 时,重建 cube-node 会更换 Pod Network Namespace,存量沙箱网络可能中断。不要在有重要沙箱运行时随意删除这个 Pod。
12. 本次已经证明什么,还没有证明什么¶
| 验证项 | 状态 | 结论边界 |
|---|---|---|
| Helm 安装与资源 Ready | 已通过 | 仅一个单节点 profile |
| Local LVM PVC | 已通过 | 不具备跨节点高可用 |
| 原生 KVM 与 BM Guest | 已通过 | 没有测试 PVM |
| Cilium 基础共存 | 已通过 | 只覆盖模板与单沙箱 smoke,不是完整 CNI 认证 |
| 8 组官方 Helm tests | 已通过 | 证明组件和节点运行时健康 |
| 模板构建 | 已通过 | 单节点、单一官方镜像 |
| 沙箱 Create / Exec / Destroy | 已通过 | 单并发,无性能结论 |
| 与已有 KubeVirt VMI 共存 | 已观察通过 | 没有资源压力、升级和故障注入 |
| Pause / Resume / Snapshot | 未测试 | 需要单独验证状态与兼容性 |
| S3 持久卷 | 未测试 | MinIO 健康不等于业务卷闭环 |
| 入站域名与公网 TLS | 未测试 | 实验只使用本机 port-forward |
| 高并发和密度 | 未测试 | 不能引用官方 60ms 当本集群 SLO |
| 升级与灾难恢复 | 未测试 | 生产上线前必须补齐 |
13. 清理与回滚¶
卸载前先确认没有沙箱和仍需保留的模板、Snapshot、Volume:
kubectl exec -n cube-system deploy/cube-cubemastercli -- \
sh -lc 'cubemastercli \
--address "$CUBEMASTERCLI_ADDRESS" \
--port "$CUBEMASTERCLI_PORT" \
cubebox list'
再卸载 release:
移除节点标签:
卸载后还要人工检查:
- PVC/PV 是否因 StorageClass reclaim policy 被删除;
/data/cubelet、toolbox、日志和 loopback 文件是否保留;- bpffs、挂载点和 udev/fstab 是否被修改;
- NodePort、ClusterRole、ClusterRoleBinding 是否清理;
- 私有 Registry 凭据和临时 CA 是否撤销。
不要直接递归删除 /data/cubelet。先确认没有其它 release、模板、Snapshot 或仍在运行的 runtime 使用该路径,再按官方清理流程处理。
14. 下一步怎么走¶
如果目标只是验证 Agent 代码能否在 MicroVM 中运行,这篇文章的 Create → Exec → Destroy 已经完成最小闭环。
如果准备进入团队试用,建议下一阶段按这个顺序推进:
- 建设专用计算节点池,添加污点和准入策略;
- 给
/data/cubelet准备独立 XFS 数据盘; - 使用可信 HTTPS Registry、固定 Digest 和镜像签名;
- 接入正式鉴权、生产 TLS、Wildcard DNS 和受控入口;
- 决定
cubeNode.hostNetwork,并完成 NetworkPolicy/Egress 设计; - 验证 Pause/Resume、Snapshot、S3 Volume 和恢复;
- 做并发、密度、资源回收和故障注入;
- 最后才定义本环境的启动时延与可用性 SLO。