The module lifecycle stageExperimental

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.

  • spec
    object
    Desired state of the store.
    • spec.dataPool
      object

      Durability of the pool holding object data, in Ceph’s own terms: exactly one of replicated or erasureCoded. Defaults to replicated with size 3.

      This is where the removal of the None/Standard/High intent shows most clearly: erasure coding is a (k, m) pair, and no replica count expresses it.

      • spec.dataPool.erasureCoded
        object
        Every object split into data and coding chunks, trading CPU and latency for usable capacity.
        • spec.dataPool.erasureCoded.codingChunks
          integer

          Required value

          m: how many coding chunks are computed, and therefore how many failures the pool survives. k + m failure domains are needed to place them.

          Allowed values: 1 <= X

        • spec.dataPool.erasureCoded.dataChunks
          integer

          Required value

          k: how many data chunks each object is split into.

          Allowed values: 2 <= X

      • spec.dataPool.replicated
        object
        Whole copies of every object.
        • spec.dataPool.replicated.size
          integer

          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

    • spec.elasticClusterRef
      string

      Required value

      Name of the ElasticCluster (sds-elastic) whose Ceph cluster hosts the RGW pools. Immutable after creation.

      Length: 1..30

      Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$

    • spec.encryption
      object

      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.

      • spec.encryption.mode
        string

        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: Disabled

        Allowed values: Disabled, ServerManaged

      • spec.encryption.stronghold
        object

        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.

        • spec.encryption.stronghold.address
          string

          Required value

          Address of the Stronghold API, for example https://stronghold.d8-stronghold.svc.cluster.local:8200.

          Minimal length: 1

          Pattern: ^https?://

        • spec.encryption.stronghold.caSecretRef
          object
          Secret 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).
          • spec.encryption.stronghold.caSecretRef.name
            string

            Required value

            Minimal length: 1

        • spec.encryption.stronghold.tokenSecretRef
          object

          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.

          • spec.encryption.stronghold.tokenSecretRef.name
            string

            Required value

            Minimal length: 1

    • spec.gateway
      object
      The RGW serving layer.
      • spec.gateway.instances
        integer
        Number of RGW daemons serving S3. Defaults to 1.

        Allowed values: 1 <= X

    • spec.metadataPool
      object
      Durability 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.
      • spec.metadataPool.size
        integer

        Required value

        Number of copies kept, including the primary.

        Allowed values: 2 <= X

    • spec.publish
      object

      Exposes this store’s S3 endpoint outside the cluster, through the Gateway API implementation of the alb module. Unset (the default) means in-cluster only.

      The Gateway is not created here: an administrator or a team owns it, through ALBInstance or ClusterALBInstance. This module only attaches a route to it. Attaching a route from another namespace is permitted on the target side (a ReferenceGrant in the Gateway’s namespace, or the listener’s allowedRoutes); if it is not permitted, the store says so in its conditions instead of trying to grant itself access.

      • spec.publish.addressing
        string

        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.
        • VirtualHostedhttps://<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: PathStyle

        Allowed values: PathStyle, VirtualHosted

      • spec.publish.gatewayRef
        object

        Required value

        The Gateway to attach the route to. The namespace is part of the reference because a shared Gateway lives in the alb controller’s namespace, not next to the store.
        • spec.publish.gatewayRef.name
          string

          Required value

          Name of the Gateway.

          Length: 1..253

        • spec.publish.gatewayRef.namespace
          string

          Required value

          Namespace the Gateway lives in.

          Length: 1..63

      • spec.publish.hostname
        string

        Required value

        Hostname the published endpoint answers on, for example s3.example.com. A wildcard (*.s3.example.com) is required for VirtualHosted addressing and rejected for PathStyle.

        Length: 1..253

        Pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+$

      • spec.publish.tls
        object

        Required value

        Server certificate for the published endpoint. Required: SigV4 credentials travel in the Authorization header, so publishing over plain HTTP would hand the bucket to anyone who can see the traffic. There is deliberately no insecure escape hatch.
        • spec.publish.tls.secretRef
          object

          Required value

          A kubernetes.io/tls Secret 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.
          • spec.publish.tls.secretRef.name
            string

            Required value

            Name of the TLS Secret.

            Length: 1..253

    • spec.reclaimPolicy
      string

      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. The CephObjectStore itself is still removed: leaving it behind would keep the Ceph cluster in use and block the ElasticCluster from ever being deleted.
      • Delete — the RGW pools, and every object in them, are destroyed.

      Immutable after creation.

      Default: Retain

      Allowed values: Retain, Delete

  • status
    object
    Observed state of the store.
    • status.adminSecretRef
      object

      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.

      • status.adminSecretRef.name
        string
    • status.backend
      object
      Engine behind this store and its running version.
      • status.backend.type
        string
        Backend engine.

        Allowed values: SeaweedFS, CephRGW

      • status.backend.version
        string
        Running backend version.
    • status.capacity
      object
      Store-wide storage usage reported by the backend.
      • status.capacity.available
        string
        Free capacity, Kubernetes Quantity (BinarySI).
      • status.capacity.lastUpdated
        string
        Timestamp of the latest capacity probe.
      • status.capacity.total
        string
        Total usable capacity, Kubernetes Quantity (BinarySI).
      • status.capacity.used
        string
        Consumed capacity, Kubernetes Quantity (BinarySI).
      • status.capacity.usedPercent
        string
        used / total * 100, formatted with two decimals.
    • status.conditions
      array of objects
      Per-stage conditions: BackendReady, EndpointReady, and the aggregate Ready.
      • status.conditions.lastTransitionTime
        string
        Timestamp of the last status transition for this condition.
      • status.conditions.message
        string
        Human-readable explanation of the current status.

        Maximum length: 32768

      • status.conditions.observedGeneration
        integer
        Value of metadata.generation the condition was last set against.

        Allowed values: 0 <= X

      • status.conditions.reason
        string
        Machine-readable reason for the current status, suitable for log filtering.

        Length: 1..1024

        Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

      • status.conditions.status
        string
        Current status of the condition.

        Allowed values: True, False, Unknown

      • status.conditions.type
        string
        Condition type, for example Ready, BackendReady, or EndpointReady.

        Maximum length: 316

        Pattern: ^([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])$

    • status.encryption
      object

      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.

      • status.encryption.keyFingerprint
        string
        Not published by this backend — see above.
      • status.encryption.message
        string
        Why the mode in force is not the one the spec asks for.
      • status.encryption.mode
        string
        What 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

      • status.encryption.since
        string
        When this mode took effect.
    • status.endpoint
      object
      S3 endpoint clients use to reach this store.
      • status.endpoint.external
        string
        S3 endpoint URL reachable from outside the cluster, set only while spec.publish is in effect. Empty for an unpublished store: there is no external address to hand out.
      • status.endpoint.internal
        string
        In-cluster S3 endpoint URL (Service DNS), e.g. http://default-seaweedfs.d8-sds-object.svc.cluster.local:8333.
      • status.endpoint.region
        string
        Default S3 region advertised by the endpoint.
    • status.integrity
      object

      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.

      • status.integrity.damaged
        integer
        How many units were found damaged.
      • status.integrity.details
        array of strings
        The 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.
      • status.integrity.lastScrubTime
        string
        When the reported result was produced.
      • status.integrity.repaired
        integer
        How many of them the module put right. Kept apart from damaged on purpose: “something was damaged and we fixed it” is not an alarm.
      • status.integrity.scanned
        object
        How much the check covered.
        • status.integrity.scanned.objects
          integer
          Stored items examined, where the backend counts them.
        • status.integrity.scanned.volumes
          integer
          Storage units examined — SeaweedFS volumes, Ceph placement groups.
      • status.integrity.source
        string

        Who performed the check.

        Always Backend here: 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

      • status.integrity.unreachable
        integer

        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 leaves IntegrityHealthy Unknown rather than True.

    • status.observedGeneration
      integer
      Most recent metadata.generation reconciled by the controller.
    • status.phase
      string
      Coarse-grained summary derived from Conditions.

      Allowed values: Pending, InProgress, Ready, Error

    • status.redundancy
      object

      Whether the data has as many copies as the spec asks for.

      Reported apart from integrity because 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.

      • status.redundancy.copiesWanted
        integer
        How many copies of each unit of storage the replication setting calls for, the original included.
      • status.redundancy.details
        array of strings
        Which volumes are short and by how much, bounded in number.
      • status.redundancy.lastCheckTime
        string
        When 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.
      • status.redundancy.underReplicated
        integer
        How many of them have fewer copies than asked for.
      • status.redundancy.volumes
        integer
        How 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.

  • spec
    object
    Desired state of the store.
    • spec.encryption
      object

      Server-side encryption of the stored object data.

      Unset means objects are written as they arrive: whoever holds the disk reads them. With ServerManaged the 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.

      • spec.encryption.keySecretRef
        object

        Secret in the module namespace holding the wrapping key, under one of two keys: kek (32 bytes hex-encoded, used directly) or key (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.

        • spec.encryption.keySecretRef.name
          string

          Required value

          Minimal length: 1

      • spec.encryption.mode
        string

        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 from keySecretRef. 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: Disabled

        Allowed values: Disabled, ServerManaged

    • spec.externalMetadataStore
      object
      Connection details of the PostgreSQL to use with metadataStore: External. Required with it, refused without it.
      • spec.externalMetadataStore.secretRef
        object

        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, 5432 when 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, require when absent. disable sends 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, require encrypts 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 yaml and in every backup of the cluster’s resources.

        • spec.externalMetadataStore.secretRef.name
          string

          Required value

          Name of the Secret.

          Length: 1..253

    • spec.filers
      integer
      Number of filer servers, each also serving the S3 gateway. More than one requires metadataStore: Postgres. Defaults to 1.

      Default: 1

      Allowed values: 1 <= X

    • spec.integrity
      object

      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.

      SDSElasticStore has no such field: Ceph scrubs on its own schedule, and the module only reports what it finds.

      • spec.integrity.autoRepair
        boolean

        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

      • spec.integrity.enabled
        boolean
        Turns 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

      • spec.integrity.interval
        string

        How often to scrub. Defaults to 168h (weekly), and values below 1h are raised to it.

        The default is deliberately conservative: a Full scrub 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.

      • spec.integrity.mode
        string

        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: Full

        Allowed values: Index, Full

    • spec.masters
      integer
      Number of master servers. Masters hold a Raft quorum, so an odd count is what makes sense: 1 for a store that may go down with its node, 3 for one that must not. Defaults to 3.

      Default: 3

      Allowed values: 1 <= X

    • spec.metadataStore
      string

      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 by externalMetadataStore. Same capability as Postgres and 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: LevelDB

      Allowed values: LevelDB, Postgres, External

    • spec.placement
      object
      Scheduling of the store’s data plane.
      • spec.placement.nodeSelector
        object
        Node labels the data-plane Pods must match (same semantics as a Pod’s spec.nodeSelector).
      • spec.placement.tolerations
        array of objects
        Tolerations for the data-plane Pods (same shape as a Pod’s spec.tolerations).
        • spec.placement.tolerations.effect
          string

          Allowed values: ‘’, NoSchedule, PreferNoSchedule, NoExecute

        • spec.placement.tolerations.key
          string
        • spec.placement.tolerations.operator
          string

          Allowed values: Exists, Equal

        • spec.placement.tolerations.tolerationSeconds
          integer
        • spec.placement.tolerations.value
          string
    • spec.postgresClassName
      string

      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.placement cannot reach them — tolerations, nodeSelector and nodeAffinity are 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

    • spec.publish
      object

      Exposes this store’s S3 endpoint outside the cluster, through the Gateway API implementation of the alb module. Unset (the default) means in-cluster only.

      The Gateway is not created here: an administrator or a team owns it, through ALBInstance or ClusterALBInstance. This module only attaches a route to it. Attaching a route from another namespace is permitted on the target side (a ReferenceGrant in the Gateway’s namespace, or the listener’s allowedRoutes); if it is not permitted, the store says so in its conditions instead of trying to grant itself access.

      • spec.publish.addressing
        string

        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.
        • VirtualHostedhttps://<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: PathStyle

        Allowed values: PathStyle, VirtualHosted

      • spec.publish.gatewayRef
        object

        Required value

        The Gateway to attach the route to. The namespace is part of the reference because a shared Gateway lives in the alb controller’s namespace, not next to the store.
        • spec.publish.gatewayRef.name
          string

          Required value

          Name of the Gateway.

          Length: 1..253

        • spec.publish.gatewayRef.namespace
          string

          Required value

          Namespace the Gateway lives in.

          Length: 1..63

      • spec.publish.hostname
        string

        Required value

        Hostname the published endpoint answers on, for example s3.example.com. A wildcard (*.s3.example.com) is required for VirtualHosted addressing and rejected for PathStyle.

        Length: 1..253

        Pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+$

      • spec.publish.tls
        object

        Required value

        Server certificate for the published endpoint. Required: SigV4 credentials travel in the Authorization header, so publishing over plain HTTP would hand the bucket to anyone who can see the traffic. There is deliberately no insecure escape hatch.
        • spec.publish.tls.secretRef
          object

          Required value

          A kubernetes.io/tls Secret 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.
          • spec.publish.tls.secretRef.name
            string

            Required value

            Name of the TLS Secret.

            Length: 1..253

    • spec.reclaimPolicy
      string

      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: Retain

      Allowed values: Retain, Delete

    • spec.replication
      string

      SeaweedFS’s own three-digit replication code xyz: copies on other data centres, other racks, and other servers in the same rack. 000 keeps a single copy, 001 one extra copy on another server, 002 two. Defaults to 001.

      Only 00z is 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: 001

      Pattern: ^[0-9]{3}$

    • spec.storage
      object

      Required value

      PVCs backing the data plane.
      • spec.storage.class
        string

        Required value

        Name of the Kubernetes StorageClass used to provision PVCs. Immutable after creation.

        Length: 1..253

      • spec.storage.sizePerNode
        string
        Capacity provisioned per volume server as a Kubernetes Quantity (BinarySI), e.g. 50Gi or 2Ti. The store-wide capacity is roughly sizePerNode times volumeServers. Defaults to 10Gi.

        Pattern: ^[0-9]+(\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|k|M|G|T|P|E)?$

    • spec.volumeServers
      integer
      Number 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 to 3.

      Default: 3

      Allowed values: 1 <= X

  • status
    object
    Observed state of the store.
    • status.adminSecretRef
      object

      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.

      • status.adminSecretRef.name
        string
    • status.backend
      object
      Engine behind this store and its running version.
      • status.backend.type
        string
        Backend engine.

        Allowed values: SeaweedFS, CephRGW

      • status.backend.version
        string
        Running backend version.
    • status.capacity
      object
      Store-wide storage usage reported by the backend.
      • status.capacity.available
        string
        Free capacity, Kubernetes Quantity (BinarySI).
      • status.capacity.lastUpdated
        string
        Timestamp of the latest capacity probe.
      • status.capacity.total
        string
        Total usable capacity, Kubernetes Quantity (BinarySI).
      • status.capacity.used
        string
        Consumed capacity, Kubernetes Quantity (BinarySI).
      • status.capacity.usedPercent
        string
        used / total * 100, formatted with two decimals.
    • status.conditions
      array of objects
      Per-stage conditions: BackendReady, EndpointReady, and the aggregate Ready.
      • status.conditions.lastTransitionTime
        string
        Timestamp of the last status transition for this condition.
      • status.conditions.message
        string
        Human-readable explanation of the current status.

        Maximum length: 32768

      • status.conditions.observedGeneration
        integer
        Value of metadata.generation the condition was last set against.

        Allowed values: 0 <= X

      • status.conditions.reason
        string
        Machine-readable reason for the current status, suitable for log filtering.

        Length: 1..1024

        Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

      • status.conditions.status
        string
        Current status of the condition.

        Allowed values: True, False, Unknown

      • status.conditions.type
        string
        Condition type, for example Ready, BackendReady, or EndpointReady.

        Maximum length: 316

        Pattern: ^([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])$

    • status.encryption
      object

      What is actually encrypting the stored data, and with which key.

      keyFingerprint is 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.

      • status.encryption.keyFingerprint
        string
        Identifies 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.
      • status.encryption.message
        string
        Why the mode in force is not the one the spec asks for.
      • status.encryption.mode
        string
        What 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

      • status.encryption.since
        string
        When this mode and key took effect.
    • status.endpoint
      object
      S3 endpoint clients use to reach this store.
      • status.endpoint.external
        string
        S3 endpoint URL reachable from outside the cluster, set only while spec.publish is in effect. Empty for an unpublished store: there is no external address to hand out.
      • status.endpoint.internal
        string
        In-cluster S3 endpoint URL (Service DNS), e.g. http://default-seaweedfs.d8-sds-object.svc.cluster.local:8333.
      • status.endpoint.region
        string
        Default S3 region advertised by the endpoint.
    • status.integrity
      object

      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.

      • status.integrity.damaged
        integer
        How many units were found damaged.
      • status.integrity.details
        array of strings
        The 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.
      • status.integrity.lastScrubTime
        string
        When the reported result was produced.
      • status.integrity.repaired
        integer
        How many of them the module put right. Kept apart from damaged on purpose: “something was damaged and we fixed it” is not an alarm.
      • status.integrity.scanned
        object
        How much the check covered.
        • status.integrity.scanned.objects
          integer
          Stored items examined, where the backend counts them.
        • status.integrity.scanned.volumes
          integer
          Storage units examined — SeaweedFS volumes, Ceph placement groups.
      • status.integrity.source
        string

        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

      • status.integrity.unreachable
        integer

        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 leaves IntegrityHealthy Unknown rather than True.

    • status.observedGeneration
      integer
      Most recent metadata.generation reconciled by the controller.
    • status.phase
      string
      Coarse-grained summary derived from Conditions.

      Allowed values: Pending, InProgress, Ready, Error

    • status.redundancy
      object

      Whether the data has as many copies as the spec asks for.

      Reported apart from integrity because 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.

      • status.redundancy.copiesWanted
        integer
        How many copies of each unit of storage the replication setting calls for, the original included.
      • status.redundancy.details
        array of strings
        Which volumes are short and by how much, bounded in number.
      • status.redundancy.lastCheckTime
        string
        When 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.
      • status.redundancy.underReplicated
        integer
        How many of them have fewer copies than asked for.
      • status.redundancy.volumes
        integer
        How 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).

  • spec
    object
    Desired state of the access.
    • spec.bucketRef
      string

      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..253

      Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$

    • spec.credentialsSecretName
      string
      Overrides the name of the credentials Secret written in this access’s namespace. Defaults to <metadata.name>-s3-credentials.

      Length: 1..253

    • spec.endpointScope
      string

      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

    • spec.permission
      string

      Access level granted to the issued credentials.

      • ReadWrite (default) — read and write objects.
      • ReadOnly — read objects only.

      Default: ReadWrite

      Allowed values: ReadWrite, ReadOnly

  • status
    object
    Observed state of the access.
    • status.accessKeyID
      string
      Public access key id issued for this access (the secret key is only written into the credentials Secret).
    • status.bucketName
      string
      Effective bucket name the access is scoped to.
    • status.conditions
      array of objects
      Per-component conditions: AccessGranted, CredentialsReady, and the aggregate Ready.
      • status.conditions.lastTransitionTime
        string
        Timestamp of the last status transition for this condition.
      • status.conditions.message
        string
        Human-readable explanation of the current status.

        Maximum length: 32768

      • status.conditions.observedGeneration
        integer
        Value of metadata.generation the condition was last set against.

        Allowed values: 0 <= X

      • status.conditions.reason
        string
        Machine-readable reason for the current status, suitable for log filtering.

        Length: 1..1024

        Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

      • status.conditions.status
        string
        Current status of the condition.

        Allowed values: True, False, Unknown

      • status.conditions.type
        string
        Condition type, for example Ready, AccessGranted, or CredentialsReady.

        Maximum length: 316

        Pattern: ^([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])$

    • status.endpoint
      string
      In-cluster S3 endpoint URL of the backing cluster.
    • status.lastRotationTime
      string
      Timestamp of the most recent key issuance.
    • status.observedGeneration
      integer
      Most recent metadata.generation reconciled by the controller.
    • status.observedRotation
      string
      Last value of the storage.deckhouse.io/rotate annotation processed by the controller.
    • status.phase
      string
      Coarse-grained summary derived from Conditions.

      Allowed values: Pending, InProgress, Ready, Error

    • status.secretRef
      object
      Reference 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.
      • status.secretRef.name
        string

        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.

  • spec
    object
    Desired state of the bucket.
    • spec.accessPolicy
      string

      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: Private

      Allowed values: Private, PublicRead

    • spec.bucketName
      string
      Name of the bucket in S3. Defaults to metadata.name when omitted. Must follow S3 bucket naming rules. Immutable after creation.

      Length: 3..63

      Pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$

    • spec.bucketRef
      object

      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 Released object 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.

      • spec.bucketRef.name
        string

        Required value

        Name of the owning Bucket.

        Length: 1..253

      • spec.bucketRef.namespace
        string

        Required value

        Namespace of the owning Bucket.

        Length: 1..253

    • spec.lifecycle
      object
      Lifecycle 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.
      • spec.lifecycle.rules
        array of objects

        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.

        • spec.lifecycle.rules.abortIncompleteUploadsAfterDays
          integer
          AbortIncompleteUploadsAfterDays 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

        • spec.lifecycle.rules.expireAfterDays
          integer
          ExpireAfterDays 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 expireNoncurrentAfterDays to reclaim the space.

          Allowed values: 1 <= X

        • spec.lifecycle.rules.expireNoncurrentAfterDays
          integer

          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

        • spec.lifecycle.rules.id
          string

          ID names the rule in the backend, so a rule can be recognised in aws s3api get-bucket-lifecycle-configuration output.

          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

        • spec.lifecycle.rules.prefix
          string
          Prefix 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 expireAfterDays on a whole bucket worth reading twice.

          Maximum length: 1024

    • spec.objectLock
      object
      ObjectLock mirrors the owning Bucket’s object lock request. Immutable, for the reason given on Bucket: the backend accepts it only at creation.
      • spec.objectLock.days
        integer

        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

      • spec.objectLock.mode
        string

        Required value

        Mode is the retention mode for new objects.

        Allowed values: Governance, Compliance

    • spec.quota
      object
      Optional usage limits for the bucket. Enforcement depends on backend capabilities.
      • spec.quota.maxObjects
        integer
        Maximum number of objects. 0 (default) means no limit.

        Allowed values: 0 <= X

      • spec.quota.maxSize
        string
        Maximum 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)?$

    • spec.reclaimPolicy
      string

      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: Retain

      Allowed values: Retain, Delete

    • spec.storeRef
      object

      Required value

      The store holding this bucket. The controller resolves it from the owning Bucket’s ObjectStore class and writes it here; the store must exist and be Ready before 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.

      • spec.storeRef.kind
        string

        Required value

        Kind of the store object, e.g. SeaweedFSStore.

        Length: 1..63

      • spec.storeRef.name
        string

        Required value

        Name of the store object.

        Length: 1..30

        Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$

    • spec.versioning
      string
      Versioning mirrors the owning Bucket’s versioning request.

      Default: Suspended

      Allowed values: Enabled, Suspended

  • status
    object
    Observed state of the bucket.
    • status.bucketName
      string
      Effective bucket name created in the backend.
    • status.conditions
      array of objects
      Per-component conditions: BucketReady and the aggregate Ready.
      • status.conditions.lastTransitionTime
        string
        Timestamp of the last status transition for this condition.
      • status.conditions.message
        string
        Human-readable explanation of the current status.

        Maximum length: 32768

      • status.conditions.observedGeneration
        integer
        Value of metadata.generation the condition was last set against.

        Allowed values: 0 <= X

      • status.conditions.reason
        string
        Machine-readable reason for the current status, suitable for log filtering.

        Length: 1..1024

        Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

      • status.conditions.status
        string
        Current status of the condition.

        Allowed values: True, False, Unknown

      • status.conditions.type
        string
        Condition type, for example Ready or BucketReady.

        Maximum length: 316

        Pattern: ^([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])$

    • status.endpoint
      string
      In-cluster S3 endpoint URL of the backing cluster.
    • status.objectLock
      object
      ObjectLock is the object lock configuration read back from the backend, for the same reason.
      • status.objectLock.days
        integer
        Days is the default retention in days, zero when there is no default rule.
      • status.objectLock.enabled
        boolean

        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.
      • status.objectLock.mode
        string
        Mode is the default retention mode, empty when the bucket carries object lock but no default rule.

        Allowed values: Governance, Compliance

    • status.observedGeneration
      integer
      Most recent metadata.generation reconciled by the controller.
    • status.phase
      string
      Coarse-grained summary derived from Conditions, plus the one state no condition can express: Released — the owning Bucket is gone and its reclaim policy was Retain, so the bucket and its objects are still here with nobody claiming them.

      Allowed values: Pending, InProgress, Ready, Released, Error

    • status.versioning
      string
      Versioning 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.

  • spec
    object
    Desired state of the bucket.
    • spec.accessPolicy
      string

      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: Private

      Allowed values: Private, PublicRead

    • spec.lifecycle
      object

      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.

      • spec.lifecycle.rules
        array of objects

        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.

        • spec.lifecycle.rules.abortIncompleteUploadsAfterDays
          integer
          AbortIncompleteUploadsAfterDays 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

        • spec.lifecycle.rules.expireAfterDays
          integer
          ExpireAfterDays 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 expireNoncurrentAfterDays to reclaim the space.

          Allowed values: 1 <= X

        • spec.lifecycle.rules.expireNoncurrentAfterDays
          integer

          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

        • spec.lifecycle.rules.id
          string

          ID names the rule in the backend, so a rule can be recognised in aws s3api get-bucket-lifecycle-configuration output.

          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

        • spec.lifecycle.rules.prefix
          string
          Prefix 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 expireAfterDays on a whole bucket worth reading twice.

          Maximum length: 1024

    • spec.objectLock
      object

      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.

      • spec.objectLock.days
        integer

        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

      • spec.objectLock.mode
        string

        Required value

        Mode is the retention mode for new objects.

        Allowed values: Governance, Compliance

    • spec.objectStoreRef
      string

      Required value

      Name of the ObjectStore in which the bucket is provisioned. Immutable after creation.

      Length: 1..30

      Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$

    • spec.quota
      object

      Optional usage limits for the bucket. Enforcement depends on backend capabilities.

      Left empty it takes the ObjectStore class quota, if the class sets one; asking for more than the class allows is rejected by the admission webhook.

      • spec.quota.maxObjects
        integer
        Maximum number of objects. 0 (default) means no limit.

        Allowed values: 0 <= X

      • spec.quota.maxSize
        string
        Maximum 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)?$

    • spec.reclaimPolicy
      string

      What happens to the bucket’s data when this Bucket is deleted.

      • Retain — the bucket and its objects are kept; the BucketContents stays behind in phase Released.
      • Delete — the bucket and all its objects are deleted.

      Left empty it takes the ObjectStore class default, which is itself Retain unless the class says otherwise. There is deliberately no schema default here: a defaulted Retain would be indistinguishable from a tenant asking for Retain, and the class could then never supply anything else.

      Allowed values: Retain, Delete

    • spec.versioning
      string

      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: Suspended

      Allowed values: Enabled, Suspended

  • status
    object
    Observed state of the bucket.
    • status.bucketContentsName
      string
      Name of the cluster-scoped BucketContents this Bucket owns. The controller derives it, so this is where to read it from.
    • status.conditions
      array of objects
      Per-stage conditions: Bound, ContentsReady, and the aggregate Ready.
      • status.conditions.lastTransitionTime
        string
        Timestamp of the last status transition for this condition.
      • status.conditions.message
        string
        Human-readable explanation of the current status.

        Maximum length: 32768

      • status.conditions.observedGeneration
        integer
        Value of metadata.generation the condition was last set against.

        Allowed values: 0 <= X

      • status.conditions.reason
        string
        Machine-readable reason for the current status, suitable for log filtering.

        Length: 1..1024

        Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

      • status.conditions.status
        string
        Current status of the condition.

        Allowed values: True, False, Unknown

      • status.conditions.type
        string
        Condition type, for example Ready, Bound, or ContentsReady.

        Maximum length: 316

        Pattern: ^([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])$

    • status.endpoint
      string
      In-cluster S3 endpoint URL of the backing ObjectStore.
    • status.observedGeneration
      integer
      Most recent metadata.generation reconciled by the controller.
    • status.phase
      string
      Coarse-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.

  • spec
    object
    Desired state of the class.
    • spec.quota
      object
      Optional ceiling for buckets of this class. A Bucket asking for more than the class allows is rejected by the admission webhook; a Bucket asking for nothing gets these values.
      • spec.quota.maxObjects
        integer
        Maximum number of objects per bucket. 0 (default) means no ceiling.

        Allowed values: 0 <= X

      • spec.quota.maxSize
        string
        Maximum 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)?$

    • spec.reclaimPolicy
      string

      Default a Bucket of this class gets when it sets none of its own.

      • Retain (default) — a deleted Bucket leaves its BucketContents behind in phase Released with the data intact.
      • Delete — the bucket and all its objects are deleted with the Bucket.

      Default: Retain

      Allowed values: Retain, Delete

    • spec.storeRef
      object

      Required value

      The store object providing the data plane.

      Immutable after creation.

      • spec.storeRef.kind
        string

        Required value

        Kind of the store object, e.g. SeaweedFSStore or SDSElasticStore.

        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

      • spec.storeRef.name
        string

        Required value

        Name of the store object.

        Length: 1..30

        Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$

  • status
    object
    Observed state of the class.
    • status.backend
      object
      Engine 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.
      • status.backend.type
        string
        Backend engine.

        Allowed values: SeaweedFS, CephRGW

      • status.backend.version
        string
        Running backend version.
    • status.conditions
      array of objects
      Per-stage conditions: StoreResolved, StoreReady, and the aggregate Ready.
      • status.conditions.lastTransitionTime
        string
        Timestamp of the last status transition for this condition.
      • status.conditions.message
        string
        Human-readable explanation of the current status.

        Maximum length: 32768

      • status.conditions.observedGeneration
        integer
        Value of metadata.generation the condition was last set against.

        Allowed values: 0 <= X

      • status.conditions.reason
        string
        Machine-readable reason for the current status, suitable for log filtering.

        Length: 1..1024

        Pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$

      • status.conditions.status
        string
        Current status of the condition.

        Allowed values: True, False, Unknown

      • status.conditions.type
        string
        Condition type, for example Ready, StoreResolved, or StoreReady.

        Maximum length: 316

        Pattern: ^([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])$

    • status.endpoint
      object
      S3 endpoint of the referenced store. A copy, as above.
      • status.endpoint.external
        string
        External 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.
      • status.endpoint.internal
        string
        In-cluster S3 endpoint URL (Service DNS).
      • status.endpoint.region
        string
        Default S3 region advertised by the endpoint.
    • status.observedGeneration
      integer
      Most recent metadata.generation reconciled by the controller.
    • status.phase
      string
      Coarse-grained summary derived from Conditions. Ready means spec.storeRef resolves and that store is itself Ready.

      Allowed values: Pending, InProgress, Ready, Error