Storage Pools

Configure SeaweedFS storage pools for tiered object storage

Storage pools let you partition SeaweedFS volume servers by disk type. Each pool creates a separate Volume StatefulSet tagged with a SeaweedFS diskType, and a matching set of COSI resources (BucketClasses and BucketAccessClasses) that buckets can reference.

When to Use Pools

Use storage pools when your cluster has different storage tiers and you want to control which tier a bucket uses. For example, you might have fast NVMe drives for hot data and large HDD drives for archival storage.

If all your volume servers use the same storage, you do not need pools – the default BucketClass is sufficient.

Enabling SeaweedFS on a Tenant

Before configuring pools, enable SeaweedFS on the tenant:

kubectl patch -n tenant-root tenants.apps.cozystack.io root --type=merge -p '{
  "spec":{
    "seaweedfs": true
  }
}'

Wait for the SeaweedFS HelmRelease to become ready:

kubectl -n tenant-root get hr seaweedfs

Expected output:

NAME        AGE   READY   STATUS
seaweedfs   2m    True    Helm upgrade succeeded for release tenant-root/seaweedfs.v1 with chart seaweedfs@...

Pool Configuration

Once SeaweedFS is running, patch its HelmRelease to add storage pools:

kubectl patch -n tenant-root helmreleases.helm.toolkit.fluxcd.io seaweedfs --type=merge -p '{
  "spec":{
    "values":{
      "volume":{
        "pools":{
          "ssd":{
            "diskType": "ssd",
            "size": "50Gi",
            "storageClass": "local-nvme"
          },
          "hdd":{
            "diskType": "hdd",
            "size": "500Gi",
            "storageClass": "local-hdd",
            "replicas": 3
          }
        }
      }
    }
  }
}'

The equivalent full resource looks like this:

apiVersion: apps.cozystack.io/v1alpha1
kind: SeaweedFS
metadata:
  name: seaweedfs
  namespace: tenant-example
spec:
  host: s3.example.com
  topology: Simple
  volume:
    replicas: 2
    size: 100Gi
    pools:
      ssd:
        diskType: ssd
        size: 50Gi
        storageClass: local-nvme
      hdd:
        diskType: hdd
        size: 500Gi
        storageClass: local-hdd
        replicas: 3

Pool Parameters

ParameterRequiredDescription
diskTypeYesSeaweedFS disk type tag (lowercase alphanumeric, e.g. ssd, hdd, nvme)
replicasNoNumber of volume server replicas. Defaults to volume.replicas
sizeNoPVC size per replica. Defaults to volume.size
storageClassNoKubernetes StorageClass for PVCs. Defaults to volume.storageClass
resourcesNoExplicit CPU/memory limits. Defaults to volume.resources
resourcesPresetNoSizing preset when resources is omitted. Defaults to volume.resourcesPreset

Naming Rules

Pool names must be valid DNS labels (lowercase letters, digits, hyphens). The following suffixes are reserved and must not be used as pool names:

  • Names ending in -lock (reserved for object-lock BucketClasses)
  • Names ending in -readonly (reserved for read-only BucketAccessClasses)

COSI Resources Created per Pool

Each pool automatically creates four COSI resources:

ResourceName PatternPurpose
BucketClass{namespace}-{pool}Standard bucket provisioning
BucketClass{namespace}-{pool}-lockBucket provisioning with object locking enabled
BucketAccessClass{namespace}-{pool}Read-write credentials
BucketAccessClass{namespace}-{pool}-readonlyRead-only credentials

For example, a pool named ssd in namespace tenant-example creates:

  • BucketClass tenant-example-ssd
  • BucketClass tenant-example-ssd-lock
  • BucketAccessClass tenant-example-ssd
  • BucketAccessClass tenant-example-ssd-readonly

MultiZone Topology with Pools

In MultiZone topology, pools are defined per zone under volume.zones[zone].pools.

Zone Parameters

Each zone accepts the following parameters in addition to pools:

ParameterRequiredDescription
replicasNoNumber of volume server replicas in this zone. Defaults to volume.replicas
sizeNoPVC size per replica. Defaults to volume.size
storageClassNoKubernetes StorageClass for PVCs. Defaults to volume.storageClass
dataCenterNoSeaweedFS data center name. Defaults to the zone key name (e.g. zone dc1 gets dataCenter: dc1)
nodeSelectorNoYAML nodeSelector for scheduling volume server pods. Defaults to topology.kubernetes.io/zone: <zoneName>
poolsNoMap of storage pools for this zone. Same structure as volume.pools

Example

Patch the SeaweedFS HelmRelease to add per-zone pools:

kubectl patch -n tenant-example helmreleases.helm.toolkit.fluxcd.io seaweedfs --type=merge -p '{
  "spec":{
    "values":{
      "volume":{
        "zones":{
          "dc1":{
            "pools":{
              "ssd":{"diskType": "ssd", "size": "50Gi"},
              "hdd":{"diskType": "hdd", "size": "500Gi"}
            }
          },
          "dc2":{
            "pools":{
              "ssd":{"diskType": "ssd", "size": "50Gi"},
              "hdd":{"diskType": "hdd", "size": "500Gi"}
            }
          }
        }
      }
    }
  }
}'

In this example, zone dc1 automatically gets dataCenter: dc1 and nodeSelector: {topology.kubernetes.io/zone: dc1}.

To override these defaults, specify them explicitly:

volume:
  zones:
    us-east-1a:
      dataCenter: us-east
      nodeSelector:
        topology.kubernetes.io/zone: us-east-1a
        node.kubernetes.io/instance-type: storage-optimized
      pools:
        ssd:
          diskType: ssd
          size: 50Gi

The equivalent full resource with explicit zone settings:

apiVersion: apps.cozystack.io/v1alpha1
kind: SeaweedFS
metadata:
  name: seaweedfs
  namespace: tenant-example
spec:
  host: s3.example.com
  topology: MultiZone
  volume:
    replicas: 2
    size: 100Gi
    zones:
      dc1:
        pools:
          ssd:
            diskType: ssd
            size: 50Gi
          hdd:
            diskType: hdd
            size: 500Gi
      dc2:
        pools:
          ssd:
            diskType: ssd
            size: 50Gi
          hdd:
            diskType: hdd
            size: 500Gi

Each zone+pool combination creates its own Volume StatefulSet. In this example, that means four StatefulSets: seaweedfs-volume-dc1-ssd, seaweedfs-volume-dc1-hdd, seaweedfs-volume-dc2-ssd, and seaweedfs-volume-dc2-hdd.

COSI resources are deduplicated across zones – if both dc1 and dc2 define a pool named ssd with the same diskType, only one set of BucketClass/BucketAccessClass resources is created.

Verification

After deploying SeaweedFS with pools, verify the resources:

# Check that volume server StatefulSets were created for each pool
kubectl get statefulset -n tenant-example -l app.kubernetes.io/name=seaweedfs

# Check BucketClasses
kubectl get bucketclass

# Check BucketAccessClasses
kubectl get bucketaccessclass

You should see BucketClass and BucketAccessClass resources for each pool name.