Repository navigation
Conversation
`spec.tiers` registers S3, RustFS and MinIO remote tiers through the RustFS tier admin API, so bucket lifecycle transitions can reference a tier managed by the same Tenant. Tiers are reconciled before buckets. Credentials come from `tiers[].credsSecret` (`accesskey`/`secretkey`). RustFS never returns a tier secret key, so the applied Secret resourceVersion is recorded in `status.provisioning.tiers`; a Secret change, a different Secret, or an access key listed by RustFS that differs from the Secret updates the credentials with the edit API. Type, endpoint, bucket, prefix and region cannot change on a registered tier: a live tier with the same name and other settings is reported as `TierConflict` without writes, and a matching one is adopted. RustFS rejects a remote prefix that already holds objects with 409; that is reported as `TierConflict` too, and `force: true` registers the tier anyway. Removed tiers are retained, like other provisioned items. Closes rustfs#280
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Type of Change
Related Issues
Closes #280
Summary of Changes
A Tenant can now declare remote storage tiers in
spec.tiers. Bucket lifecycle transitions (#279) can then reference a tier that the same Tenant manages, so a Tenant, its tiers and its ILM rules are all managed through GitOps.list_tiers,add_tier(PUT /rustfs/admin/v3/tier?force=) andedit_tier_credentials(POST /rustfs/admin/v3/tier/{name}) are added. The tier list parser keeps type, name, endpoint, bucket, prefix, region and access key, and dropssecretKey.list_tier_namesfrom Feature request: Transition rules in spec.buckets[].lifecycle #279 now uses the same parser.credsSecret.TierConflictwith the differing field names, and nothing is written. Removing it automatically would be destructive: removal is rejected while objects reference the tier, and the transitioned objects depend on the remote prefix.status.provisioning.tiersrecords the SecretresourceVersion, the Secret name and an access-key hash, as for users. A Secret update, a differentcredsSecret, or an access key in the RustFS tier list that differs from the Secret updates the tier through the edit API. The tier Secret is added to the Tenant reference index, so a Secret update enqueues the Tenant. If a RustFS version ever lists the access key as empty orREDACTED, only the Secret version is compared, so the operator does not rewrite credentials on every reconcile.force, RustFS rejects a remote prefix that already holds objects with409 XMinioAdminTierBackendInUse. The operator reports this asTierConflictinstead of retrying.force: truesendsforce=trueand is meant for a prefix that belongs to this Tenant, for example after a restore. It is used only when the operator adds the tier.Retainedin RustFS and status, the samedeletionPolicy: Retainas policies, users and buckets.STANDARD,REDUCED_REDUNDANCY) with CEL. Reconcile repeats the RustFS checks exactly (Unicode uppercase, reserved names, valid XML text, since the name is also an S3 storage class). Errors are classified by status as elsewhere: timeouts, 429 and 5xx stayPendingand requeue; other 4xx and Secret errors fail withTierApplyFailed,TierSecretInvalidorTierConflict. The three new reasons are blocking and have next actions.tiers, the console shows tier status rows, and OpenAPI schemas,console-webtypes, the CRD YAML, the chart README, both user guides and CHANGELOG are updated.Checklist
make pre-commit(fmt-check + clippy + test + console-lint + console-fmt-check)[Unreleased](if user-visible change)Impact
The CRD change is additive:
spec.tiersandstatus.provisioning.tiersare new optional lists. The operator needs no new RBAC, because it already reads Secrets in the Tenant namespace for users.Verification
New tests:
rustfs-admin:tier_settings_are_read_without_the_secret_key. The Feature request: Transition rules in spec.buckets[].lifecycle #279 parser tests now run against the shared parser.missing_tier_is_registered_with_secret_credentialschecks the exact add payload andforce=false;owned_tier_with_unchanged_secret_is_not_rewritten;rotated_tier_secret_only_updates_credentials;existing_tier_is_adopted_once_and_out_of_band_access_key_is_corrected;live_tier_with_different_settings_fails_without_writes;non_empty_remote_prefix_is_a_conflict_unless_forced;tier_name_and_secret_errors_fail_before_rustfs_writes;transient_tier_list_failure_keeps_ownership_and_retries;spec_tier_is_registered_before_a_bucket_lifecycle_references_it, an end-to-end run with a mocked Secret;removed_tier_is_retained_with_its_ownership;redacted_live_access_key_falls_back_to_the_secret_version;tier_names_follow_rustfs_rules;tier_secret_values_are_trimmed_and_required.tier_deserializes_issue_yaml_shape_and_omits_defaults,tenant_crd_declares_tiers_with_rustfs_name_rules. The reference-index, referenced-secret, reason and OpenAPI tests also cover tiers.The payload shapes, status codes and the "only credentials are editable" rule come from the RustFS
1.0.2-preview.2tier handlers (rustfs/src/admin/handlers/tier.rs,crates/ecstore/src/services/tier/).Checks were run in containers matching CI: Rust stable in
rust:1-bookwormwith Helm 3.21.3 and cargo-nextest, andconsole-webinnode:24with pnpm 10.28.1. Allmake pre-committargets passed.cargo nextest run --allran 784 tests with 784 passing,helm lintpassed for both charts, andhelm templaterenders. A server-side dry run of the generated CRD on Kubernetes v1.36.5 accepted the CEL rules.Live check on a staging cluster. The cluster runs an operator image built from this branch (the
operatorbinary on top ofrustfs/operator:0.0.8) with the CRD from this branch. It manages a RustFS1.0.2-preview.2Tenant whose tiers point at Storj;STORJandLATEhad been registered earlier withrc ilm tier add.STORJdeclared with the live settingsReady, adopted with one credential edit, thenRustFS tier matches specon later reconciles without writesLATEdeclared with a differentprefixFailed/TierConflict:live RustFS tier differs from spec in prefix, no writeLATEprefix corrected in the specReadyTIERS-TESTon an empty prefixRustFS tier was registered) and listed byrc ilm tier listwith the declared settingscredsSecretupdated (newresourceVersion)observedSecretResourceVersionfollowed the SecretSTORJ, after the credential editx-amz-storage-class: STORJ); GET returned the original bytes (same SHA-256)Ready, lifecycle adopted without a PUTAdditional Notes
s3,rustfs,minio) are modeled. Azure, GCS and the other RustFS backends use different credential shapes and can follow if there is interest. The remotestorageClassof an S3 tier is not modeled either.deletionPolicyisRetainonly, like the other provisioned items. ADeletepolicy would need the remove API and its in-use checks, and can be added separately.Thank you for your contribution! Please ensure your PR follows the community standards (CODE_OF_CONDUCT.md) and sign the CLA if this is your first contribution.