Skip to content

docs: add bilingual cross-node Pause/Resume/Snapshot guide - #1506

Open
ls-ggg wants to merge 5 commits into
TencentCloud:masterfrom
ls-ggg:coolli/docs-cross-node-snapshot
Open

docs: add bilingual cross-node Pause/Resume/Snapshot guide#1506
ls-ggg wants to merge 5 commits into
TencentCloud:masterfrom
ls-ggg:coolli/docs-cross-node-snapshot

Conversation

@ls-ggg

@ls-ggg ls-ggg commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add English and Chinese operator guides for cross-node Pause / Resume / FromSnap on the S3 CoW backend (docs/guide/cross-node-snapshot.md, docs/zh/guide/cross-node-snapshot.md).
  • Cover origin-first scheduling, CanCrossNode (backend=s3 and remote_status=ready), host-fact matching (cpuid_hash + host_kernel_release), CLI columns, and current limitations.
  • Wire the pages into the VitePress sidebar and add see-also links from snapshot, lifecycle, template, and architecture docs.

CLI examples match current master: cubemastercli tpl create-from-image --backend s3 and cubeopscli node list --json for HostFacts. Benchmark tables are placeholders.

Test plan

  • Confirm both pages render in VitePress (EN + ZH sidebars under Core Concepts).
  • Spot-check CLI examples against cubemastercli tpl create-from-image --help and cubeopscli node list --help.
  • Follow the see-also links from snapshot / lifecycle / template / architecture pages.

Assisted-by: Cursor:Composer
Signed-off-by: ls-ggg 335814617@qq.com

Document S3 backend, remote_status=ready, origin-first scheduling, and
host-fact matching so operators can restore pause packages and snapshots
on another node.

Assisted-by: Cursor:Composer
Signed-off-by: ls-ggg <335814617@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

The target node's kernel and CPU identity must match the origin. Memory state (including CPU registers and feature bits) cannot restore correctly otherwise.

> **Current match policy:** cross-node compatibility currently requires **equality on `cpuid_hash` and `host_kernel_release` only**. Other fields (`cpu_vendor`, `host_kernel_fingerprint`, `kvm_api_version`) are collected and shown but **are not equality gates**. A target with a non-empty `kvm_module_taint` (forced / out-of-tree / unsigned `kvm.ko`) is rejected. Later releases may tighten this; follow the version you run.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kvm_module_taint claim here doesn't match the cross-node scheduling path. In the code, the taint gate is enforced only by the diagnostic restore-compat endpoints (EvaluateSnapshotRestoreCompat / ListCompatibleNodesForSnapshot / ListCompatibleNodesForFactors in CubeMaster/pkg/templatecenter/restore_compat.go, kvmModuleTaintDimension). The actual cross-node scheduler — restoreplace.Decide (CubeMaster/pkg/restoreplace/placement.go:274) → nodemeta.QueryHostFactCandidatesfilterHostFactCandidates (CubeMaster/pkg/nodemeta/service.go:190) — filters candidates only on cpuid_hash + host_kernel_release equality and never consults kvm_module_taint. Both Resume (resumePlacement) and FromSnap (fromSnapshotPlacement) route through restoreplace.Decide. So a cross-node restore can land on a node with a tainted kvm.ko provided the two equality keys match. Consider scoping this to the compatible-nodes check, or (if the code comment's "hard restore blocker" intent is to hold) filing the scheduler gap separately. Same applies to the ZH page.

cubemastercli cubebox list --all
```

Non-paused rows sort by create time descending; paused rows come last and include `pause_snap`. After a successful Resume those columns return to `-`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: "those columns return to -" only holds for remote and pause_snap. The backend column is filled from the sandbox's persisted spec (enrichSandboxListBackends, CubeMaster/pkg/service/sandbox/sandbox_list.go:249), so an S3-backed sandbox keeps showing s3 after a successful Resume — it does not return to -. Consider rewording to "the remote and pause_snap columns return to -".

> **当前匹配范围**:跨机兼容性判定**目前仅以 `cpuid_hash` 与 `host_kernel_release` 两个维度做相等匹配**。
> 其余字段(`cpu_vendor`、`host_kernel_fingerprint`、`kvm_api_version`)目前只是采集并展示、
> **尚未纳入相等匹配门禁**。目标节点若带非空的 `kvm_module_taint`(强制 / 树外 / 未签名的 `kvm.ko`),
> 会被拒绝作为跨机目标。后续版本可能收紧匹配维度,请以实际版本为准。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

与英文版同一处:跨机调度路径(restoreplace.Decidenodemeta.QueryHostFactCandidates/filterHostFactCandidates)只按 cpuid_hashhost_kernel_release 相等匹配,并不读取 kvm_module_taint。taint 门禁只在兼容性诊断接口(restore_compat.goEvaluateSnapshotRestoreCompat / ListCompatibleNodesForSnapshot / ListCompatibleNodesForFactors)中生效。建议将该表述限定到「兼容性检查」范围,或另行修复调度器。

@cubesandboxbot

cubesandboxbot Bot commented Aug 25, 2026

Copy link
Copy Markdown

Review: docs: add bilingual cross-node Pause/Resume/Snapshot guide

Scope: Docs-only PR (586 additions, 2 deletions). Adds EN/ZH docs/guide/cross-node-snapshot.md, wires both into the VitePress sidebar under Core Concepts, and adds see-also links from the lifecycle, snapshot-rollback-clone, templates, template-from-image, and architecture pages.

Overall: Technically accurate. I verified the substantive claims against the base tree (master @ c5df275, which includes the CubeS3lvol backend from #1490): CanCrossNode semantics, origin-first scheduling, PinToOrigin for host-mount, the cpuid_hash/host_kernel_release equality gates, cpuid_hash computation, CLI flags/columns, the remote_status state machine, and the S3lvol paths are all correct. The issues below are mostly about consistency between the PR description and the docs, plus one accuracy nuance in how the kvm_module_taint gate is described.

Findings

1. HIGH — Benchmark tables presented as measured data, while the PR description calls them placeholders

The PR body explicitly states "Benchmark tables are placeholders," but the new docs present concrete numbers (e.g. cold-start s3 p95 471.4ms, cross-node FromSnap p95 7322.8ms) "measured on 2026-08-25" with a full environment/template/method section. These two statements cannot both be true. If the tables are placeholders, they must be clearly marked as illustrative (or removed) before merge; if they are real measurements, the PR description should be updated. (Also posted inline: EN docs/guide/cross-node-snapshot.md:195, ZH docs/zh/guide/cross-node-snapshot.md:232.)

2. MEDIUM — kvm_module_taint "rejected" overstates what the scheduler enforces

The docs claim a target with a non-empty kvm_module_taint is rejected for cross-node restore. In the current code, the placement decision (restoreplace.DecidedefaultListCompatiblenodemeta.QueryHostFactCandidates) enforces equality only on cpuid_hash + host_kernel_release; the taint gate exists solely in the diagnostic restore-compat evaluation (CubeMaster/pkg/templatecenter/restore_compat.go, kvmModuleTaintDimension), which the scheduler does not consult. The "Current match policy" paragraph and the kvm_module_taint table row should clarify that the taint rejection is reported by the diagnostic check, not enforced by placement today. (Posted inline: docs/guide/cross-node-snapshot.md:90.)

3. MINOR — "No extra feature flag" conflicts with ONE_CLICK_ENABLE_S3LVOL

The docs say the S3 path is "on by default" with "no extra feature flag," but the one-click installer exposes ONE_CLICK_ENABLE_S3LVOL (default 0, see deploy/one-click/env.example and deploy/one-click/install.sh:1555) that turns the cube-sandbox-s3lvol systemd unit on. For one-click installs, S3lvol is therefore not on by default — operators must set the flag. The claim may be true of the CubeMaster/Cubelet code path once the service is running, but the sentence as written will mislead installer users. (Posted inline: docs/guide/cross-node-snapshot.md:118.)

4. MINOR — State machine omits the transient running state

The docs describe pending → inprogress → ready / failed. The code also has a transient running state (RemoteStatusRunning in CubeMaster/pkg/base/constants/snapshot_backend.go). Fine as a simplification, but worth noting the omitted state so operators are not surprised to see running in DB/CLI output.

Verified as accurate

  • CanCrossNode(backend, remote_status) is true only when backend==s3 and remote_status==ready (case-insensitive, whitespace-trimmed) — matches restoreplace.CanCrossNode (CubeMaster/pkg/restoreplace/placement.go:78).
  • Origin-first scheduling: restoreplace.Decide returns the origin whenever it is healthy, schedulable, and in scope; cross-node runs only when the origin cannot schedule and CanCrossNode holds.
  • Host-mount sandboxes are pinned via PinToOrigin and do not cross even when remote_status=ready — matches crossNodeBlockedReason.
  • Cross-node candidates match the origin on cpuid_hash + host_kernel_release only — matches nodemeta.QueryHostFactCandidates.
  • cpuid_hash computation (deterministic SHA-256, prefix sha256:, first logical CPU only, flags/Features sorted, x86/ARM key lists) — matches Cubelet/pkg/cubelet/versioninfo/hostfacts.go.
  • CLI claims: tpl create-from-image --backend s3 flag exists; cubebox template list prints a BACKEND column; cubebox list shows backend/remote columns plus pause_snap; cubebox snapshot list/info show origin_node_id, backend/remote_status, and a per-node replicas table; cubeopscli node list --json emits HostFacts; CubeOps default port 3010.
  • cubebox list sort: non-paused rows newest-CreateAt-first, paused rows last; after a successful resume the pause_snap/remote columns return to - — matches SortSandboxList (CubeMaster/pkg/service/sandbox/types/sandbox_list_sort.go) and the pause_snap column in cubebox list.
  • S3lvol paths /data/cubelet/cos.cfg and /data/cubelet/rcow/wal_bdev.img — match CubeS3lvol/README.md.
  • VitePress anchors: the double-dash anchors (e.g. #跨机目标必须与源机-kernel--cpu-信息一致, and the existing #控制面--数据库 in docs/zh/guide/kubernetes/faq.md) are consistent with VitePress 1.6.4 slugify (each whitespace char → -, no collapse, / stripped), so the in-page links should resolve.
  • Sidebar wiring in docs/.vitepress/config.mjs is consistent between EN and ZH and lands under Core Concepts; the see-also links added across the other doc pages point at files that exist.

Notes

  • This review is AI-generated and has not been reviewed by a human maintainer.
  • The diff was not truncated (no review-input/TRUNCATED marker present).

ls-ggg and others added 4 commits August 25, 2026 17:28
Record 2026-08-25 per-instance avg/p95, template spec, and host SKU.
Rounds stay "start N then kill all" so later re-runs keep the same tables.

Assisted-by: Cursor:Composer
Signed-off-by: ls-ggg <335814617@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted-by: Cursor:Composer
Signed-off-by: ls-ggg <335814617@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted-by: Cursor:Composer
Signed-off-by: ls-ggg <335814617@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted-by: Cursor:Composer
Signed-off-by: ls-ggg <335814617@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

Times are **milliseconds**. **avg** / **p95** are **per-sandbox** create latency (when that sandbox became `running`), not batch wall time divided by concurrency.

Figures below were measured on 2026-08-25. Numbers depend on hardware, image, and dirty-page load; treat them as a same-cluster xfs vs s3 comparison, not a SLA.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says "Benchmark tables are placeholders", but this section presents concrete numbers as measured on 2026-08-25 with a detailed environment/method. This is contradictory as written. If the tables are placeholders, mark them clearly as illustrative/placeholder (or drop them) before merge; if they are real measurements, update the PR description instead. As-is, readers will treat these numbers as measured results.


The target node's kernel and CPU identity must match the origin. Memory state (including CPU registers and feature bits) cannot restore correctly otherwise.

> **Current match policy:** cross-node compatibility currently requires **equality on `cpuid_hash` and `host_kernel_release` only**. Other fields (`cpu_vendor`, `host_kernel_fingerprint`, `kvm_api_version`) are collected and shown but **are not equality gates**. A target with a non-empty `kvm_module_taint` (forced / out-of-tree / unsigned `kvm.ko`) is rejected. Later releases may tighten this; follow the version you run.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This states a target with non-empty kvm_module_taint is "rejected" for cross-node restore, but the current scheduler path does not enforce that. restoreplace.DecidedefaultListCompatiblenodemeta.QueryHostFactCandidates gates on equality of cpuid_hash and host_kernel_release only; the kvm_module_taint gate exists solely in the diagnostic restore-compat evaluation (CubeMaster/pkg/templatecenter/restore_compat.go, kvmModuleTaintDimension), which is not what the scheduler consults. Consider clarifying that the taint rejection is currently only reported by the diagnostic check, not enforced by placement — or note it as a planned gate.


## Configuring the S3 backend

The S3 path in CubeSandbox is **on by default**. You need a ready **S3lvol** service; there is no extra feature flag.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"No extra feature flag" is imprecise for one-click installs: deploy/one-click/env.example exposes ONE_CLICK_ENABLE_S3LVOL (default 0, see deploy/one-click/install.sh:1555), which turns the cube-sandbox-s3lvol systemd unit on. So S3lvol is not on by default when using the one-click installer — operators must set that flag. The "on by default" claim may be true of the CubeMaster/Cubelet code path once the service is up, but the sentence as written will mislead installer users. Suggest mentioning the flag.


单位 **ms**。表中 **avg** / **p95** 是**单实例**从发起到进入 `running` 的耗时,不是整批 wall 再除以并发。

下列数字测于 2026-08-25。结果随硬件、镜像和脏页负载变化,只适合作为同集群上 xfs 与 s3 的对照,不是 SLA。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 描述里写的是 "Benchmark tables are placeholders",但本节以「测于 2026-08-25」的形式给出了具体数字和详细的测试方法,两者矛盾。若这些表格是占位数据,请在合入前明确标注为示例/占位(或删除);若确为实测数据,请同步更新 PR 描述。否则读者会把这些数字当作实测结果。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant