Files
rustfs/docs/superpowers/plans/rebalance-decommission-phase3-hardening-plan.md
T
Zhengchao An d1db9a10cd chore(docs): refresh agent docs, guard doc paths, archive plans (#4203)
Agent-instruction and architecture docs had drifted from the code:

- CLAUDE.md: slim to commands + pointers; fix wrong claim that
  `make pre-commit` is the full pre-PR gate (that is `make pre-pr`);
  drop stale pre-#3929 file paths and merged bug narratives
- AGENTS.md: drop dead `rust-refactor-helper` skill rule and the
  hand-maintained (already stale) scoped-AGENTS index; link
  architecture docs from Sources of Truth
- .github/AGENTS.md: replace the outdated copied CI command matrix
  with a pointer to ci.yml
- crates/AGENTS.md: merge duplicated Testing sections
- ARCHITECTURE.md: resolve the utils->config contradiction (edges are
  removed), mark volatile counts as snapshots, fix a bad path
- docs/architecture: add README router; move one-shot plans/trackers
  (rebalance-decommission phases, migration-progress ledger, PR
  template) to docs/superpowers/plans with archive headers; fix stale
  source paths in kept inventories (core/sets.rs, core/pools.rs,
  store/mod.rs, startup_* split from #3671)
- docs/operations/tier-ilm-debugging.md: extracted tier debugging
  playbook with corrected paths
- scripts/check_doc_paths.sh: new guard failing pre-commit/pre-pr when
  instruction/architecture docs reference nonexistent file paths
- .claude/skills: add tier-debug and arch-checks repo skills;
  .gitignore now keeps .claude/skills and docs/operations committable

Verification: ./scripts/check_doc_paths.sh,
./scripts/check_architecture_migration_rules.sh (both pass)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:30:13 +08:00

12 KiB

Archived implementation plan/tracker — moved from docs/architecture/ (2026-07). Kept for history; not maintained. File paths inside may reflect the pre-#3929 module layout (e.g. crates/ecstore/src/rebalance.rs is now crates/ecstore/src/store/rebalance.rs; set_disk.rs is now set_disk/).

Rebalance and Decommission Phase 3 Hardening Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Improve operator visibility, auditability, metadata robustness, and documented compatibility after the Phase 1 and Phase 2 safety fixes.

Architecture: Phase 3 should not change core data movement semantics unless a hardening test exposes a safety bug. It adds bounded status data, structured logs, metadata validation tests, and an explicit decision around rebalance completion tolerance.

Tech Stack: Rust, tracing structured logs, admin status DTOs, serde/rmp metadata decoding, existing guardrail scripts, crate-local unit tests.


Scope

This plan covers:

  • F11: improve rebalance cleanup failure reporting.
  • F12: add structured audit fields for rebalance/decommission operations.
  • F13: harden persisted rebalance and pool metadata decoding.
  • F14: decide and document rebalance completion threshold behavior.

This plan assumes the safety semantics from Phase 1 and the data movement behavior from Phase 2 are stable.

Shared Principles

  • Hardening must not hide safety failures.
  • Status fields should be bounded to avoid unbounded metadata growth.
  • Logs must be structured, searchable, and free of secrets.
  • Metadata compatibility must be explicit: strict where possible, legacy-compatible where necessary.

F11: Rebalance Cleanup Failure Reporting

Decision

Rebalance cleanup failures should not be invisible completion details. Admin status should expose whether completion had cleanup warnings and provide bounded object-level detail.

Files

  • Modify: crates/ecstore/src/rebalance.rs
  • Modify: rustfs/src/admin/handlers/rebalance.rs
  • Possibly modify: admin response DTOs in the same module or related madmin types
  • Test: rebalance status and metadata tests

Design

  1. Extend cleanup warning metadata.

    • Keep existing count.
    • Add a bounded list of recent cleanup failures, for example last 10 entries.
    • Each entry should include bucket, object, message, and timestamp.
  2. Keep metadata bounded.

    • Do not store every cleanup failure unboundedly in rebalance.bin.
    • Use a ring-buffer style helper or truncate older entries.
  3. Make terminal state visible.

    • If rebalance completes with cleanup warnings, status should show warning count and details.
    • Avoid reporting a clean completion when source cleanup failed.

Implementation Tasks

  • Add a cleanup warning entry struct with bounded retention.
  • Add metadata compatibility defaults for older rebalance.bin without the new list.
  • Update record_rebalance_cleanup_warning_in_meta to append bounded entries and update count/last fields.
  • Update admin status serialization to expose warning count and entries.
  • Add tests for one warning, multiple warnings, and bounded truncation.
  • Add legacy metadata decode test.

Focused Test Commands

cargo test -p rustfs-ecstore cleanup_warning --lib
cargo test -p rustfs-ecstore rebalance_meta --lib
cargo test -p rustfs rebalance --lib

Acceptance Criteria

  • Multiple cleanup failures are visible through count and bounded details.
  • Legacy rebalance metadata still decodes.
  • Status distinguishes clean completion from completion with cleanup warnings.

Risks

  • Adding status fields may affect clients if response schemas are strict. Prefer additive fields with defaults.

F12: Structured Audit Fields

Decision

Rebalance and decommission admin operations should have consistent structured logs for success, rejection, propagation failure, and partial/degraded state.

Files

  • Modify: rustfs/src/admin/handlers/rebalance.rs
  • Modify: rustfs/src/admin/handlers/pools.rs
  • Modify: crates/ecstore/src/notification_sys.rs
  • Modify: crates/ecstore/src/rpc/peer_rest_client.rs
  • Possibly modify: scripts/check_logging_guardrails.sh or related guardrails if logging rules require updates

Design

  1. Define standard fields.

    • event
    • component
    • subsystem
    • action
    • result
    • request_id when available
    • actor or masked access key when available
    • remote_addr when available
    • pool_indices or rebalance_id
    • peer
    • error
  2. Apply to admin handlers.

    • Start, stop, cancel, status-affecting operations.
    • Authorization failures should remain handled by existing auth paths but should have enough context if already logged.
  3. Apply to peer propagation.

    • Peer success and failure should use stable event names.
    • Partial failure must be warn/error, not info-only.
  4. Avoid secret leakage.

    • Never log raw credentials, signatures, tokens, or full auth headers.

Implementation Tasks

  • Inventory existing rebalance/decommission log events and field names.
  • Define a small local helper or convention for masked actor/request fields if one already exists.
  • Update rebalance admin start/stop/status logs.
  • Update decommission start/cancel/status logs.
  • Update notification peer propagation failure logs.
  • Add log-capture tests for success, partial failure, and rejected operation where feasible.
  • Run logging guardrail script if the repository has one.

Focused Test Commands

cargo test -p rustfs rebalance --lib
cargo test -p rustfs pools --lib
cargo test -p rustfs-ecstore notification --lib
scripts/check_logging_guardrails.sh

Acceptance Criteria

  • Operators can answer who requested an operation, what resource it targeted, and which peers failed.
  • Partial failures are searchable through stable structured fields.
  • Logs contain no secrets.

Risks

  • Logging changes can be noisy. Keep high-volume per-object logs out of admin audit events.

F13: Persisted Metadata Decode Hardening

Decision

Persisted rebalance and pool metadata should reject or surface unknown/corrupt fields where compatibility allows. Legacy compatibility must be tested explicitly.

Files

  • Modify: crates/ecstore/src/rebalance.rs
  • Modify: crates/ecstore/src/pools.rs
  • Possibly add fixtures under an existing test fixture directory if one exists
  • Test: metadata decode tests in rebalance.rs and pools.rs

Design

  1. Identify persisted structs.

    • Rebalance metadata and stats structs.
    • Pool metadata and decommission info structs.
  2. Choose strictness per struct.

    • Use strict unknown-field rejection where metadata is not expected to carry forward-compatible fields.
    • For legacy-compatible structs, keep decode lenient but log or validate unknown/unsupported state where possible.
  3. Add state validation.

    • Reject conflicting terminal states such as complete plus canceled plus running.
    • Reject impossible counters or invalid pool indices where existing validation can catch them.
  4. Preserve legacy fixtures.

    • Existing old metadata must still decode if compatibility is required.

Implementation Tasks

  • List all rebalance and pool metadata structs currently deserialized from persisted bytes.
  • Add fixture tests for unknown fields, missing critical fields, and conflicting terminal states.
  • Add strict serde attributes only where fixtures show compatibility is safe.
  • Add post-decode validation helpers for state conflicts.
  • Update load paths to surface validation errors with actionable messages.

Focused Test Commands

cargo test -p rustfs-ecstore rebalance_meta --lib
cargo test -p rustfs-ecstore pool_meta --lib
cargo test -p rustfs-ecstore metadata --lib

Acceptance Criteria

  • Unknown/corrupt metadata does not silently become an apparently valid operation state.
  • Legacy metadata fixtures continue to decode through documented paths.
  • Conflicting terminal state is rejected or quarantined.

Risks

  • Strict decode can block startup if old metadata contains benign extra fields. Start with tests and post-decode validation before broad strict attributes.

F14: Rebalance Completion Threshold Decision

Decision

RustFS must explicitly choose whether to match MinIO's tolerance-based rebalance completion or keep strict completion. The recommended default is to match MinIO unless RustFS has a documented reason to move more data.

Files

  • Modify: crates/ecstore/src/rebalance.rs
  • Possibly modify: admin docs if present
  • Test: rebalance goal/completion tests in rebalance.rs

Design Options

  1. Match MinIO tolerance.

    • Complete when pool free-space ratio is within the MinIO-like tolerance of the goal.
    • Reduces movement and operational time.
    • Best for compatibility.
  2. Keep strict behavior and document it.

    • No code behavior change.
    • Add tests proving strict behavior is intentional.
    • Status/docs should avoid implying MinIO-compatible tolerance.
  3. Configurable tolerance.

    • Most flexible but not recommended unless operators need it.
    • Adds configuration and support burden.

Start with option 1 if compatibility is the goal. If maintainers prefer strictness, implement option 2 with explicit tests and documentation.

Implementation Tasks

  • Add tests that capture current strict behavior around the completion goal.
  • Add tests for MinIO-like tolerance behavior.
  • Confirm maintainers choose MinIO-compatible or strict behavior.
  • Implement the selected threshold behavior.
  • Update status/docs comments so completion semantics are clear.

Focused Test Commands

cargo test -p rustfs-ecstore rebalance_goal --lib
cargo test -p rustfs-ecstore check_if_rebalance_done --lib
cargo test -p rustfs-ecstore rebalance --lib

Acceptance Criteria

  • Completion threshold behavior is covered by deterministic tests.
  • Operators can understand whether RustFS matches MinIO tolerance.
  • Empty-queue completion path remains valid.

Risks

  • Changing threshold may alter operational expectations for existing users. Document the change if behavior changes.

Phase 3 Test Matrix

Run after individual fix tests pass:

cargo test -p rustfs-ecstore rebalance_meta --lib
cargo test -p rustfs-ecstore pool_meta --lib
cargo test -p rustfs-ecstore rebalance --lib
cargo test -p rustfs rebalance --lib
cargo test -p rustfs pools --lib
cargo fmt --all --check

If logging guardrails are relevant:

scripts/check_logging_guardrails.sh

Before PR:

cargo fmt --all
cargo fmt --all --check
make pre-commit

Clean generated build artifacts after build-based verification.

Suggested PR Split

  1. PR 1: F11 cleanup warning status.
  2. PR 2: F12 structured audit fields.
  3. PR 3: F13 metadata decode hardening.
  4. PR 4: F14 completion threshold decision and tests.

F11 may depend on Phase 2 cleanup semantics if F10 changes retry behavior. F12 can be done anytime after Phase 1 defines distributed failure semantics.

Open Questions Before Coding

  1. What is the maximum number of cleanup warning entries to keep in persisted rebalance metadata?
  2. Which actor identity is safe and useful to log for admin requests?
  3. Should metadata unknown fields fail startup, warn and continue, or quarantine only the affected operation?
  4. Should RustFS match MinIO's rebalance completion tolerance by default?