The module lifecycle stage: Experimental
The module has requirements for installation
The Deckhouse Kubernetes Platform installs CRDs but does not remove them when a module is disabled. If you no longer need the created CRDs, delete them.
SDSElasticStore
Short names: sdsestore
Scope: Cluster
Version: v1alpha1
SDSElasticStore is an object store backed by the Ceph RADOS Gateway:
it provisions a Rook CephObjectStore on top of an ElasticCluster
already deployed by the sds-elastic module. It takes Ceph’s own pool
settings — replication or erasure coding — rather than a cross-backend
redundancy intent.
The name is deliberately neither ElasticCluster (the sds-elastic
resource it points at) nor CephObjectStore (the Rook resource it
creates underneath).
It is not consumed directly. An ObjectStore names it through
spec.storeRef, and tenants name that ObjectStore in their
Bucket.
-
objectspecDesired state of the store.
-
objectspec.dataPool
Durability of the pool holding object data, in Ceph’s own terms: exactly one of
replicatedorerasureCoded. Defaults to replicated with size 3.This is where the removal of the
None/Standard/Highintent shows most clearly: erasure coding is a(k, m)pair, and no replica count expresses it.-
objectspec.dataPool.erasureCodedEvery object split into data and coding chunks, trading CPU and latency for usable capacity.
-
integerspec.dataPool.erasureCoded.codingChunks
Required value
m: how many coding chunks are computed, and therefore how many failures the pool survives.k + mfailure domains are needed to place them.Allowed values:
1 <= X -
integerspec.dataPool.erasureCoded.dataChunks
Required value
k: how many data chunks each object is split into.Allowed values:
2 <= X
-
-
objectspec.dataPool.replicatedWhole copies of every object.
-
integerspec.dataPool.replicated.size
Required value
Number of copies kept, including the primary. The minimum is 2 and the sensible value is 3: size 1 loses data on any OSD loss, and size 2 blocks I/O while degraded.Allowed values:
2 <= X
-
-
-
stringspec.elasticClusterRef
Required value
Name of theElasticCluster(sds-elastic) whose Ceph cluster hosts the RGW pools. Immutable after creation.Length:
1..30Pattern:
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ -
objectspec.encryption
Server-side encryption of the stored object data.
Unlike
SeaweedFSStore, this needs an external secrets store — Deckhouse Stronghold: RGW’s server-managed encryption keeps its keys in a KMS and has no mode where the module can simply hand it a key. That asymmetry is in the API on purpose — the alternative would be a key reference here that is accepted and does nothing.What it configures is the
CephObjectStore’s own security block, which Rook turns into the RGW daemons’ encryption options. The module holds no key material at any point: it holds a token that lets RGW ask Stronghold.-
stringspec.encryption.mode
What encrypts the data.
Disabled(default) — nothing does.ServerManaged— RGW encrypts every object with a data key it takes from Deckhouse Stronghold (SSE-S3). Clients need no change.
Cannot be turned back off: objects already written still need their keys from the KMS.
Default:
DisabledAllowed values:
Disabled,ServerManaged -
objectspec.encryption.stronghold
The Deckhouse Stronghold instance RGW encrypts against.
What travels to Rook is Vault vocabulary (
KMS_PROVIDER: vault,VAULT_ADDR), and that is not a workaround: Stronghold keeps the Vault API and RGW speaks it. Any other Vault-compatible store therefore works too — it is just not what the documentation walks you through.The transit engine is required, and its mount path is not configurable: for SSE-S3 Rook builds the RGW prefix from the engine name alone (
/v1/transit), so a transit mounted anywhere else would be configured here, accepted, and never reached.-
stringspec.encryption.stronghold.address
Required value
Address of the Stronghold API, for examplehttps://stronghold.d8-stronghold.svc.cluster.local:8200.Minimal length:
1Pattern:
^https?:// -
objectspec.encryption.stronghold.caSecretRefSecret in the module namespace holding the CA bundle for a Stronghold with a private certificate, under the key
ca.crt. It is copied to sds-elastic’s namespace under the key Rook projects into the RGW pod (cert).-
stringspec.encryption.stronghold.caSecretRef.name
Required value
Minimal length:
1
-
-
objectspec.encryption.stronghold.tokenSecretRef
Required value
Secret in the module namespace holding the Stronghold token, under the key
token.Rook looks the token up in the
CephObjectStore’s own namespace, which is sds-elastic’s rather than this module’s. The module therefore copies this Secret there, owned by the store, and keeps the copy in step with the original.A token rather than Kubernetes authentication because that is all Rook wires for RGW. Keep it short-lived; the rotation reaches the copy on the next reconcile.
-
stringspec.encryption.stronghold.tokenSecretRef.name
Required value
Minimal length:
1
-
-
-
-
objectspec.gatewayThe RGW serving layer.
-
integerspec.gateway.instancesNumber of RGW daemons serving S3. Defaults to
1.Allowed values:
1 <= X
-
-
objectspec.metadataPoolDurability of the RGW metadata pools (index, log, bucket metadata). Always replicated — RGW metadata needs omap, which erasure-coded pools do not support. Defaults to size 3.
-
integerspec.metadataPool.size
Required value
Number of copies kept, including the primary.Allowed values:
2 <= X
-
-
objectspec.publish
Exposes this store’s S3 endpoint outside the cluster, through the Gateway API implementation of the
albmodule. Unset (the default) means in-cluster only.The
Gatewayis not created here: an administrator or a team owns it, throughALBInstanceorClusterALBInstance. This module only attaches a route to it. Attaching a route from another namespace is permitted on the target side (aReferenceGrantin the Gateway’s namespace, or the listener’sallowedRoutes); if it is not permitted, the store says so in its conditions instead of trying to grant itself access.-
stringspec.publish.addressing
How a client addresses a bucket on the published endpoint.
PathStyle(default) —https://s3.example.com/<bucket>/<key>. One DNS name and one certificate, which is what an administrator can always get.VirtualHosted—https://<bucket>.s3.example.com/<key>. Needs wildcard DNS and a wildcard certificate (DNS-01 only), and is not supported uniformly by the backends’ S3 gateways.
Default:
PathStyleAllowed values:
PathStyle,VirtualHosted -
objectspec.publish.gatewayRef
Required value
The Gateway to attach the route to. The namespace is part of the reference because a shared Gateway lives in thealbcontroller’s namespace, not next to the store.-
stringspec.publish.gatewayRef.name
Required value
Name of the Gateway.Length:
1..253 -
stringspec.publish.gatewayRef.namespace
Required value
Namespace the Gateway lives in.Length:
1..63
-
-
stringspec.publish.hostname
Required value
Hostname the published endpoint answers on, for examples3.example.com. A wildcard (*.s3.example.com) is required forVirtualHostedaddressing and rejected forPathStyle.Length:
1..253Pattern:
^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+$ -
objectspec.publish.tls
Required value
Server certificate for the published endpoint. Required: SigV4 credentials travel in theAuthorizationheader, so publishing over plain HTTP would hand the bucket to anyone who can see the traffic. There is deliberately no insecure escape hatch.-
objectspec.publish.tls.secretRef
Required value
Akubernetes.io/tlsSecret in the module namespace. The module issues no certificates and does not depend on the cert-manager API: point this at the Secret cert-manager produces, or put your own there. Rotating the certificate is a write to that Secret — the store is not recreated.-
stringspec.publish.tls.secretRef.name
Required value
Name of the TLS Secret.Length:
1..253
-
-
-
-
stringspec.reclaimPolicy
What happens to the Ceph pools when this store is deleted.
Retain(default) — the pools are kept (preservePoolsOnDelete: true), so no stored objects are lost. TheCephObjectStoreitself is still removed: leaving it behind would keep the Ceph cluster in use and block theElasticClusterfrom ever being deleted.Delete— the RGW pools, and every object in them, are destroyed.
Immutable after creation.
Default:
RetainAllowed values:
Retain,Delete
-
-
objectstatusObserved state of the store.
-
objectstatus.adminSecretRef
Reference to the Secret (in the module namespace) holding the backend admin credentials the controller manages buckets and access keys with.
Not published by every backend: Ceph RGW credentials are owned by Rook and live in the sds-elastic namespace, not this module’s.
-
stringstatus.adminSecretRef.name
-
-
objectstatus.backendEngine behind this store and its running version.
-
stringstatus.backend.typeBackend engine.
Allowed values:
SeaweedFS,CephRGW -
stringstatus.backend.versionRunning backend version.
-
-
objectstatus.capacityStore-wide storage usage reported by the backend.
-
stringstatus.capacity.availableFree capacity, Kubernetes Quantity (BinarySI).
-
stringstatus.capacity.lastUpdatedTimestamp of the latest capacity probe.
-
stringstatus.capacity.totalTotal usable capacity, Kubernetes Quantity (BinarySI).
-
stringstatus.capacity.usedConsumed capacity, Kubernetes Quantity (BinarySI).
-
stringstatus.capacity.usedPercent
used / total * 100, formatted with two decimals.
-
-
array of objectsstatus.conditionsPer-stage conditions:
BackendReady,EndpointReady, and the aggregateReady.-
stringstatus.conditions.lastTransitionTimeTimestamp of the last status transition for this condition.
-
stringstatus.conditions.messageHuman-readable explanation of the current status.
Maximum length:
32768 -
integerstatus.conditions.observedGenerationValue of
metadata.generationthe condition was last set against.Allowed values:
0 <= X -
stringstatus.conditions.reasonMachine-readable reason for the current status, suitable for log filtering.
Length:
1..1024Pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ -
stringstatus.conditions.statusCurrent status of the condition.
Allowed values:
True,False,Unknown -
stringstatus.conditions.typeCondition type, for example
Ready,BackendReady, orEndpointReady.Maximum length:
316Pattern:
^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
-
-
objectstatus.encryption
What is actually encrypting the stored data.
No key fingerprint here, unlike
SeaweedFSStore: on this backend the key lives in the KMS and never passes through the module, so there is nothing of ours to fingerprint — and a fingerprint of the token would suggest the data depends on it, which it does not.-
stringstatus.encryption.keyFingerprintNot published by this backend — see above.
-
stringstatus.encryption.messageWhy the mode in force is not the one the spec asks for.
-
stringstatus.encryption.modeWhat the backend is doing, which is not always what the spec asks for: a store whose KMS configuration could not be applied keeps the mode it was already running with.
Allowed values:
Disabled,ServerManaged -
stringstatus.encryption.sinceWhen this mode took effect.
-
-
objectstatus.endpointS3 endpoint clients use to reach this store.
-
stringstatus.endpoint.externalS3 endpoint URL reachable from outside the cluster, set only while
spec.publishis in effect. Empty for an unpublished store: there is no external address to hand out. -
stringstatus.endpoint.internalIn-cluster S3 endpoint URL (Service DNS), e.g.
http://default-seaweedfs.d8-sds-object.svc.cluster.local:8333. -
stringstatus.endpoint.regionDefault S3 region advertised by the endpoint.
-
-
objectstatus.integrity
What is known about the stored data being intact: when it was last checked, by whom, and what was found.
Absent means nothing has been checked yet, which is not the same as “nothing is wrong” — that is why the timestamp is a field of its own and not implied by the counters.
-
integerstatus.integrity.damagedHow many units were found damaged.
-
array of stringsstatus.integrity.detailsThe backend’s own words about each finding, bounded in number and length. Not summarised: only the engine’s text names the volume, the object and the checksums, and that is what a disk is searched by.
-
stringstatus.integrity.lastScrubTimeWhen the reported result was produced.
-
integerstatus.integrity.repairedHow many of them the module put right. Kept apart from
damagedon purpose: “something was damaged and we fixed it” is not an alarm. -
objectstatus.integrity.scannedHow much the check covered.
-
integerstatus.integrity.scanned.objectsStored items examined, where the backend counts them.
-
integerstatus.integrity.scanned.volumesStorage units examined — SeaweedFS volumes, Ceph placement groups.
-
-
stringstatus.integrity.source
Who performed the check.
Always
Backendhere: Ceph scrubs on its own schedule and the module reports what it found. It never starts a deep-scrub and never turns on automatic repair — that is configuration of the Ceph cluster, and it belongs to the module that owns it.Allowed values:
Module,Backend -
integerstatus.integrity.unreachable
How many storage nodes could not be asked at all.
Apart from
damaged, and the distinction is not academic: a volume server that was restarting while the check ran has said nothing about its data. Counting that as damage would page somebody about corruption that was never found, and would hide the real news — that part of the store went unchecked. A pass with unreachable nodes and no findings leavesIntegrityHealthyUnknown rather than True.
-
-
integerstatus.observedGenerationMost recent
metadata.generationreconciled by the controller. -
stringstatus.phaseCoarse-grained summary derived from Conditions.
Allowed values:
Pending,InProgress,Ready,Error -
objectstatus.redundancy
Whether the data has as many copies as the spec asks for.
Reported apart from
integritybecause a missing copy is not damage: a store one replica short may have every byte intact, and it is one disk away from not having them. One number for both would hide whichever came second.-
integerstatus.redundancy.copiesWantedHow many copies of each unit of storage the replication setting calls for, the original included.
-
array of stringsstatus.redundancy.detailsWhich volumes are short and by how much, bounded in number.
-
stringstatus.redundancy.lastCheckTimeWhen this accounting was made. It comes from the master’s own topology, so it is refreshed on every reconcile rather than on the scrub schedule.
-
integerstatus.redundancy.underReplicatedHow many of them have fewer copies than asked for.
-
integerstatus.redundancy.volumesHow many units of storage were accounted for.
-
-
SeaweedFSStore
Short names: swfsstore
Scope: Cluster
Version: v1alpha1
SeaweedFSStore is an object store backed by SeaweedFS: master, volume server and filer StatefulSets on PVCs, fronted by the S3 gateway. It takes SeaweedFS’s own settings — how many of each component, and the replication code — rather than a cross-backend redundancy intent.
It is not consumed directly. An ObjectStore names it through
spec.storeRef, and tenants name that ObjectStore in their
Bucket.
-
objectspecDesired state of the store.
-
objectspec.encryption
Server-side encryption of the stored object data.
Unset means objects are written as they arrive: whoever holds the disk reads them. With
ServerManagedthe module hands the S3 gateway a key from a Secret and marks every bucket it manages for default encryption, so objects are encrypted without any change to the clients writing them.The shape differs from
SDSElasticStore’s on purpose: SeaweedFS wraps each object’s data key with a key this module supplies, so a Secret is enough, while Ceph RGW can only do the same through an external Vault.-
objectspec.encryption.keySecretRef
Secret in the module namespace holding the wrapping key, under one of two keys:
kek(32 bytes hex-encoded, used directly) orkey(any passphrase, from which the key is derived).Referenced rather than inlined so the key never appears in the store object. Note what changing it means: the backend does not re-wrap anything, so objects written under the previous key stop being readable. The module fingerprints the key and refuses to apply a changed one — see
status.encryption.-
stringspec.encryption.keySecretRef.name
Required value
Minimal length:
1
-
-
stringspec.encryption.mode
What encrypts the data.
Disabled(default) — nothing does.ServerManaged— the S3 gateway encrypts every object with a data key of its own, wrapped by the key fromkeySecretRef. Reads and writes need no client change, and the wrapping key never reaches the metadata store.
Cannot be turned back off: objects already written still need the wrapping key, so the key would have to stay configured anyway. A field that says “disabled” while the key must remain would be lying, so the way back is a new store.
Default:
DisabledAllowed values:
Disabled,ServerManaged
-
-
objectspec.externalMetadataStoreConnection details of the PostgreSQL to use with
metadataStore: External. Required with it, refused without it.-
objectspec.externalMetadataStore.secretRef
Required value
Secret in the module namespace (
d8-sds-object) holding the connection details. Keys:host(required) — hostname or address of the server;port— TCP port,5432when absent;database(required) — database the filer writes its metadata into;username,password(required) — a role that may create tables in it: the filer creates one table per bucket on first use;sslmode— libpq mode,requirewhen absent.disablesends the password in the clear and is refused;ca.crt— PEM bundle to verify the server with. Present, it is mounted into the filer and the connection verifies the server against it; absent,requireencrypts without checking who is on the other end.
A Secret and not fields here: the connection carries a password, and a password in a spec is a password in every
kubectl get -o yamland in every backup of the cluster’s resources.-
stringspec.externalMetadataStore.secretRef.name
Required value
Name of the Secret.Length:
1..253
-
-
integerspec.filersNumber of filer servers, each also serving the S3 gateway. More than one requires
metadataStore: Postgres. Defaults to1.Default:
1Allowed values:
1 <= X -
objectspec.integrity
Periodic data scrub.
SeaweedFS verifies a checksum whenever an object is read, and it has a scrub that verifies every stored object without reading it through the gateway — but it never runs that scrub on its own. Cold data is therefore never checked, which is exactly where a rotting disk goes unnoticed longest. This module runs it on a schedule instead.
SDSElasticStorehas no such field: Ceph scrubs on its own schedule, and the module only reports what it finds.-
booleanspec.integrity.autoRepair
Lets the module replace a damaged copy of a volume with a fresh one pulled from a copy that is intact.
Off by default because it is the most destructive thing this module does: the repair deletes a copy of live data on the strength of an automatic decision. Whether a controller may do that to save the data is the tenant’s call.
It never runs without a way back. The store must keep more than one copy, and another copy of that volume must have been scrubbed clean in the same pass — “this copy is bad” is not “that one is good”, and a volume server that did not answer the scrub is not evidence of anything. When neither holds, the damage is reported and the copy is left alone.
Default:
false -
booleanspec.integrity.enabledTurns the scrub off when
false. A field rather than “set a huge interval”: switching it off is a decision worth reading in the manifest, and an interval of a year looks like a typo.Default:
true -
stringspec.integrity.interval
How often to scrub. Defaults to
168h(weekly), and values below1hare raised to it.The default is deliberately conservative: a
Fullscrub reads every stored byte, and the cost of that on a large store has not been measured. Shorten it when the store’s disks matter more than its read bandwidth. -
stringspec.integrity.mode
How thorough the scrub is.
Full(default) — verifies the checksum of every stored object. Reads all the data.Index— checks the volume indexes only. Cheap, and it finds a damaged index but not a rotted object body, which is the thing worth looking for.
Default:
FullAllowed values:
Index,Full
-
-
integerspec.mastersNumber of master servers. Masters hold a Raft quorum, so an odd count is what makes sense:
1for a store that may go down with its node,3for one that must not. Defaults to3.Default:
3Allowed values:
1 <= X -
stringspec.metadataStore
Where the filer keeps its metadata.
LevelDB(default) — the built-in store on the filer’s own PVC. No external dependency, and no sharing: one filer.Postgres— a Postgres deployed alongside through the managed-postgres module, which is what allows several filers to serve the same namespace.External— a PostgreSQL this module does not run, named byexternalMetadataStore. Same capability asPostgresand a different owner: whoever runs that database owns its availability, its backups and its upgrades.
Immutable after creation: the metadata is not migrated between them.
Default:
LevelDBAllowed values:
LevelDB,Postgres,External -
objectspec.placementScheduling of the store’s data plane.
-
objectspec.placement.nodeSelectorNode labels the data-plane Pods must match (same semantics as a Pod’s
spec.nodeSelector). -
array of objectsspec.placement.tolerationsTolerations for the data-plane Pods (same shape as a Pod’s
spec.tolerations).-
stringspec.placement.tolerations.effect
Allowed values:
‘’,NoSchedule,PreferNoSchedule,NoExecute -
stringspec.placement.tolerations.key
-
stringspec.placement.tolerations.operator
Allowed values:
Exists,Equal -
integerspec.placement.tolerations.tolerationSeconds
-
stringspec.placement.tolerations.value
-
-
-
stringspec.postgresClassName
Name of the PostgresClass the managed metadata database is provisioned from. Empty means the class named
default.This is the only handle the store has on where the database Pods run: the Postgres resource carries no scheduling fields, so
spec.placementcannot reach them —tolerations,nodeSelectorandnodeAffinityare fields of the PostgresClass. To place the database on dedicated nodes, create a class that says so and name it here.Applies only to
metadataStore: Postgres.Maximum length:
253 -
objectspec.publish
Exposes this store’s S3 endpoint outside the cluster, through the Gateway API implementation of the
albmodule. Unset (the default) means in-cluster only.The
Gatewayis not created here: an administrator or a team owns it, throughALBInstanceorClusterALBInstance. This module only attaches a route to it. Attaching a route from another namespace is permitted on the target side (aReferenceGrantin the Gateway’s namespace, or the listener’sallowedRoutes); if it is not permitted, the store says so in its conditions instead of trying to grant itself access.-
stringspec.publish.addressing
How a client addresses a bucket on the published endpoint.
PathStyle(default) —https://s3.example.com/<bucket>/<key>. One DNS name and one certificate, which is what an administrator can always get.VirtualHosted—https://<bucket>.s3.example.com/<key>. Needs wildcard DNS and a wildcard certificate (DNS-01 only), and is not supported uniformly by the backends’ S3 gateways.
Default:
PathStyleAllowed values:
PathStyle,VirtualHosted -
objectspec.publish.gatewayRef
Required value
The Gateway to attach the route to. The namespace is part of the reference because a shared Gateway lives in thealbcontroller’s namespace, not next to the store.-
stringspec.publish.gatewayRef.name
Required value
Name of the Gateway.Length:
1..253 -
stringspec.publish.gatewayRef.namespace
Required value
Namespace the Gateway lives in.Length:
1..63
-
-
stringspec.publish.hostname
Required value
Hostname the published endpoint answers on, for examples3.example.com. A wildcard (*.s3.example.com) is required forVirtualHostedaddressing and rejected forPathStyle.Length:
1..253Pattern:
^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+$ -
objectspec.publish.tls
Required value
Server certificate for the published endpoint. Required: SigV4 credentials travel in theAuthorizationheader, so publishing over plain HTTP would hand the bucket to anyone who can see the traffic. There is deliberately no insecure escape hatch.-
objectspec.publish.tls.secretRef
Required value
Akubernetes.io/tlsSecret in the module namespace. The module issues no certificates and does not depend on the cert-manager API: point this at the Secret cert-manager produces, or put your own there. Rotating the certificate is a write to that Secret — the store is not recreated.-
stringspec.publish.tls.secretRef.name
Required value
Name of the TLS Secret.Length:
1..253
-
-
-
-
stringspec.reclaimPolicy
What happens to the persisted data when this store is deleted.
Retain(default) — the PVCs are kept, so nothing stored is lost.Delete— the PVCs are removed with the workloads.
Immutable after creation.
Default:
RetainAllowed values:
Retain,Delete -
stringspec.replication
SeaweedFS’s own three-digit replication code
xyz: copies on other data centres, other racks, and other servers in the same rack.000keeps a single copy,001one extra copy on another server,002two. Defaults to001.Only
00zis accepted: the data plane runs every volume server in one Kubernetes cluster with the default SeaweedFS topology, so a copy in another rack or data centre has nowhere to go and the write would never complete.Immutable after creation: raising the code does not re-replicate what is already written.
Default:
001Pattern:
^[0-9]{3}$ -
objectspec.storage
Required value
PVCs backing the data plane.-
stringspec.storage.class
Required value
Name of the Kubernetes StorageClass used to provision PVCs. Immutable after creation.Length:
1..253 -
stringspec.storage.sizePerNodeCapacity provisioned per volume server as a Kubernetes Quantity (BinarySI), e.g.
50Gior2Ti. The store-wide capacity is roughlysizePerNodetimesvolumeServers. Defaults to10Gi.Pattern:
^[0-9]+(\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E)?$
-
-
integerspec.volumeServersNumber of volume servers holding the data. Must be at least the copy count in
replication, or writes never find anywhere to put a copy. Defaults to3.Default:
3Allowed values:
1 <= X
-
-
objectstatusObserved state of the store.
-
objectstatus.adminSecretRef
Reference to the Secret (in the module namespace) holding the backend admin credentials the controller manages buckets and access keys with.
Not published by every backend: Ceph RGW credentials are owned by Rook and live in the sds-elastic namespace, not this module’s.
-
stringstatus.adminSecretRef.name
-
-
objectstatus.backendEngine behind this store and its running version.
-
stringstatus.backend.typeBackend engine.
Allowed values:
SeaweedFS,CephRGW -
stringstatus.backend.versionRunning backend version.
-
-
objectstatus.capacityStore-wide storage usage reported by the backend.
-
stringstatus.capacity.availableFree capacity, Kubernetes Quantity (BinarySI).
-
stringstatus.capacity.lastUpdatedTimestamp of the latest capacity probe.
-
stringstatus.capacity.totalTotal usable capacity, Kubernetes Quantity (BinarySI).
-
stringstatus.capacity.usedConsumed capacity, Kubernetes Quantity (BinarySI).
-
stringstatus.capacity.usedPercent
used / total * 100, formatted with two decimals.
-
-
array of objectsstatus.conditionsPer-stage conditions:
BackendReady,EndpointReady, and the aggregateReady.-
stringstatus.conditions.lastTransitionTimeTimestamp of the last status transition for this condition.
-
stringstatus.conditions.messageHuman-readable explanation of the current status.
Maximum length:
32768 -
integerstatus.conditions.observedGenerationValue of
metadata.generationthe condition was last set against.Allowed values:
0 <= X -
stringstatus.conditions.reasonMachine-readable reason for the current status, suitable for log filtering.
Length:
1..1024Pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ -
stringstatus.conditions.statusCurrent status of the condition.
Allowed values:
True,False,Unknown -
stringstatus.conditions.typeCondition type, for example
Ready,BackendReady, orEndpointReady.Maximum length:
316Pattern:
^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
-
-
objectstatus.encryption
What is actually encrypting the stored data, and with which key.
keyFingerprintis the field with teeth. Changing the wrapping key does not re-wrap anything: every object written under the old key becomes unreadable, and the backend answers a read with an internal error rather than anything naming the key. The change is also latent — the gateway reads the key at startup, so a rewritten Secret breaks nothing until the next restart, which will happen for an unrelated reason weeks later. The fingerprint is how the module notices while the reads still work.-
stringstatus.encryption.keyFingerprintIdentifies the wrapping key without disclosing it. This is the key the stored objects were written under; a spec naming a different one is reported rather than applied.
-
stringstatus.encryption.messageWhy the mode in force is not the one the spec asks for.
-
stringstatus.encryption.modeWhat the backend is doing, which is not always what the spec asks for: a store whose key cannot be read keeps running with the mode it already had.
Allowed values:
Disabled,ServerManaged -
stringstatus.encryption.sinceWhen this mode and key took effect.
-
-
objectstatus.endpointS3 endpoint clients use to reach this store.
-
stringstatus.endpoint.externalS3 endpoint URL reachable from outside the cluster, set only while
spec.publishis in effect. Empty for an unpublished store: there is no external address to hand out. -
stringstatus.endpoint.internalIn-cluster S3 endpoint URL (Service DNS), e.g.
http://default-seaweedfs.d8-sds-object.svc.cluster.local:8333. -
stringstatus.endpoint.regionDefault S3 region advertised by the endpoint.
-
-
objectstatus.integrity
What is known about the stored data being intact: when it was last checked, by whom, and what was found.
Absent means nothing has been checked yet, which is not the same as “nothing is wrong” — that is why the timestamp is a field of its own and not implied by the counters.
-
integerstatus.integrity.damagedHow many units were found damaged.
-
array of stringsstatus.integrity.detailsThe backend’s own words about each finding, bounded in number and length. Not summarised: only the engine’s text names the volume, the object and the checksums, and that is what a disk is searched by.
-
stringstatus.integrity.lastScrubTimeWhen the reported result was produced.
-
integerstatus.integrity.repairedHow many of them the module put right. Kept apart from
damagedon purpose: “something was damaged and we fixed it” is not an alarm. -
objectstatus.integrity.scannedHow much the check covered.
-
integerstatus.integrity.scanned.objectsStored items examined, where the backend counts them.
-
integerstatus.integrity.scanned.volumesStorage units examined — SeaweedFS volumes, Ceph placement groups.
-
-
stringstatus.integrity.source
Who performed the check.
Module— this module ran it (SeaweedFS has the check but never runs it on its own).Backend— the engine checks on its own schedule and the module reports what it found (Ceph).
Allowed values:
Module,Backend -
integerstatus.integrity.unreachable
How many storage nodes could not be asked at all.
Apart from
damaged, and the distinction is not academic: a volume server that was restarting while the check ran has said nothing about its data. Counting that as damage would page somebody about corruption that was never found, and would hide the real news — that part of the store went unchecked. A pass with unreachable nodes and no findings leavesIntegrityHealthyUnknown rather than True.
-
-
integerstatus.observedGenerationMost recent
metadata.generationreconciled by the controller. -
stringstatus.phaseCoarse-grained summary derived from Conditions.
Allowed values:
Pending,InProgress,Ready,Error -
objectstatus.redundancy
Whether the data has as many copies as the spec asks for.
Reported apart from
integritybecause a missing copy is not damage: a store one replica short may have every byte intact, and it is one disk away from not having them. One number for both would hide whichever came second.-
integerstatus.redundancy.copiesWantedHow many copies of each unit of storage the replication setting calls for, the original included.
-
array of stringsstatus.redundancy.detailsWhich volumes are short and by how much, bounded in number.
-
stringstatus.redundancy.lastCheckTimeWhen this accounting was made. It comes from the master’s own topology, so it is refreshed on every reconcile rather than on the scrub schedule.
-
integerstatus.redundancy.underReplicatedHow many of them have fewer copies than asked for.
-
integerstatus.redundancy.volumesHow many units of storage were accounted for.
-
-
BucketAccess
Short names: ba
Scope: Namespaced
Version: v1alpha1
BucketAccess requests scoped S3 credentials for a Bucket in the same
namespace. The controller mints a dedicated access key / secret key
for this access, writes a Secret in the same namespace (see
status.secretRef) with the standard S3 connection variables, and
revokes the key when the access is deleted.
Access is namespace-local by construction: the Bucket it references
must live in this namespace, and that Bucket’s contents are private to
it. An access whose Bucket is not Bound stays Pending.
Key rotation: set or change the annotation
storage.deckhouse.io/rotate to trigger issuance of a fresh key
pair (the Secret is updated and the previous key is revoked).
-
objectspecDesired state of the access.
-
stringspec.bucketRef
Required value
Name of the Bucket (in this access’s namespace) whose contents the credentials are scoped to. The Bucket must be Bound before credentials are issued. Immutable after creation.Length:
1..253Pattern:
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ -
stringspec.credentialsSecretNameOverrides the name of the credentials Secret written in this access’s namespace. Defaults to
<metadata.name>-s3-credentials.Length:
1..253 -
stringspec.endpointScope
EndpointScope selects which of the store’s addresses lands in the credentials Secret. Defaults to Internal.
Internal is the default because most consumers run in this cluster, and moving them onto an external load balancer unasked would be a regression in both latency and traffic cost.
External on a store that is not published does NOT fall back to the internal address: the access goes NotReady and says why. A silent fallback hands out a working Secret whose address is unreachable from where it is about to be used, and that gets found out in production.
Allowed values:
Internal,External -
stringspec.permission
Access level granted to the issued credentials.
ReadWrite(default) — read and write objects.ReadOnly— read objects only.
Default:
ReadWriteAllowed values:
ReadWrite,ReadOnly
-
-
objectstatusObserved state of the access.
-
stringstatus.accessKeyIDPublic access key id issued for this access (the secret key is only written into the credentials Secret).
-
stringstatus.bucketNameEffective bucket name the access is scoped to.
-
array of objectsstatus.conditionsPer-component conditions:
AccessGranted,CredentialsReady, and the aggregateReady.-
stringstatus.conditions.lastTransitionTimeTimestamp of the last status transition for this condition.
-
stringstatus.conditions.messageHuman-readable explanation of the current status.
Maximum length:
32768 -
integerstatus.conditions.observedGenerationValue of
metadata.generationthe condition was last set against.Allowed values:
0 <= X -
stringstatus.conditions.reasonMachine-readable reason for the current status, suitable for log filtering.
Length:
1..1024Pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ -
stringstatus.conditions.statusCurrent status of the condition.
Allowed values:
True,False,Unknown -
stringstatus.conditions.typeCondition type, for example
Ready,AccessGranted, orCredentialsReady.Maximum length:
316Pattern:
^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
-
-
stringstatus.endpointIn-cluster S3 endpoint URL of the backing cluster.
-
stringstatus.lastRotationTimeTimestamp of the most recent key issuance.
-
integerstatus.observedGenerationMost recent
metadata.generationreconciled by the controller. -
stringstatus.observedRotationLast value of the
storage.deckhouse.io/rotateannotation processed by the controller. -
stringstatus.phaseCoarse-grained summary derived from Conditions.
Allowed values:
Pending,InProgress,Ready,Error -
objectstatus.secretRefReference to the Secret (in this access’s namespace) holding the S3 connection variables and credentials:
S3_ENDPOINT,S3_REGION,S3_BUCKET,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY.-
stringstatus.secretRef.name
Required value
Name of the referenced Secret.
-
-
BucketContents
Short names: bktc
Scope: Cluster
Version: v1alpha1
BucketContents is the backing object for a single S3 bucket in a store — what a PersistentVolume is to a claim. The controller creates it for a namespaced Bucket and provisions the bucket in the backend; it is not meant to be declared by hand, and the admission webhook admits it only from the module’s own service account.
It is cluster-scoped and credentials are NOT issued here: the owning Bucket’s namespace requests scoped access and receives a credentials Secret via namespaced BucketAccess resources.
It outlives its Bucket when the reclaim policy says so. A Bucket
deleted under Retain leaves this object behind in phase Released
with the data intact — which is what keeps deleting a namespace from
destroying the objects in it. Recreating the same Bucket (same
namespace, same name) re-binds it and the data comes back with it.
-
objectspecDesired state of the bucket.
-
stringspec.accessPolicy
Bucket access policy.
Private(default) — accessible only with issued credentials.PublicRead— objects are readable anonymously; writes still require credentials, and listing the bucket is not granted (an anonymous caller must know the object key).
Default:
PrivateAllowed values:
Private,PublicRead -
stringspec.bucketNameName of the bucket in S3. Defaults to
metadata.namewhen omitted. Must follow S3 bucket naming rules. Immutable after creation.Length:
3..63Pattern:
^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ -
objectspec.bucketRef
Identifies the Bucket that owns this object.
This is the authoritative owner record: it names the only namespace allowed to issue credentials for the bucket. Only the module’s own service account may set it (enforced by the admission webhook on create), and it is immutable afterwards, so these contents cannot be re-pointed at another Bucket and no Bucket can take over contents that belong to a different one. The
storage.deckhouse.io/owned-by-bucket-*labels mirror it for label queries but are user-settable and are never used for authorization.A
Releasedobject keeps it: it records which Bucket the data belongs to, and it is what lets that same Bucket — recreated with the same name in the same namespace — pick the data back up.-
stringspec.bucketRef.name
Required value
Name of the owning Bucket.Length:
1..253 -
stringspec.bucketRef.namespace
Required value
Namespace of the owning Bucket.Length:
1..253
-
-
objectspec.lifecycleLifecycle mirrors the owning Bucket’s expiry rules. Unlike objectLock it is kept in step on every pass: expiry can be changed on a live bucket, and a rule removed from the Bucket has to stop deleting objects.
-
array of objectsspec.lifecycle.rules
Rules to apply. An empty list removes the bucket’s lifecycle configuration entirely.
Keyed by id: the API server then rejects two rules under one name, and a rule keeps its identity when the list is reordered. Both matter because the id is what the rule is called in the backend — S3 requires it to be unique, and this module recognises a rule by it when deciding whether anything needs writing.
-
integerspec.lifecycle.rules.abortIncompleteUploadsAfterDaysAbortIncompleteUploadsAfterDays removes the parts of a multipart upload that was never completed. Those parts occupy space and appear in no listing, so without this they are storage nobody can see and nobody frees.
Allowed values:
1 <= X -
integerspec.lifecycle.rules.expireAfterDaysExpireAfterDays deletes an object this many days after it was written. On a versioned bucket this makes the current version non-current rather than removing the data; use
expireNoncurrentAfterDaysto reclaim the space.Allowed values:
1 <= X -
integerspec.lifecycle.rules.expireNoncurrentAfterDays
ExpireNoncurrentAfterDays deletes a version this many days after it stopped being current. Only meaningful on a versioned bucket.
Object lock outranks it: a version under an unexpired retention is not deleted, whatever this says.
Allowed values:
1 <= X -
stringspec.lifecycle.rules.id
ID names the rule in the backend, so a rule can be recognised in
aws s3api get-bucket-lifecycle-configurationoutput.Required, and given rather than derived. A name taken from the rule’s position would change under every insertion into the list: the same rule would arrive at the backend under a new name, the old one would be dropped, and a reordering nobody thinks of as a change would rewrite the whole configuration.
Length:
1..255 -
stringspec.lifecycle.rules.prefixPrefix limits the rule to object keys starting with it. Absent, the rule applies to every object in the bucket — which is what makes an accidental
expireAfterDayson a whole bucket worth reading twice.Maximum length:
1024
-
-
-
objectspec.objectLockObjectLock mirrors the owning Bucket’s object lock request. Immutable, for the reason given on Bucket: the backend accepts it only at creation.
-
integerspec.objectLock.days
Required value
Days is how long a new object stays protected, in days.
Days rather than a duration because S3 expresses a default retention in whole days or whole years, and years are days without loss of meaning.
Allowed values:
1 <= X -
stringspec.objectLock.mode
Required value
Mode is the retention mode for new objects.Allowed values:
Governance,Compliance
-
-
objectspec.quotaOptional usage limits for the bucket. Enforcement depends on backend capabilities.
-
integerspec.quota.maxObjectsMaximum number of objects.
0(default) means no limit.Allowed values:
0 <= X -
stringspec.quota.maxSizeMaximum total size of the bucket as a Kubernetes Quantity (BinarySI), e.g.
10Gi. Omit for no size limit.Pattern:
^[0-9]+(\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E)?$
-
-
stringspec.reclaimPolicy
What happens to bucket data when the Bucket is deleted.
Retain(default) — the bucket and its objects are kept in the backend.Delete— the bucket and all its objects are deleted.
Default:
RetainAllowed values:
Retain,Delete -
objectspec.storeRef
Required value
The store holding this bucket. The controller resolves it from the owning
Bucket’sObjectStoreclass and writes it here; the store must exist and beReadybefore the bucket is provisioned.It is the store and not the class, on purpose: the data lives in the store, so a class that is later deleted or re-pointed must not change where these contents are looked for.
Immutable after creation.
-
stringspec.storeRef.kind
Required value
Kind of the store object, e.g.SeaweedFSStore.Length:
1..63 -
stringspec.storeRef.name
Required value
Name of the store object.Length:
1..30Pattern:
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
-
-
stringspec.versioningVersioning mirrors the owning Bucket’s versioning request.
Default:
SuspendedAllowed values:
Enabled,Suspended
-
-
objectstatusObserved state of the bucket.
-
stringstatus.bucketNameEffective bucket name created in the backend.
-
array of objectsstatus.conditionsPer-component conditions:
BucketReadyand the aggregateReady.-
stringstatus.conditions.lastTransitionTimeTimestamp of the last status transition for this condition.
-
stringstatus.conditions.messageHuman-readable explanation of the current status.
Maximum length:
32768 -
integerstatus.conditions.observedGenerationValue of
metadata.generationthe condition was last set against.Allowed values:
0 <= X -
stringstatus.conditions.reasonMachine-readable reason for the current status, suitable for log filtering.
Length:
1..1024Pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ -
stringstatus.conditions.statusCurrent status of the condition.
Allowed values:
True,False,Unknown -
stringstatus.conditions.typeCondition type, for example
ReadyorBucketReady.Maximum length:
316Pattern:
^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
-
-
stringstatus.endpointIn-cluster S3 endpoint URL of the backing cluster.
-
objectstatus.objectLockObjectLock is the object lock configuration read back from the backend, for the same reason.
-
integerstatus.objectLock.daysDays is the default retention in days, zero when there is no default rule.
-
booleanstatus.objectLock.enabled
Required value
Enabled is true when the bucket has object lock turned on. It stays true even with no default retention rule: the lock cannot be turned off once a bucket has it, and objects already protected stay protected. -
stringstatus.objectLock.modeMode is the default retention mode, empty when the bucket carries object lock but no default rule.
Allowed values:
Governance,Compliance
-
-
integerstatus.observedGenerationMost recent
metadata.generationreconciled by the controller. -
stringstatus.phaseCoarse-grained summary derived from Conditions, plus the one state no condition can express:
Released— the owning Bucket is gone and its reclaim policy wasRetain, so the bucket and its objects are still here with nobody claiming them.Allowed values:
Pending,InProgress,Ready,Released,Error -
stringstatus.versioningVersioning is the versioning state read back from the backend, not a copy of the request: versioning can be turned on by something other than this module, and a copy of the spec would say nothing about that.
Allowed values:
Enabled,Suspended
-
Bucket
Short names: bkt
Scope: Namespaced
Version: v1alpha1
Bucket is what a tenant creates to get a bucket. The controller
provisions a cluster-scoped BucketContents for it in
spec.objectStoreRef, owned by this Bucket and private to this
namespace — the same shape as PersistentVolumeClaim/PersistentVolume.
Binding an already existing bucket is not offered: it needed a policy to say which namespaces may take someone else’s, and that mechanism was removed together with cross-namespace sharing.
Credentials are requested separately with a BucketAccess that
references this Bucket by name in the same namespace.
Deleting it under reclaimPolicy: Retain leaves the BucketContents
behind in phase Released with the data intact; recreating a Bucket
with the same name in the same namespace picks it back up.
-
objectspecDesired state of the bucket.
-
stringspec.accessPolicy
Access policy for the bucket.
Private(default) — accessible only with issued credentials.PublicRead— objects are readable anonymously; writes still require credentials, and listing the bucket is not granted (an anonymous caller must know the object key).
Default:
PrivateAllowed values:
Private,PublicRead -
objectspec.lifecycle
Lifecycle expires objects on a schedule, so a bucket that collects logs or temporary artefacts does not grow without bound and nobody has to remember to empty it.
Expiry only. Moving objects between storage tiers is a lifecycle transition, and SeaweedFS 4.39 implements no transition action at all — its engine compiles expiration, noncurrent expiration, incomplete-upload abort and delete-marker cleanup, and nothing else. A field accepted on one backend and silently ignored on the other is worse than a field that is not there.
-
array of objectsspec.lifecycle.rules
Rules to apply. An empty list removes the bucket’s lifecycle configuration entirely.
Keyed by id: the API server then rejects two rules under one name, and a rule keeps its identity when the list is reordered. Both matter because the id is what the rule is called in the backend — S3 requires it to be unique, and this module recognises a rule by it when deciding whether anything needs writing.
-
integerspec.lifecycle.rules.abortIncompleteUploadsAfterDaysAbortIncompleteUploadsAfterDays removes the parts of a multipart upload that was never completed. Those parts occupy space and appear in no listing, so without this they are storage nobody can see and nobody frees.
Allowed values:
1 <= X -
integerspec.lifecycle.rules.expireAfterDaysExpireAfterDays deletes an object this many days after it was written. On a versioned bucket this makes the current version non-current rather than removing the data; use
expireNoncurrentAfterDaysto reclaim the space.Allowed values:
1 <= X -
integerspec.lifecycle.rules.expireNoncurrentAfterDays
ExpireNoncurrentAfterDays deletes a version this many days after it stopped being current. Only meaningful on a versioned bucket.
Object lock outranks it: a version under an unexpired retention is not deleted, whatever this says.
Allowed values:
1 <= X -
stringspec.lifecycle.rules.id
ID names the rule in the backend, so a rule can be recognised in
aws s3api get-bucket-lifecycle-configurationoutput.Required, and given rather than derived. A name taken from the rule’s position would change under every insertion into the list: the same rule would arrive at the backend under a new name, the old one would be dropped, and a reordering nobody thinks of as a change would rewrite the whole configuration.
Length:
1..255 -
stringspec.lifecycle.rules.prefixPrefix limits the rule to object keys starting with it. Absent, the rule applies to every object in the bucket — which is what makes an accidental
expireAfterDayson a whole bucket worth reading twice.Maximum length:
1024
-
-
-
objectspec.objectLock
ObjectLock makes the bucket write-once-read-many: a version under retention cannot be deleted, by the tenant or by anyone else, until the retention expires.
It requires versioning Enabled, and it is immutable — it can neither be added to an existing bucket nor removed nor retuned. Ceph RGW accepts object lock only when the bucket is created, so a mutable field would mean the same manifest works on one store and fails on another, with nothing in the manifest to say which.
Requesting it forbids reclaimPolicy Delete: a bucket holding protected objects cannot be removed, so that combination would leave the object stuck in Terminating until the last retention lapses.
-
integerspec.objectLock.days
Required value
Days is how long a new object stays protected, in days.
Days rather than a duration because S3 expresses a default retention in whole days or whole years, and years are days without loss of meaning.
Allowed values:
1 <= X -
stringspec.objectLock.mode
Required value
Mode is the retention mode for new objects.Allowed values:
Governance,Compliance
-
-
stringspec.objectStoreRef
Required value
Name of the ObjectStore in which the bucket is provisioned. Immutable after creation.Length:
1..30Pattern:
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ -
objectspec.quota
Optional usage limits for the bucket. Enforcement depends on backend capabilities.
Left empty it takes the
ObjectStoreclass quota, if the class sets one; asking for more than the class allows is rejected by the admission webhook.-
integerspec.quota.maxObjectsMaximum number of objects. 0 (default) means no limit.
Allowed values:
0 <= X -
stringspec.quota.maxSizeMaximum total size as a Kubernetes Quantity (BinarySI), e.g.
10Gi. Omit for no size limit.Pattern:
^[0-9]+(\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E)?$
-
-
stringspec.reclaimPolicy
What happens to the bucket’s data when this Bucket is deleted.
Retain— the bucket and its objects are kept; theBucketContentsstays behind in phaseReleased.Delete— the bucket and all its objects are deleted.
Left empty it takes the
ObjectStoreclass default, which is itselfRetainunless the class says otherwise. There is deliberately no schema default here: a defaultedRetainwould be indistinguishable from a tenant asking forRetain, and the class could then never supply anything else.Allowed values:
Retain,Delete -
stringspec.versioning
Versioning keeps every version of an object instead of overwriting it.
It can be turned on later, but not turned off again once objectLock is set: object lock is built on versions, and both backends refuse to suspend versioning while a bucket is locked.
Default:
SuspendedAllowed values:
Enabled,Suspended
-
-
objectstatusObserved state of the bucket.
-
stringstatus.bucketContentsNameName of the cluster-scoped
BucketContentsthis Bucket owns. The controller derives it, so this is where to read it from. -
array of objectsstatus.conditionsPer-stage conditions:
Bound,ContentsReady, and the aggregateReady.-
stringstatus.conditions.lastTransitionTimeTimestamp of the last status transition for this condition.
-
stringstatus.conditions.messageHuman-readable explanation of the current status.
Maximum length:
32768 -
integerstatus.conditions.observedGenerationValue of
metadata.generationthe condition was last set against.Allowed values:
0 <= X -
stringstatus.conditions.reasonMachine-readable reason for the current status, suitable for log filtering.
Length:
1..1024Pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ -
stringstatus.conditions.statusCurrent status of the condition.
Allowed values:
True,False,Unknown -
stringstatus.conditions.typeCondition type, for example
Ready,Bound, orContentsReady.Maximum length:
316Pattern:
^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
-
-
stringstatus.endpointIn-cluster S3 endpoint URL of the backing ObjectStore.
-
integerstatus.observedGenerationMost recent
metadata.generationreconciled by the controller. -
stringstatus.phaseCoarse-grained summary derived from conditions.
Allowed values:
Pending,InProgress,Ready,Error
-
ObjectStore
Short names: ostore
Scope: Cluster
Version: v1alpha1
ObjectStore is the class tenants consume — the analogue of a
StorageClass. It runs no data plane of its own: it names one store
object through spec.storeRef and the defaults buckets created
against it inherit.
The name of the class is the consumption interface, which is why a
Bucket references it with a plain string: the typed {kind, name}
reference to a backend-specific store is administrator-facing and
stops here.
Several classes may point at the same store with different defaults,
the way several StorageClasses can share one pool.
There is no spec.type: the backend follows from storeRef.kind.
-
objectspecDesired state of the class.
-
objectspec.quotaOptional ceiling for buckets of this class. A
Bucketasking for more than the class allows is rejected by the admission webhook; aBucketasking for nothing gets these values.-
integerspec.quota.maxObjectsMaximum number of objects per bucket.
0(default) means no ceiling.Allowed values:
0 <= X -
stringspec.quota.maxSizeMaximum total size per bucket as a Kubernetes Quantity (BinarySI), e.g.
100Gi. Omit for no size ceiling.Pattern:
^[0-9]+(\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E)?$
-
-
stringspec.reclaimPolicy
Default a
Bucketof this class gets when it sets none of its own.Retain(default) — a deletedBucketleaves itsBucketContentsbehind in phaseReleasedwith the data intact.Delete— the bucket and all its objects are deleted with theBucket.
Default:
RetainAllowed values:
Retain,Delete -
objectspec.storeRef
Required value
The store object providing the data plane.
Immutable after creation.
-
stringspec.storeRef.kind
Required value
Kind of the store object, e.g.
SeaweedFSStoreorSDSElasticStore.Deliberately not an enum here: adding a backend would then mean editing this CRD — the very coupling per-Kind stores remove — and every class in the cluster is validated by this schema. The admission webhook checks the value against the store Kinds the module implements, and the controller’s driver registry is the runtime authority: a Kind with no driver reconciles nothing.
Length:
1..63 -
stringspec.storeRef.name
Required value
Name of the store object.Length:
1..30Pattern:
^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
-
-
-
objectstatusObserved state of the class.
-
objectstatus.backendEngine behind the referenced store, resolved from
storeRef.kind. A copy, saving a reader of the class one lookup; the store object remains the source of truth.-
stringstatus.backend.typeBackend engine.
Allowed values:
SeaweedFS,CephRGW -
stringstatus.backend.versionRunning backend version.
-
-
array of objectsstatus.conditionsPer-stage conditions:
StoreResolved,StoreReady, and the aggregateReady.-
stringstatus.conditions.lastTransitionTimeTimestamp of the last status transition for this condition.
-
stringstatus.conditions.messageHuman-readable explanation of the current status.
Maximum length:
32768 -
integerstatus.conditions.observedGenerationValue of
metadata.generationthe condition was last set against.Allowed values:
0 <= X -
stringstatus.conditions.reasonMachine-readable reason for the current status, suitable for log filtering.
Length:
1..1024Pattern:
^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ -
stringstatus.conditions.statusCurrent status of the condition.
Allowed values:
True,False,Unknown -
stringstatus.conditions.typeCondition type, for example
Ready,StoreResolved, orStoreReady.Maximum length:
316Pattern:
^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
-
-
objectstatus.endpointS3 endpoint of the referenced store. A copy, as above.
-
stringstatus.endpoint.externalExternal is the S3 endpoint URL reachable from outside the cluster, set only while the store is published (spec.publish). Empty is the honest answer for an unpublished store: there is no address to hand out.
-
stringstatus.endpoint.internalIn-cluster S3 endpoint URL (Service DNS).
-
stringstatus.endpoint.regionDefault S3 region advertised by the endpoint.
-
-
integerstatus.observedGenerationMost recent
metadata.generationreconciled by the controller. -
stringstatus.phaseCoarse-grained summary derived from Conditions.
Readymeansspec.storeRefresolves and that store is itself Ready.Allowed values:
Pending,InProgress,Ready,Error
-