Skip to content

Component multi-version

A node keeps several versions of each component on disk at the same time. When creating or restoring a sandbox, the version bound to the template is used; if it is not on the node, a copy is pulled from the CubeOps warehouse. This way, after a node upgrades its components to a new version, sandboxes built with the old version still restore and old templates still schedule — the upgrade does not affect them.

The four components:

ComponentWhat it is
cube-shimContainer runtime shim and cube-runtime
cube-imageGuest root filesystem image
cube-agentThe agent inside the guest
cube-kernel-scfGuest kernel

Background: why multi-version

Previously a node had only one copy of each component (the current toolbox). When the upgrader bumped it, the version changed. The trouble is that a template is built against a specific version. Say the node bumps cube-image from v1 to v2:

  • A sandbox built with v1, on restore, can only pick up v2 — the version does not match, restore fails outright.
  • An old template replica built on v1 is flagged incompatible (STALE) and cannot be scheduled.
  • To recover, the old template has to be rebuilt and the node re-provisioned with components. New and old templates could not coexist on one node.

With multi-version: every version is kept. v1 is still on the node, so an old sandbox restores against v1 and an old template still schedules — upgrading to v2 does not affect it at all. New and old templates coexist on one node; upgrades are no longer disruptive.

How it runs

When creating or restoring a sandbox, the flow is:

There are two places on the node disk:

/usr/local/services/cubetoolbox            ← current toolbox: updated in place by the upgrader, what the node uses now
/data/cubelet/root/component_versions/     ← versioned inventory: versions side by side, read at create/restore
├── cube-image/
│   ├── v1.0/
│   └── v1.2/
└── cube-kernel-scf/
    └── v1.2/

In one line: a missing version is never papered over with the current toolbox — it is fetched from the warehouse. So the current toolbox can be upgraded freely, and replicas already bound to an old version are unaffected — this is stable restore. New templates bind all four components; only history replicas migrated from an older version may have bound only two, and they do not get stable restore.

What operators do

1. Import versions into the warehouse (so nodes have something to download)

On the warehouse home page, click “Import one-click package.” Only cube-sandbox-one-click-<tag>-{amd64,arm64}.tar.gz is accepted, imported per package — one package writes several components at once; there is no “import only one.” Three sources: GitHub Release (defaults to allowing only TencentCloud/CubeSandbox), CNB Release (CubeSandbox/CubeSandbox), local tar.gz upload (max 8 GB). After submitting you do not have to watch it — go to the “Jobs” page for progress.

2. Stage large versions onto nodes ahead of time (don’t let the first create stall on download)

On a component’s detail page, click “Preinstall”, tick the nodes that don’t have it, and it downloads in the background. Preinstall does not create a sandbox — it only stages the version onto the node. cube-image and the kernel are large (GB-scale); downloading on first create will most likely exceed the 10-minute timeout — stage them first and it is fine.

3. Read coverage, clean up old versions (manage disk)

Each card on the warehouse home has a “coverage” line: green = everything covered, yellow = N nodes missing, grey “coverage unavailable” = CubeOps cannot list nodes. The inventory is not cleaned up automatically; old versions accumulate. Before deleting, check the “bound version” column of the compat matrix and confirm no replica still binds that version. Deleting a version in the console removes only the central copy in the warehouse — the node-local copy is not removed.

Troubleshooting

ErrorWhat it meansWhat to do
component version missing on nodecubeops_addr is not set and the node lacks the versionSet cubeops_addr on the node and open access to CubeOps :3010
component version not in warehouseAddress is set but the warehouse has no such versionImport the matching one-click package in the console
Download failed (network error / 5xx / validation failed)Warehouse has it but download or extract failedCheck the Cubelet logs mod=warehouse; retry or re-import
Coverage shows “unavailable”CubeOps cannot list nodesCheck CubeOps node management / Redis and the node-agent heartbeat
Import job failedThe jobs page shows the reason: out of allow-list, missing token, source unreachable, bad package formatFix per the message

Deployment

“Fetch on miss” depends on two network paths:

  • Node → CubeOps: ask for the download URL and report the local version inventory. If this path is down, the node falls back to “only versions already on the node” — a miss fails outright.
  • Node → object storage: where the data actually comes from. Component packages live in a dedicated cube-ops bucket.

All three deployments configure the CubeOps address for nodes automatically (override with CUBE_OPS_ADDR); what differs is the object-storage side:

DeploymentWorks out of the boxObject storage
HelmThe chart's bundled MinIO by default. To use your own S3/COS, set cubeOps.s3 and make sure nodes can reach that address.
One-click installReuses the volume MinIO/S3 connection automatically, in a dedicated cube-ops bucket. Nothing to configure.
Terraform TKEThe default stack ships no object storage, so the warehouse is disabled. Wire COS (or another S3) into cube-ops to enable it — the address must be reachable from the compute CVMs, which sit outside the cluster.

Warehouse data lives in S3, not on a CubeOps local disk, so CubeOps can run multiple replicas. The availability ceiling is the chart's bundled MinIO — a single instance; for HA, use external S3/COS.

Configuration

SettingDefaultNotes
cubeops_addr (Cubelet)emptyCubeOps address, e.g. http://<ops>:3010. Empty = no download; a missing version fails outright.
cubeops_timeout (Cubelet)10mTotal time budget for pulling one version; leave headroom for GB-scale components.
CUBE_OPS_S3_ENDPOINT (CubeOps)emptyObject-storage address. Empty = warehouse disabled; CubeOps itself still runs.
CUBE_OPS_S3_NODE_ENDPOINT (CubeOps)same as endpointThe address nodes download from; set it only when nodes cannot reach the default one (e.g. they sit outside the cluster).
CUBE_OPS_S3_BUCKET (CubeOps)cube-opsDedicated bucket for warehouse blobs.
CUBE_OPS_WAREHOUSE_WORK_DIR (CubeOps)/var/tmp/cubeops-warehouseLocal scratch space for unpacking imports; give it room for the largest package.
CUBE_OPS_WAREHOUSE_GITHUB_REPOS / CNB_REPOSsee allow-lists aboveImport allow-lists, comma-separated, overridable.
CUBE_OPS_WAREHOUSE_*_TOKENemptyOnly needed for private releases.

Two things to know about the cube-ops bucket:

  • Permissions: give CubeOps read/write access to the bucket, including multipart uploads. The minimum IAM action list is in the CubeOps README.
  • Credentials: nodes hold no S3 credentials (unlike s3fs volumes) — they only get a short-lived signed download URL. That also means anyone who can write the bucket can change the binaries nodes execute; treat the AK/SK as a trust boundary.

/internal/warehouse/* called by nodes carries no JWT (identified only by X-Cube-Node-ID, same treatment as /internal/meta) — expose it only to the compute-node network, never to the public. Admin APIs go through /opsapi and carry JWT.