API Reference
Packages
storage.simplyblock.io/v1alpha1
Package v1alpha1 contains API Schema definitions for the simplyblock v1alpha1 API group.
Resource Types
- BackupImport
- BackupPolicy
- BackupRestore
- ControlPlane
- ReplicationOps
- ReplicationPair
- ReplicationPolicy
- ReplicationSlot
- StorageBackup
- StorageCluster
- StorageNode
- StorageNodeOps
- StorageNodeSet
- StoragePool
- Task
- VolumeMigration
ActionStatus
Appears in: - StorageClusterStatus
Example:
action: string
nodeUUID: string
state: string
message: string
updatedAt: Time
observedGeneration: integer
triggered: boolean
subPhase: string
volumesMigrated: integer
volumesPending: integer
| Field | Description | Default | Validation |
|---|---|---|---|
action string |
Action is the requested action name. | ||
nodeUUID string |
NodeUUID is the target node UUID for the action. | ||
state string |
|||
message string |
Message is a human-readable action result or error. | ||
updatedAt Time ⧉ |
UpdatedAt is the timestamp of the last status transition. | ||
observedGeneration integer |
ObservedGeneration is the resource generation observed by this status. | ||
triggered boolean |
Triggered indicates whether the underlying backend action has been fired. | ||
subPhase string |
SubPhase tracks the active drain step within the remove action. | Enum: [Validating Suspending Migrating Verifying Removing] Optional: {} |
|
volumesMigrated integer |
VolumesMigrated is the count of volumes successfully migrated so far. | Optional: {} |
|
volumesPending integer |
VolumesPending is the count of volumes still awaiting migration. | Optional: {} |
AttachedLvol
AttachedLvol records a single PVC-to-lvol attachment managed by this policy.
Appears in: - BackupPolicyStatus
Example:
pvcName: string
pvcNamespace: string
lvolID: string
| Field | Description | Default | Validation |
|---|---|---|---|
pvcName string |
PVCName is the name of the PVC. | ||
pvcNamespace string |
PVCNamespace is the namespace of the PVC. | ||
lvolID string |
LvolID is the Simplyblock logical volume UUID that this policy is attached to. |
BackupCredentialsSecretRef
Appears in: - BackupSpec
Example:
name: string
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
Name is the name of the Secret in the same namespace as the cluster CR. |
BackupImport
BackupImport imports a completed backup from a source cluster into a target cluster, creating a StorageBackup CR that can be referenced by a BackupRestore.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: BackupImport
metadata:
name: string
spec:
sourceClusterName: string
sourceBackupID: '^[a-zA-Z0-9_-]{1,128}$'
targetClusterName: string
status:
phase: string
message: string
sourceClusterUUID: string
targetClusterUUID: string
importedBackupID: string
storageBackupRef: string
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
BackupImport |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec BackupImportSpec |
spec defines the desired state of BackupImport | Required: {} |
|
status BackupImportStatus |
status defines the observed state of BackupImport | Optional: {} |
BackupImportSpec
BackupImportSpec defines the desired state of BackupImport.
Appears in: - BackupImport
Example:
sourceClusterName: string
sourceBackupID: '^[a-zA-Z0-9_-]{1,128}$'
targetClusterName: string
| Field | Description | Default | Validation |
|---|---|---|---|
sourceClusterName string |
SourceClusterName is the StorageCluster CR name of the cluster that owns the backup. | ||
sourceBackupID string |
SourceBackupID is the UUID of the backup on the source cluster to import. | Pattern: ^[a-zA-Z0-9_-]\{1,128\}$ |
|
targetClusterName string |
TargetClusterName is the StorageCluster CR name of the cluster to import into. |
BackupImportStatus
BackupImportStatus defines the observed state of BackupImport.
Appears in: - BackupImport
Example:
phase: string
message: string
sourceClusterUUID: string
targetClusterUUID: string
importedBackupID: string
storageBackupRef: string
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase is the high-level lifecycle shown in kubectl output. | ||
message string |
Message contains the latest reconciliation detail or error. | ||
sourceClusterUUID string |
SourceClusterUUID is the resolved UUID of the source cluster. | ||
targetClusterUUID string |
TargetClusterUUID is the resolved UUID of the target cluster. | ||
importedBackupID string |
ImportedBackupID is the backup UUID after successful import into the target cluster. | ||
storageBackupRef string |
StorageBackupRef is the name of the StorageBackup CR created in the target namespace after a successful import. This CR can be referenced directly in a BackupRestore. |
||
completedAt Time ⧉ |
CompletedAt is when the import completed. |
BackupPolicy
BackupPolicy is the Schema for the backuppolicies API.
A BackupPolicy defines retention and scheduling parameters for Simplyblock backups. To apply a policy to a PVC, annotate the PVC with:
simplyblock.io/backup-policy: <BackupPolicy-name>
The deprecated simplybk/backup-policy annotation is still honoured for backwards compatibility; when both are set, simplyblock.io/backup-policy takes precedence.
The BackupPolicy must be in the same namespace as the annotated PVC. The controller attaches and detaches the policy in the Simplyblock backend whenever the annotation is added or removed.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: BackupPolicy
metadata:
name: string
spec:
clusterName: string
maxVersions: integer
maxAge: '^[1-9]\d*[mhdw]$'
schedule: '^(\d+[mhdw],\d+)( +\d+[mhdw],\d+)*$'
status:
phase: string
message: string
clusterUUID: string
policyID: string
attachedLvols:
- pvcName: string
pvcNamespace: string
lvolID: string
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
BackupPolicy |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec BackupPolicySpec |
spec defines the desired state of BackupPolicy | Required: {} |
|
status BackupPolicyStatus |
status defines the observed state of BackupPolicy | Optional: {} |
BackupPolicySpec
BackupPolicySpec defines the desired state of BackupPolicy.
Appears in: - BackupPolicy
Example:
clusterName: string
maxVersions: integer
maxAge: '^[1-9]\d*[mhdw]$'
schedule: '^(\d+[mhdw],\d+)( +\d+[mhdw],\d+)*$'
| Field | Description | Default | Validation |
|---|---|---|---|
clusterName string |
ClusterName is the target storage cluster name. | ||
maxVersions integer |
MaxVersions is the maximum number of completed backup versions to retain. When exceeded, the oldest backup is merged into the second-oldest. |
Optional: {} |
|
maxAge string |
MaxAge is the maximum age of backups to retain (e.g. "7d", "12h", "30m"). Backups older than this are merged. Accepts m, h, d, w suffixes. |
Pattern: ^[1-9]\d*[mhdw]$ Optional: {} |
|
schedule string |
Schedule defines the tiered backup schedule as a space-separated list of interval,keep_count pairs (e.g. "15m,4 60m,11 24h,7"). Intervals must be strictly increasing. Supported units: m, h, d, w. |
Pattern: ^(\d+[mhdw],\d+)( +\d+[mhdw],\d+)*$ Optional: {} |
BackupPolicyStatus
BackupPolicyStatus defines the observed state of BackupPolicy.
Appears in: - BackupPolicy
Example:
phase: string
message: string
clusterUUID: string
policyID: string
attachedLvols:
- pvcName: string
pvcNamespace: string
lvolID: string
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase is the high-level lifecycle state of the policy. | ||
message string |
Message contains the latest reconciliation detail or error. | ||
clusterUUID string |
ClusterUUID is the resolved backend cluster UUID. | ||
policyID string |
PolicyID is the UUID assigned to this policy by the Simplyblock backend. | ||
attachedLvols AttachedLvol array |
AttachedLvols lists the PVCs (and their lvol IDs) currently attached to this policy in the Simplyblock backend. The controller uses this to detect and reconcile annotation additions and removals. |
BackupRef
BackupRef identifies the StorageBackup to restore from, scoped to the same namespace.
Appears in: - BackupRestoreSpec
Example:
name: string
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
Name is the StorageBackup resource name. |
BackupRestore
BackupRestore is the Schema for the backuprestores API.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: BackupRestore
metadata:
name: string
spec:
clusterName: string
backupRef:
name: string
targetPool: string
targetNode: string
pvcTemplate:
metadata:
name: string
spec: PersistentVolumeClaimSpec
status:
phase: string
message: string
clusterUUID: string
backupID: string
sourceLvolID: string
fsType: string
poolName: string
poolUUID: string
restoredLvolID: string
pvName: string
pvcName: string
pvcNamespace: string
sourceClusterUUID: string
startedAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
BackupRestore |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec BackupRestoreSpec |
spec defines the desired state of BackupRestore | Required: {} |
|
status BackupRestoreStatus |
status defines the observed state of BackupRestore | Optional: {} |
BackupRestoreSpec
BackupRestoreSpec defines the desired state of BackupRestore.
Appears in: - BackupRestore
Example:
clusterName: string
backupRef:
name: string
targetPool: string
targetNode: string
pvcTemplate:
metadata:
name: string
spec: PersistentVolumeClaimSpec
| Field | Description | Default | Validation |
|---|---|---|---|
clusterName string |
ClusterName is the target storage cluster name. | ||
backupRef BackupRef |
BackupRef references the StorageBackup resource to restore from. | ||
targetPool string |
TargetPool overrides the pool to restore into. Defaults to the source backup's pool. |
Optional: {} |
|
targetNode string |
TargetNode is the UUID of the storage node to restore onto. Defaults to the node that originally held the backup. |
Optional: {} |
|
pvcTemplate PVCTemplate |
PVCTemplate describes the PVC to create once the restore completes. |
BackupRestoreStatus
BackupRestoreStatus defines the observed state of BackupRestore.
Appears in: - BackupRestore
Example:
phase: string
message: string
clusterUUID: string
backupID: string
sourceLvolID: string
fsType: string
poolName: string
poolUUID: string
restoredLvolID: string
pvName: string
pvcName: string
pvcNamespace: string
sourceClusterUUID: string
startedAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase is the high-level lifecycle shown in kubectl output. | ||
message string |
Message contains the latest reconciliation detail or error. | ||
clusterUUID string |
ClusterUUID is the backend cluster UUID. | ||
backupID string |
BackupID is the backend backup UUID being restored. | ||
sourceLvolID string |
SourceLvolID is the original logical volume UUID that was backed up. | ||
fsType string |
FSType is the filesystem type of the original source volume, copied from the referenced StorageBackup's status.fsType. Set on the restored PersistentVolume so it mounts with the same filesystem it was backed up with, instead of the CSI driver's default. |
||
poolName string |
PoolName is the pool the restore was issued against. | ||
poolUUID string |
PoolUUID is the backend pool UUID. | ||
restoredLvolID string |
RestoredLvolID is the UUID of the newly-created logical volume. | ||
pvName string |
PVName is the name of the PersistentVolume created by the controller. | ||
pvcName string |
PVCName is the name of the PersistentVolumeClaim created from pvcTemplate. | ||
pvcNamespace string |
PVCNamespace is the namespace of the created PVC. | ||
sourceClusterUUID string |
SourceClusterUUID is the UUID of the cluster that originally created the backup. Copied from the referenced StorageBackup's status.sourceClusterUUID. When non-empty and different from ClusterUUID, the controller resolves that cluster's backup credentials and sends them with the restore request, since the backup's bucket may not be this cluster's own. |
||
startedAt Time ⧉ |
StartedAt is when the backend restore task was accepted. | ||
completedAt Time ⧉ |
CompletedAt is when the PVC became bound. |
BackupSpec
Appears in: - StorageClusterSpec
Example:
localEndpoint: '^https?://[a-zA-Z0-9.-]+(:[0-9]{1,5})?(/.*)?$'
snapshotBackups: boolean
withCompression: boolean
secondaryTarget: integer
localTesting: boolean
credentialsSecretRef:
name: string
| Field | Description | Default | Validation |
|---|---|---|---|
localEndpoint string |
Pattern: ^https?://[a-zA-Z0-9.-]+(:[0-9]\{1,5\})?(/.*)?$ |
||
snapshotBackups boolean |
Optional: {} |
||
withCompression boolean |
Optional: {} |
||
secondaryTarget integer |
Optional: {} |
||
localTesting boolean |
Optional: {} |
||
credentialsSecretRef BackupCredentialsSecretRef |
CredentialsSecretRef points to the Secret holding access_key_id and secret_access_key. |
CapacityThresholdSpec
Appears in: - StorageClusterSpec
Example:
capacity: integer
provisionedCapacity: integer
| Field | Description | Default | Validation |
|---|---|---|---|
capacity integer |
Capacity defines the absolute capacity threshold value. | ||
provisionedCapacity integer |
ProvisionedCapacity defines the provisioned-capacity threshold value. |
ControlPlane
ControlPlane is a singleton resource (one per namespace, named "simplyblock") that reflects the readiness of the simplyblock control plane. It is created automatically by the Helm chart and should not be created or deleted manually.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: ControlPlane
metadata:
name: string
spec:
image: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
status:
phase: string
message: string
lastChecked: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
ControlPlane |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec ControlPlaneSpec |
Optional: {} |
||
status ControlPlaneStatus |
Optional: {} |
ControlPlaneSpec
ControlPlaneSpec holds configuration for the singleton ControlPlane resource created by the Helm chart.
Appears in: - ControlPlane
Example:
image: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
| Field | Description | Default | Validation |
|---|---|---|---|
image string |
Image is the container image used for all simplyblock control-plane and storage-node workloads (e.g. quay.io/simplyblock-io/simplyblock:26.2.2). StorageNodeSet CRs that omit spec.clusterImage inherit this value. Must reference one of the trusted registries (quay.io/simplyblock-io, docker.io/simplyblock, public.ecr.aws/simply-block); digest pinning (@sha256:...) is recommended. |
Pattern: ^($\|(quay\.io/simplyblock-io\|docker\.io/simplyblock\|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]\{64\})?)$ Optional: {} |
ControlPlaneStatus
ControlPlaneStatus reflects the observed readiness of the simplyblock control plane (FDB + management API).
Appears in: - ControlPlane
Example:
phase: string
message: string
lastChecked: Time
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase is Initializing while the control plane is not yet healthy, and Ready once the FDB health check passes. |
Enum: [Initializing Ready] |
|
message string |
Message contains a human-readable explanation of the current phase, for example the FDB error returned by the health endpoint. |
||
lastChecked Time ⧉ |
LastChecked is the timestamp of the most recent FDB health probe. |
DataRealignmentSettings
DataRealignmentSettings controls the periodic, post-migration control-plane data realignment. After one or more volumes have been moved the operator asks the control plane to re-align its internal data structures to the new placement, restoring fault-tolerance (FTT) and node-affinity guarantees.
Appears in: - VolumeMigrationSettings
Example:
enabled: boolean
interval: Duration
minMoves: integer
| Field | Description | Default | Validation |
|---|---|---|---|
enabled boolean |
Enabled activates automatic post-migration data realignment for this cluster. Defaults to true. |
Optional: {} |
|
interval Duration ⧉ |
Interval is how often the operator checks whether a realignment is pending (i.e. at least one volume has moved since the last successful realignment) and, if so, triggers it. Explicit triggers (see the simplyblock.io/trigger-realignment annotation) bypass this spacing. Defaults to 10m. Note that this is a floor on the spacing between realignment requests, not a ceiling on how long one takes: a realignment blocks all volume migrations for as long as the control plane needs, which on a busy cluster has been measured at tens of minutes. An interval shorter than that means the next realignment is requested as soon as the previous one finishes and any volume has moved, which is what MinMoves exists to damp. |
Optional: {} |
|
minMoves integer |
MinMoves is how many volume moves must accumulate before a realignment is triggered. Defaults to 1: every completed migration schedules a realignment. Raise it to batch. Because the control plane refuses new migrations while a realignment runs, a value of 1 makes the two alternate — one migration completes, a realignment follows and blocks migrations until it is done. On a cluster where realignment takes tens of minutes that is most of the available time, so a run that migrates continuously spends the majority of it waiting. A higher value trades realignment promptness (data structures stay unaligned for longer, so fault-tolerance and node-affinity guarantees are restored later) for migration throughput. Explicit triggers (the simplyblock.io/trigger-realignment annotation) ignore this threshold, so a drain or node removal still realigns immediately. |
Minimum: 1 Optional: {} |
DrainOpsSpec
DrainOpsSpec configures the drain workflow for action=remove.
Appears in: - StorageNodeOpsSpec
Example:
systemVolumeFilterRegex: string
| Field | Description | Default | Validation |
|---|---|---|---|
systemVolumeFilterRegex string |
SystemVolumeFilterRegex is a Go regular expression matched against backend volume names. Matching volumes are treated as system volumes: excluded from drain migration and deleted inline during the Verifying phase. Defaults to "^sb-fio-baseline-.*". |
Optional: {} |
HashicorpVaultSettings
HashicorpVaultSettings configures the HashiCorp Vault endpoint the cluster uses to store keys.
Appears in: - StorageClusterSpec
Example:
baseURL: '^https?://[a-zA-Z0-9.-]+(:[0-9]{1,5})?(/.*)?$'
| Field | Description | Default | Validation |
|---|---|---|---|
baseURL string |
BaseURL is the HashiCorp Vault endpoint (e.g. https://vault.example.com:8200). | Pattern: ^https?://[a-zA-Z0-9.-]+(:[0-9]\{1,5\})?(/.*)?$ |
JournalManagerSpec
JournalManagerSpec defines journal manager tuning parameters.
Appears in: - StorageNodeOverrides - StorageNodeSetSpec
Example:
count: integer
percentPerDevice: integer
| Field | Description | Default | Validation |
|---|---|---|---|
count integer |
Count is the number of journal managers to configure. | ||
percentPerDevice integer |
PercentPerDevice is the journal manager capacity percentage per device. |
MetricsBackend
Underlying type: string
MetricsBackend selects the NodeMetricsProvider implementation.
Validation: - Enum: [controlplane prometheus uniform]
Appears in: - VolumeAutoPlacementSettings
| Field | Description |
|---|---|
controlplane |
|
prometheus |
|
uniform |
MetricsBackendUniform returns IOPS=1 for every node, disabling IOPS-based scoring while keeping capacity/volume-count balancing active. |
MigrationConnection
MigrationConnection holds the NVMe-oF connection parameters for one path
on the migration target node, as returned by the storage API's CreateMigration.
All fields are passed verbatim to nvme connect in the validation Job.
Appears in: - VolumeMigrationStatus
Example:
nqn: string
ip: string
port: integer
transport: string
nrIoQueues: integer
reconnectDelay: integer
ctrlLossTmo: integer
fastIOFailTmo: integer
keepAliveTmo: integer
| Field | Description | Default | Validation |
|---|---|---|---|
nqn string |
|||
ip string |
|||
port integer |
|||
transport string |
|||
nrIoQueues integer |
|||
reconnectDelay integer |
|||
ctrlLossTmo integer |
|||
fastIOFailTmo integer |
|||
keepAliveTmo integer |
NodeDrainState
NodeDrainState tracks the upgrade-drain coordination state for a single worker node.
Appears in: - StorageNodeSetStatus
Example:
hostname: string
phase: string
startedAt: Time
message: string
activeNodeUUID: string
| Field | Description | Default | Validation |
|---|---|---|---|
hostname string |
Hostname is the Kubernetes node name. | ||
phase string |
Phase is the current drain coordination phase. | Enum: [detected shutdown_called draining restart_called complete failed] |
|
startedAt Time ⧉ |
StartedAt is when drain coordination began for this node. | ||
message string |
Message provides additional status detail or error information. | ||
activeNodeUUID string |
ActiveNodeUUID is the backend UUID of the storage node currently being shut down or restarted. Used to sequence through multiple NUMA-socket nodes on the same worker one at a time during drain coordination. |
NodeLatencyMetrics
NodeLatencyMetrics holds fio-measured 4K NVMe-oF latency for a single backend storage node. The benchmark volume NQN and connection details are derived at runtime from the node UUID and the cluster NQN — they are not stored here.
Appears in: - StorageNodeSetStatus - StorageNodeStatus
Example:
nodeUUID: string
baselineP50NS: integer
baselineP99NS: integer
baselineMeasuredAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
nodeUUID string |
NodeUUID is the backend storage node UUID. | ||
baselineP50NS integer |
BaselineP50NS is the p50 write latency (nanoseconds) from the initial empty-cluster benchmark. | ||
baselineP99NS integer |
BaselineP99NS is the p99 write latency (nanoseconds) from the initial empty-cluster benchmark. | ||
baselineMeasuredAt Time ⧉ |
BaselineMeasuredAt is when the baseline was established. |
NodeLoadMetrics
NodeLoadMetrics holds the latency deviation state for a single storage node.
Appears in: - RebalancingMetrics
Example:
nodeUUID: string
latencyDeviationPct: float
volumeCount: integer
lastUpdated: Time
| Field | Description | Default | Validation |
|---|---|---|---|
nodeUUID string |
|||
latencyDeviationPct float |
|||
volumeCount integer |
|||
lastUpdated Time ⧉ |
NodeRecycleSpec
NodeRecycleSpec configures the node-recycle action behaviour.
Appears in: - StorageClusterSpec
Example:
refreshSNodeAPI: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
refreshSNodeAPI boolean |
RefreshSNodeAPI restarts the storage-node DaemonSet pod on each node after the backend node is shut down and before it is restarted, ensuring the latest image is running before the node comes back online. |
NodeRecycleStatus
NodeRecycleStatus tracks in-progress state for the node-recycle action. All fields are persisted in CR status so the reconciler can resume after a requeue.
Appears in: - StorageClusterStatus
Example:
pendingNodes:
- string
processedNodes:
- string
nodePhase: string
phaseTriggered: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
pendingNodes string array |
PendingNodes is the ordered list of node UUIDs still to be recycled. | ||
processedNodes string array |
ProcessedNodes is the list of node UUIDs already recycled. | ||
nodePhase string |
NodePhase is the current step for the node being recycled: "snode-refresh" | "snode-refresh-wait" | "shutting-down" | "restarting" | "rebalancing" |
||
phaseTriggered boolean |
PhaseTriggered indicates the API call for the current NodePhase was already sent. |
NodeStatus
Appears in: - StorageNodeSetStatus
Example:
uuid: string
health: boolean
status: string
cpu: integer
memory: string
volumes: integer
rpcPort: integer
lvolPort: integer
nvmfPort: integer
devices: string
uptime: string
hostname: string
mgmtIp: string
postedAt: Time
failureDomain: integer
| Field | Description | Default | Validation |
|---|---|---|---|
uuid string |
UUID is the backend node UUID. | ||
health boolean |
Health indicates whether health checks are currently passing. | ||
status string |
Status is the backend lifecycle state for the node. | ||
cpu integer |
CPU is the reported CPU allocation/count for the node. | ||
memory string |
Memory is the reported memory value. | ||
volumes integer |
Volumes is the current logical volume count. | ||
rpcPort integer |
RpcPort is the node RPC service port. | ||
lvolPort integer |
LvolPort is the logical-volume subsystem port. | ||
nvmfPort integer |
NvmfPort is the NVMf service port. | ||
devices string |
Devices is the backend summary of devices on this node. | ||
uptime string |
Uptime is the reported node uptime value. | ||
hostname string |
Hostname is the Kubernetes node hostname. | ||
mgmtIp string |
MgmtIp is the management IP address for the node. | ||
postedAt Time ⧉ |
PostedAt is when the storage-node add request was sent. Used to detect timeout without blocking the reconcile goroutine. |
||
failureDomain integer |
FailureDomain is the effective failure-domain group index for this node, reflected from spec.nodeConfigs[hostname].failureDomain or spec.nodeFailureDomains[hostname]. Zero means unset. |
Optional: {} |
PVCTemplate
PVCTemplate describes the PVC the controller will create once the restore completes.
Appears in: - BackupRestoreSpec
Example:
metadata:
name: string
spec: PersistentVolumeClaimSpec
| Field | Description | Default | Validation |
|---|---|---|---|
metadata PVCTemplateMetadata |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec PersistentVolumeClaimSpec ⧉ |
Spec follows core PersistentVolumeClaimSpec. spec.resources.requests.storage must be >= the backup size. |
PVCTemplateMetadata
PVCTemplateMetadata describes the PVC metadata fields the controller honors.
Appears in: - PVCTemplate
Example:
name: string
labels:
string: string
annotations:
string: string
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
Optional: {} |
||
labels object (keys:string, values:string) |
Optional: {} |
||
annotations object (keys:string, values:string) |
Optional: {} |
PersistentVolumeClaimRef
Appears in: - StorageBackupSpec
Example:
name: string
namespace: string
| Field | Description | Default | Validation |
|---|---|---|---|
name string |
Name is the PVC name. | ||
namespace string |
Namespace overrides the backup resource namespace for the PVC lookup. |
RebalancingMetrics
RebalancingMetrics is written by the VolumeRebalancerReconciler each evaluation cycle.
Appears in: - StorageClusterStatus
Example:
avgDeviationPct: float
maxDeviationPct: float
hottestNodeUUID: string
coolestNodeUUID: string
imbalancePercent: float
lastEvaluatedAt: Time
lastMigrationAt: Time
nodeMetrics:
- nodeUUID: string
latencyDeviationPct: float
volumeCount: integer
lastUpdated: Time
| Field | Description | Default | Validation |
|---|---|---|---|
avgDeviationPct float |
AvgDeviationPct is the mean latency deviation across all nodes. | ||
maxDeviationPct float |
MaxDeviationPct is the highest per-node latency deviation (used as ImbalancePercent). | ||
hottestNodeUUID string |
|||
coolestNodeUUID string |
|||
imbalancePercent float |
|||
lastEvaluatedAt Time ⧉ |
|||
lastMigrationAt Time ⧉ |
|||
nodeMetrics NodeLoadMetrics array |
ReplicationOps
ReplicationOps is a one-shot user-driven CR for imperative replication operations: failover (planned or unplanned) and failback. The operator drives the backend calls to completion and records per-volume outcomes in status.results. Only one ReplicationOps may be active per ReplicationPolicy at a time, enforced via ReplicationPolicy.status.activeOpsRef.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: ReplicationOps
metadata:
name: string
spec:
action: string
scope: string
ref: string
sourceClusterID: string
deleteSource: boolean
status:
phase: string
subphase: string
message: string
startedAt: Time
completedAt: Time
results:
- slotRef: string
status: string
detail: string
targetLvolID: string
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
ReplicationOps |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec ReplicationOpsSpec |
|||
status ReplicationOpsStatus |
ReplicationOpsResult
ReplicationOpsResult holds the outcome for a single volume in a ReplicationOps.
Appears in: - ReplicationOpsStatus
Example:
slotRef: string
status: string
detail: string
targetLvolID: string
| Field | Description | Default | Validation |
|---|---|---|---|
slotRef string |
SlotRef is the name of the ReplicationSlot CR. | ||
status string |
Status is the outcome for this volume. | Enum: [succeeded skipped failed] |
|
detail string |
Detail is an optional human-readable note (error message or skip reason). | Optional: {} |
|
targetLvolID string |
TargetLvolID is the UUID of the volume on the target cluster (failover only). | Optional: {} |
ReplicationOpsSpec
ReplicationOpsSpec defines the desired state of a ReplicationOps.
Appears in: - ReplicationOps
Example:
action: string
scope: string
ref: string
sourceClusterID: string
deleteSource: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
action string |
Action is the operation to perform. Immutable. failover: unplanned — promote target clone, source may be down. failback: restore source as primary after a prior failover. migration: planned cutover — calls replication_commit per volume; both clusters stay up. State progression: replicating → cutover_pending → cutover_done. |
Enum: [failover failback migration] Required: {} |
|
scope string |
Scope controls which volumes are affected. Immutable. target: all volumes across every policy that uses the named ReplicationPair. policy: all volumes managed by the named ReplicationPolicy CR. volume: a single ReplicationSlot (planned or unplanned per-volume operation). |
Enum: [target policy volume] Required: {} |
|
ref string |
Ref is the name of the resource identified by Scope: a ReplicationPair name for scope=target, a ReplicationPolicy name for scope=policy, or a ReplicationSlot name for scope=volume. Immutable. |
Required: {} |
|
sourceClusterID string |
SourceClusterID is used for failback only. Omit to recover to the original source. | Optional: {} |
|
deleteSource boolean |
DeleteSource instructs the backend to delete the source volume after a successful migration cutover. Only meaningful when action=migration. |
Optional: {} |
ReplicationOpsStatus
ReplicationOpsStatus holds the observed state of a ReplicationOps.
Appears in: - ReplicationOps
Example:
phase: string
subphase: string
message: string
startedAt: Time
completedAt: Time
results:
- slotRef: string
status: string
detail: string
targetLvolID: string
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase is the current lifecycle phase of this operation. | Enum: [Pending Running Succeeded Failed] Optional: {} |
|
subphase string |
Subphase describes what the operation is currently doing within the phase (e.g. "TriggeringFailover", "UpdatingSlotStatuses", "ReleasingLock"). |
Optional: {} |
|
message string |
Message is a human-readable description of the current phase. | Optional: {} |
|
startedAt Time ⧉ |
StartedAt is when the operation began. | Optional: {} |
|
completedAt Time ⧉ |
CompletedAt is when the operation finished (successfully or not). | Optional: {} |
|
results ReplicationOpsResult array |
Results holds a per-volume summary of the operation outcome. | Optional: {} |
ReplicationPair
ReplicationPair defines the source and target clusters for a replication relationship. It is reusable configuration — multiple ReplicationPolicies may reference the same pair to replicate volumes between the same two clusters with different schedules or retention. The operator ensures the corresponding backend ReplicationTarget exists and stores its ID in status.backendTargetID for use by ReplicationPolicy resources.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: ReplicationPair
metadata:
name: string
spec:
sourceCluster: string
targetCluster: string
status:
ready: boolean
backendTargetID: string
message: string
conditions:
- Condition
activeOpsRef: string
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
ReplicationPair |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec ReplicationPairSpec |
|||
status ReplicationPairStatus |
ReplicationPairSpec
ReplicationPairSpec defines the source and target clusters for a replication relationship.
Appears in: - ReplicationPair
Example:
sourceCluster: string
targetCluster: string
| Field | Description | Default | Validation |
|---|---|---|---|
sourceCluster string |
SourceCluster is the name of the local StorageCluster (the replication source). | Required: {} |
|
targetCluster string |
TargetCluster is the name or UUID of the remote cluster (the replication target). Immutable after creation. |
Required: {} |
ReplicationPairStatus
ReplicationPairStatus holds the observed state of a ReplicationPair.
Appears in: - ReplicationPair
Example:
ready: boolean
backendTargetID: string
message: string
conditions:
- Condition
activeOpsRef: string
| Field | Description | Default | Validation |
|---|---|---|---|
ready boolean |
Ready is true when the backend ReplicationTarget has been created and is available. | Optional: {} |
|
backendTargetID string |
BackendTargetID is the UUID of the backend ReplicationTarget resource. | Optional: {} |
|
message string |
Message provides a human-readable description of the current state. | Optional: {} |
|
conditions Condition ⧉ array |
Conditions holds standard Kubernetes condition types. | Optional: {} |
|
activeOpsRef string |
ActiveOpsRef is the name of the ReplicationOps currently holding the target-scope lock on this pair. Only one scope=target ReplicationOps may be active per pair at a time. |
Optional: {} |
ReplicationPolicy
ReplicationPolicy defines the replication schedule and retention for volumes replicated between the clusters defined by a ReplicationPair. A StorageClass or PVC references a policy via the storage.simplyblock.io/replication-policy annotation. The operator automatically creates one ReplicationSlot per bound PVC. Deletion is blocked while any ReplicationSlots reference this policy.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: ReplicationPolicy
metadata:
name: string
spec:
pairRef: string
mode: string
interval: string
snapshotRetention: integer
status:
ready: boolean
backendPolicyID: string
slotCount: integer
activeOpsRef: string
conditions:
- Condition
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
ReplicationPolicy |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec ReplicationPolicySpec |
|||
status ReplicationPolicyStatus |
ReplicationPolicySpec
ReplicationPolicySpec defines the desired replication schedule and retention.
Appears in: - ReplicationPolicy
Example:
pairRef: string
mode: string
interval: string
snapshotRetention: integer
| Field | Description | Default | Validation |
|---|---|---|---|
pairRef string |
PairRef is the name of the ReplicationPair that defines the source and target clusters. Multiple ReplicationPolicies may reference the same pair with different schedules. |
Required: {} |
|
mode string |
Mode controls replication semantics. failover: target is a DR standby; volumes are read-only on the target. migration: planned online cutover to the target cluster. |
failover | Enum: [failover migration] Optional: {} |
interval string |
Interval is how often a replication snapshot is taken (e.g. "5m", "1h"). | 5m | Optional: {} |
snapshotRetention integer |
SnapshotRetention is the minimum number of snapshots to retain on the target. | 3 | Minimum: 2 Optional: {} |
ReplicationPolicyStatus
ReplicationPolicyStatus holds the observed state of a ReplicationPolicy.
Appears in: - ReplicationPolicy
Example:
ready: boolean
backendPolicyID: string
slotCount: integer
activeOpsRef: string
conditions:
- Condition
| Field | Description | Default | Validation |
|---|---|---|---|
ready boolean |
Ready is true when the backend ReplicationPolicy has been created. | Optional: {} |
|
backendPolicyID string |
BackendPolicyID is the UUID of the backend ReplicationPolicy resource. | Optional: {} |
|
slotCount integer |
SlotCount is the number of ReplicationSlot CRs currently managed by this policy. | Optional: {} |
|
activeOpsRef string |
ActiveOpsRef is the name of the currently running ReplicationOps CR. Empty when no operation is in progress. |
Optional: {} |
|
conditions Condition ⧉ array |
Conditions holds standard Kubernetes condition types. | Optional: {} |
ReplicationSlot
ReplicationSlot tracks the live replication state for a single PVC. One ReplicationSlot is created per PVC by the PVCAnnotationWatcher controller when a PVC references a ReplicationPolicy via annotation. It is owned by its PVC, so deleting the PVC cascades deletion and triggers a backend detach via the slot finalizer. The ReplicationSlot reconciler drives all backend calls: attach, monitor, cutover, failover, and detach.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: ReplicationSlot
metadata:
name: string
spec:
policyRef: string
pvcRef: string
volumeID: string
status:
state: string
direction: string
sourceLvolID: string
targetLvolID: string
targetNQN: string
lastReplicatedAt: Time
message: string
conditions:
- Condition
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
ReplicationSlot |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec ReplicationSlotSpec |
|||
status ReplicationSlotStatus |
ReplicationSlotSpec
ReplicationSlotSpec defines the identity of a per-volume replication slot.
Appears in: - ReplicationSlot
Example:
policyRef: string
pvcRef: string
volumeID: string
| Field | Description | Default | Validation |
|---|---|---|---|
policyRef string |
PolicyRef is the name of the ReplicationPolicy governing this slot. Immutable. | Required: {} |
|
pvcRef string |
PVCRef is the name of the PVC being replicated. Immutable. | Required: {} |
|
volumeID string |
VolumeID is the backend lvol UUID of the source volume. Immutable. Format: " |
Required: {} |
ReplicationSlotStatus
ReplicationSlotStatus holds the observed state of a ReplicationSlot.
Appears in: - ReplicationSlot
Example:
state: string
direction: string
sourceLvolID: string
targetLvolID: string
targetNQN: string
lastReplicatedAt: Time
message: string
conditions:
- Condition
| Field | Description | Default | Validation |
|---|---|---|---|
state string |
State is the current replication state for this slot. | Enum: [attaching replicating cutover_pending cutover_done failed_over detaching error] Optional: {} |
|
direction string |
Direction is which side of the replication relationship this cluster holds. | Enum: [source target] Optional: {} |
|
sourceLvolID string |
SourceLvolID is the UUID of the source volume on the source cluster. | Optional: {} |
|
targetLvolID string |
TargetLvolID is the UUID of the replicated volume on the target cluster. | Optional: {} |
|
targetNQN string |
TargetNQN is the NVMe NQN on the target cluster (populated after failover). | Optional: {} |
|
lastReplicatedAt Time ⧉ |
LastReplicatedAt is the timestamp of the last successful replication snapshot. | Optional: {} |
|
message string |
Message provides a human-readable description of the current state. | Optional: {} |
|
conditions Condition ⧉ array |
Conditions holds standard Kubernetes condition types. | Optional: {} |
StorageBackup
StorageBackup is the Schema for the storagebackups API.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: StorageBackup
metadata:
name: string
spec:
clusterName: string
pvcRef:
name: string
namespace: string
snapshotName: string
sourceClusterUUID: string
status:
phase: string
apiStatus: string
message: string
clusterUUID: string
pvcNamespace: string
pvName: string
poolName: string
poolUUID: string
lvolID: string
lvolName: string
fsType: string
snapshotID: string
snapshotName: string
sourceClusterUUID: string
backupID: string
s3ID: integer
nodeID: string
prevBackupID: string
size: integer
allowedHosts:
- 'map[string]string'
createdAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
StorageBackup |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec StorageBackupSpec |
spec defines the desired state of StorageBackup | Required: {} |
|
status StorageBackupStatus |
status defines the observed state of StorageBackup | Optional: {} |
StorageBackupSpec
StorageBackupSpec defines the desired state of StorageBackup.
Appears in: - StorageBackup
Example:
clusterName: string
pvcRef:
name: string
namespace: string
snapshotName: string
sourceClusterUUID: string
| Field | Description | Default | Validation |
|---|---|---|---|
clusterName string |
ClusterName is the target storage cluster name. | ||
pvcRef PersistentVolumeClaimRef |
PVCRef identifies the PVC whose backing Simplyblock volume should be snapshotted and backed up. Not required when SourceClusterUUID is set (imported backup). |
Optional: {} |
|
snapshotName string |
SnapshotName optionally overrides the internally-created snapshot name. | Optional: {} |
|
sourceClusterUUID string |
SourceClusterUUID, when non-empty, marks this StorageBackup as imported from another cluster. The StorageBackup controller will not create snapshots or backups for imported resources. Set by the BackupImport controller; do not set manually. |
Optional: {} |
StorageBackupStatus
StorageBackupStatus defines the observed state of StorageBackup.
Appears in: - StorageBackup
Example:
phase: string
apiStatus: string
message: string
clusterUUID: string
pvcNamespace: string
pvName: string
poolName: string
poolUUID: string
lvolID: string
lvolName: string
fsType: string
snapshotID: string
snapshotName: string
sourceClusterUUID: string
backupID: string
s3ID: integer
nodeID: string
prevBackupID: string
size: integer
allowedHosts:
- 'map[string]string'
createdAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
phase string |
Phase is the high-level backup lifecycle shown in kubectl output. | ||
apiStatus string |
APIStatus is the raw status returned by the backup API. | ||
message string |
Message contains the latest reconciliation detail or error. | ||
clusterUUID string |
ClusterUUID is the backend cluster UUID. | ||
pvcNamespace string |
PVCNamespace is the resolved PVC namespace. | ||
pvName string |
PVName is the bound PV name. | ||
poolName string |
PoolName is the Simplyblock pool name derived from the CSI volume handle. | ||
poolUUID string |
PoolUUID is the backend pool UUID. | ||
lvolID string |
LvolID is the Simplyblock volume UUID. | ||
lvolName string |
LvolName is the backend logical volume name. | ||
fsType string |
FSType is the filesystem type of the source PersistentVolume (e.g. "ext4", "xfs"), captured at backup time so a restore can preserve it regardless of which StorageClass the restored PVC ends up using. |
||
snapshotID string |
SnapshotID is the internally-created snapshot UUID used for the backup request. | ||
snapshotName string |
SnapshotName is the snapshot name used for the backup request. | ||
sourceClusterUUID string |
SourceClusterUUID is set for imported backups; identifies the cluster that originally created the backup. When non-empty and different from the restore target cluster UUID, BackupRestore will automatically perform source-switch operations around the restore. |
||
backupID string |
BackupID is the backend backup UUID. | ||
s3ID integer |
S3ID is the backend S3 object identifier. | ||
nodeID string |
NodeID is the source storage node UUID. | ||
prevBackupID string |
PrevBackupID links the previous backup in the chain. | ||
size integer |
Size is the backup size in bytes. | ||
allowedHosts object array |
AllowedHosts contains the allowed host metadata returned by the backup API. | ||
createdAt Time ⧉ |
CreatedAt is when the backup was created. | ||
completedAt Time ⧉ |
CompletedAt is when the backup completed. |
StorageClassParameters
StorageClassParameters defines the default StorageClass parameter values for volumes in this pool. These are passed as-is to the CSI driver when the StorageClass is created. cluster_id and pool_name are always set automatically and cannot be overridden here.
IMPORTANT: StorageClass Parameters are immutable in the Kubernetes API, so this whole field is immutable once set (see StoragePoolSpec.StorageClassParameters) — there's no supported way to change a pool's StorageClass defaults after the pool is created. Create a new StoragePool instead.
Appears in: - StoragePoolSpec
Example:
qosRwIops: string
qosRwMbytes: string
qosRMbytes: string
qosWMbytes: string
encryption: boolean
fabric: string
maxNamespacePerSubsys: string
tune2fsReservedBlocks: string
filesystem: string
| Field | Description | Default | Validation |
|---|---|---|---|
qosRwIops string |
QosRwIops sets the read/write IOPS limit (0 = unlimited). | 0 | |
qosRwMbytes string |
QosRwMbytes sets the read/write throughput limit in MB/s (0 = unlimited). | 0 | |
qosRMbytes string |
QosRMbytes sets the read throughput limit in MB/s (0 = unlimited). | 0 | |
qosWMbytes string |
QosWMbytes sets the write throughput limit in MB/s (0 = unlimited). | 0 | |
encryption boolean |
Encryption enables encryption for logical volumes. | false | |
fabric string |
Fabric is the transport fabric (e.g. tcp). | tcp | |
maxNamespacePerSubsys string |
MaxNamespacePerSubsys limits namespaces per NVMf subsystem. | 1 | |
tune2fsReservedBlocks string |
Tune2fsReservedBlocks sets the ext4 reserved-blocks percentage. Left unset, the node plugin skips tune2fs entirely and mkfs.ext4's own default reserve applies, matching a StorageClass that omits tune2fs_reserved_blocks. A default of "0" here would not be a no-op: it actively runs tune2fs -m 0 on every volume, since the node plugin only skipsthe call when the parameter is empty (see stageVolume in the CSI driver), not when it's "0". |
||
filesystem string |
Filesystem is the filesystem used to format logical volumes of this pool. | xfs | Enum: [ext4 xfs] |
StorageCluster
StorageCluster is the Schema for the storageclusters API
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: StorageCluster
metadata:
name: string
spec:
enableNodeAffinity: boolean
stripe:
dataChunks: integer
parityChunks: integer
action: string
nodeRecycle:
refreshSNodeAPI: boolean
fabricType: string
clientDataIfname: string
nvmfBasePort: integer
rpcBasePort: integer
snodeApiPort: integer
maxConcurrentWorkerRestarts: integer
maxSubsystemCount: integer
maxHugePagesSize: string
vcpuCount: integer
warningThreshold:
capacity: integer
provisionedCapacity: integer
criticalThreshold:
capacity: integer
provisionedCapacity: integer
backup:
localEndpoint: '^https?://[a-zA-Z0-9.-]+(:[0-9]{1,5})?(/.*)?$'
snapshotBackups: boolean
withCompression: boolean
secondaryTarget: integer
localTesting: boolean
credentialsSecretRef:
name: string
hashicorpVaultSettings:
baseURL: '^https?://[a-zA-Z0-9.-]+(:[0-9]{1,5})?(/.*)?$'
volumeMigrationSettings:
enabled: boolean
rebalancerImage: string
dataRealignment:
enabled: boolean
interval: Duration
minMoves: integer
volumeAutoPlacement:
enabled: boolean
migrationEnabled: boolean
evaluationInterval: Duration
imbalanceThreshold: integer
minHotColdDifferencePct: integer
defaultCoolDownSeconds: integer
maxVolumeMigrationsPerCycle: integer
storageNodeCandidateCount: integer
metricsBackend: MetricsBackend
prometheusURL: string
latencyBenchmarkEnabled: boolean
latencyBenchmarkInterval: Duration
iopsWeight: float
throughputWeight: float
enableFailureDomains: boolean
status:
uuid: string
phase: string
subPhase: string
clusterName: string
mgmtNodes: integer
storageNodes: integer
nqn: string
status: string
rebalancing: boolean
volumeMoveGeneration: integer
realignedGeneration: integer
lastDataRealignmentAt: Time
erasureCodingScheme: string
lastUpdated: Time
created: Time
configured: boolean
maxFaultTolerance: integer
maxConcurrentWorkerRestarts: integer
actionStatus:
action: string
nodeUUID: string
state: string
message: string
updatedAt: Time
observedGeneration: integer
triggered: boolean
subPhase: string
volumesMigrated: integer
volumesPending: integer
nodeRecycleStatus:
pendingNodes:
- string
processedNodes:
- string
nodePhase: string
phaseTriggered: boolean
rebalancingMetrics:
avgDeviationPct: float
maxDeviationPct: float
hottestNodeUUID: string
coolestNodeUUID: string
imbalancePercent: float
lastEvaluatedAt: Time
lastMigrationAt: Time
nodeMetrics:
- nodeUUID: string
latencyDeviationPct: float
volumeCount: integer
lastUpdated: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
StorageCluster |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec StorageClusterSpec |
spec defines the desired state of StorageCluster | Required: {} |
|
status StorageClusterStatus |
status defines the observed state of StorageCluster | Optional: {} |
StorageClusterSpec
StorageClusterSpec defines the desired state of StorageCluster
Appears in: - StorageCluster
Example:
enableNodeAffinity: boolean
stripe:
dataChunks: integer
parityChunks: integer
action: string
nodeRecycle:
refreshSNodeAPI: boolean
fabricType: string
clientDataIfname: string
nvmfBasePort: integer
rpcBasePort: integer
snodeApiPort: integer
maxConcurrentWorkerRestarts: integer
maxSubsystemCount: integer
maxHugePagesSize: string
vcpuCount: integer
warningThreshold:
capacity: integer
provisionedCapacity: integer
criticalThreshold:
capacity: integer
provisionedCapacity: integer
backup:
localEndpoint: '^https?://[a-zA-Z0-9.-]+(:[0-9]{1,5})?(/.*)?$'
snapshotBackups: boolean
withCompression: boolean
secondaryTarget: integer
localTesting: boolean
credentialsSecretRef:
name: string
hashicorpVaultSettings:
baseURL: '^https?://[a-zA-Z0-9.-]+(:[0-9]{1,5})?(/.*)?$'
volumeMigrationSettings:
enabled: boolean
rebalancerImage: string
dataRealignment:
enabled: boolean
interval: Duration
minMoves: integer
volumeAutoPlacement:
enabled: boolean
migrationEnabled: boolean
evaluationInterval: Duration
imbalanceThreshold: integer
minHotColdDifferencePct: integer
defaultCoolDownSeconds: integer
maxVolumeMigrationsPerCycle: integer
storageNodeCandidateCount: integer
metricsBackend: MetricsBackend
prometheusURL: string
latencyBenchmarkEnabled: boolean
latencyBenchmarkInterval: Duration
iopsWeight: float
throughputWeight: float
enableFailureDomains: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
enableNodeAffinity boolean |
EnableNodeAffinity enables node-affinity placement for storage components. | Optional: {} |
|
stripe StripeSpec |
StripeSpec configures erasure-coding data/parity chunk counts. | ||
action string |
Action triggers a cluster-level action. | Enum: [activate expand shutdown start restart node-recycle] |
|
nodeRecycle NodeRecycleSpec |
NodeRecycle configures the node-recycle action. | ||
fabricType string |
FabricType defines the storage fabric type. | ||
clientDataIfname string |
ClientDataIfname defines the client data network interface. | ||
nvmfBasePort integer |
NvmfBasePort defines the base NVMf service port. | ||
rpcBasePort integer |
RpcBasePort defines the base RPC service port. | ||
snodeApiPort integer |
SnodeApiPort defines the storage-node API port. | ||
maxConcurrentWorkerRestarts integer |
MaxConcurrentWorkerRestarts is the maximum number of Kubernetes worker nodes the operator may drain and restart simultaneously. The effective concurrency applied by the drain coordinator is min(MaxConcurrentWorkerRestarts, MaxFaultTolerance). Defaults to 1 when unset. |
Minimum: 1 Optional: {} |
|
maxSubsystemCount integer |
MaxSubsystemCount is the maximum number of NVMe-oF subsystems per storage node. Applies to every storage node in the cluster. Required: it sizes huge pages, and a node that receives no value fails config generation outright rather than falling back to a default. |
Maximum: 75 Minimum: 10 Required: {} |
|
maxHugePagesSize string |
MaxHugePagesSize is the maximum allocatable size of huge pages on each storage node (e.g. "100G", "1T"; a bare number is interpreted as GB). It is a floor, not a cap: the effective huge-page allocation is the larger of this value and the minimum the node's device and subsystem count requires. When omitted the computed minimum is used. |
Optional: {} |
|
vcpuCount integer |
VCPUCount is the number of vCPUs allocated to SPDK on each storage node. This is an explicit core count, not a percentage. Required: the core layout it produces must match across the cluster, so it is stated rather than left to a per-node heuristic. |
Minimum: 6 Required: {} |
|
warningThreshold CapacityThresholdSpec |
WarningThresholdSpec defines warning-level capacity thresholds. | ||
criticalThreshold CapacityThresholdSpec |
CriticalThresholdSpec defines critical-level capacity thresholds. | ||
backup BackupSpec |
Backup specifies the specification for backup to S3 configuration | ||
hashicorpVaultSettings HashicorpVaultSettings |
HashicorpVaultSettings configures the Vault endpoint used by the cluster for key storage. | ||
volumeMigrationSettings VolumeMigrationSettings |
VolumeMigrationSettings controls volume migration for this cluster. | Optional: {} |
|
volumeAutoPlacement VolumeAutoPlacementSettings |
VolumeAutoPlacement configures automatic, latency-driven volume rebalancing. When nil/disabled the operator performs only manually-triggered VolumeMigrations. |
Optional: {} |
|
enableFailureDomains boolean |
EnableFailureDomains opts the cluster into failure-domain mode. When enabled, every storage node must declare a failure-domain group so the control plane can spread erasure-coding chunks across independent fault groups. Immutable once set — failure- domain mode cannot be toggled on a live cluster. |
Optional: {} |
StorageClusterStatus
StorageClusterStatus defines the observed state of StorageCluster.
Appears in: - StorageCluster
Example:
uuid: string
phase: string
subPhase: string
clusterName: string
mgmtNodes: integer
storageNodes: integer
nqn: string
status: string
rebalancing: boolean
volumeMoveGeneration: integer
realignedGeneration: integer
lastDataRealignmentAt: Time
erasureCodingScheme: string
lastUpdated: Time
created: Time
configured: boolean
maxFaultTolerance: integer
maxConcurrentWorkerRestarts: integer
actionStatus:
action: string
nodeUUID: string
state: string
message: string
updatedAt: Time
observedGeneration: integer
triggered: boolean
subPhase: string
volumesMigrated: integer
volumesPending: integer
nodeRecycleStatus:
pendingNodes:
- string
processedNodes:
- string
nodePhase: string
phaseTriggered: boolean
rebalancingMetrics:
avgDeviationPct: float
maxDeviationPct: float
hottestNodeUUID: string
coolestNodeUUID: string
imbalancePercent: float
lastEvaluatedAt: Time
lastMigrationAt: Time
nodeMetrics:
- nodeUUID: string
latencyDeviationPct: float
volumeCount: integer
lastUpdated: Time
| Field | Description | Default | Validation |
|---|---|---|---|
uuid string |
UUID is the backend cluster UUID. | ||
phase string |
Phase tracks the cluster creation lifecycle to prevent concurrent reconcilers from creating duplicate clusters. Set to "creation" while a creation is in progress and cleared once the cluster UUID is persisted. |
||
subPhase string |
SubPhase tracks the step within the current Phase. Reserved for future sub-state machine expansion; currently only "creating" is used. |
||
clusterName string |
ClusterName is the resolved backend cluster name. | ||
mgmtNodes integer |
MgmtNodes is the number of management nodes. FIXME: Unused for now (API update required?) |
||
storageNodes integer |
StorageNodes is the number of storage nodes. FIXME: Unused for now (API update required?) |
||
nqn string |
NQN is the cluster NVM subsystem qualified name. | ||
status string |
Status is the backend-reported lifecycle status. | ||
rebalancing boolean |
Rebalancing indicates whether cluster rebalancing is currently active. | ||
volumeMoveGeneration integer |
VolumeMoveGeneration counts completed volume moves. Every migration that reaches Completed increments it, and nothing else writes it, so it only ever grows. |
Optional: {} |
|
realignedGeneration integer |
RealignedGeneration is the VolumeMoveGeneration that the last successfully requested realignment covers. A realignment is outstanding while VolumeMoveGeneration exceeds it. This is recorded from the value read before the request is sent, because that is what the realignment can actually account for: a migration completing while the request is in flight raises VolumeMoveGeneration past it and so correctly leaves another realignment outstanding, instead of being swallowed by the one already running. |
Optional: {} |
|
lastDataRealignmentAt Time ⧉ |
LastDataRealignmentAt is the time of the last successful control-plane data realignment. It is used to space realignments by DataRealignment.Interval and to avoid re-running at the end of an interval when nothing is pending. |
Optional: {} |
|
erasureCodingScheme string |
ErasureCodingScheme is the active erasure-coding layout, for example "2x1". | ||
lastUpdated Time ⧉ |
LastUpdated is the last backend update timestamp. FIXME: Unused for now (API update required?) |
||
created Time ⧉ |
Created is the backend creation timestamp. FIXME: Unused for now (API update required?) |
||
configured boolean |
Configured indicates whether initial cluster setup completed. | ||
maxFaultTolerance integer |
MaxFaultTolerance is the backend-reported maximum number of nodes that can be simultaneously offline (failed, drained, or restarted) without violating the cluster's redundancy guarantees. |
||
maxConcurrentWorkerRestarts integer |
MaxConcurrentWorkerRestarts is the effective concurrent-restart limit applied by the drain coordinator: min(spec.MaxConcurrentWorkerRestarts, MaxFaultTolerance). Defaults to 1. Exposed here so controllers and tooling can read a single authoritative value without re-computing it. |
Optional: {} |
|
actionStatus ActionStatus |
ActionStatus tracks the most recent action execution state. | ||
nodeRecycleStatus NodeRecycleStatus |
NodeRecycleStatus tracks in-progress state for the node-recycle action. | ||
rebalancingMetrics RebalancingMetrics |
RebalancingMetrics is updated by the auto-rebalancer each evaluation cycle. | Optional: {} |
StorageNode
StorageNode is the Schema for a single backend storage node instance. One StorageNode CR exists per (workerNode, socketIndex) pair and is owned by the parent StorageNodeSet.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: StorageNode
metadata:
name: string
spec:
storageNodeSetRef: string
workerNode: string
socketId: string
nodeIndex: integer
socketIndex: integer
overrides:
spdkImage: string
spdkProxyImage: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
deviceNames:
- string
enableCpuTopology: boolean
reservedSystemCPU: string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
failureDomain: integer
expand: boolean
status:
uuid: string
status: string
health: boolean
hostname: string
uptime: string
resources:
cpu: integer
memory: string
volumes: integer
devices: string
ports:
management: string
nvmeof: integer
lvol: integer
rpc: integer
postedAt: Time
activeOpsRef: string
latencyMetrics:
nodeUUID: string
baselineP50NS: integer
baselineP99NS: integer
baselineMeasuredAt: Time
failureDomain: integer
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
StorageNode |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec StorageNodeSpec |
|||
status StorageNodeStatus |
StorageNodeOps
StorageNodeOps is a one-shot operational CR targeting a single StorageNode. Analogous to a Kubernetes Job — it drives an action (shutdown, restart, suspend, resume, remove/drain) to completion and records the result. Only one StorageNodeOps can be active per StorageNode at a time.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: StorageNodeOps
metadata:
name: string
spec:
storageNodeRef: string
action: string
targetWorkerNode: string
force: boolean
reattachVolume: boolean
newSsdPcie:
- string
drain:
systemVolumeFilterRegex: string
status:
phase: StorageNodeOpsPhase
subPhase: StorageNodeOpsSubPhase
message: string
volumesMigrated: integer
volumesPending: integer
triggered: boolean
startedAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
StorageNodeOps |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec StorageNodeOpsSpec |
|||
status StorageNodeOpsStatus |
StorageNodeOpsPhase
Underlying type: string
StorageNodeOpsPhase is the lifecycle phase of a StorageNodeOps.
Validation: - Enum: [Pending Running Succeeded Failed]
Appears in: - StorageNodeOpsStatus
| Field | Description |
|---|---|
Pending |
|
Running |
|
Succeeded |
|
Failed |
StorageNodeOpsSpec
StorageNodeOpsSpec defines the desired state of a StorageNodeOps.
Appears in: - StorageNodeOps
Example:
storageNodeRef: string
action: string
targetWorkerNode: string
force: boolean
reattachVolume: boolean
newSsdPcie:
- string
drain:
systemVolumeFilterRegex: string
| Field | Description | Default | Validation |
|---|---|---|---|
storageNodeRef string |
StorageNodeRef is the name of the target StorageNode. Immutable. | Required: {} |
|
action string |
Action is the operation to perform. Immutable. | Enum: [shutdown restart suspend resume remove migrate] Required: {} |
|
targetWorkerNode string |
TargetWorkerNode is the Kubernetes worker hostname the storage node is relocated onto. Required (and only used) when action=migrate. A migration is NOT a drain/remove: the storage node keeps its backend UUID and its partition / logical-volume assignments follow it. The operator issues a control-plane restart pointed at the target host's storage-node-api (node_address), waits for the node to come back online there, then /promotes it (starting a rebalance) and re-points the StorageNode's spec.workerNode and the owning StorageNodeSet.workerNodes from the source worker to this one. No fresh storage node is provisioned and no VolumeMigration CRs are created. Immutable. |
Optional: {} |
|
force boolean |
Force enables forced execution where the backend supports it. | Optional: {} |
|
reattachVolume boolean |
ReattachVolume reattaches volumes during the node restart. Applicable when action=restart or action=migrate. |
Optional: {} |
|
newSsdPcie string array |
NewSsdPcie lists additional NVMe PCIe addresses to bind on the target host during a migration. Passed through to the control-plane restart as new_ssd_pcie. Only applicable when action=migrate. |
Optional: {} |
|
drain DrainOpsSpec |
Drain configures the drain workflow. Only applicable when action=remove. | Optional: {} |
StorageNodeOpsStatus
StorageNodeOpsStatus holds the observed state of a StorageNodeOps.
Appears in: - StorageNodeOps
Example:
phase: StorageNodeOpsPhase
subPhase: StorageNodeOpsSubPhase
message: string
volumesMigrated: integer
volumesPending: integer
triggered: boolean
startedAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
phase StorageNodeOpsPhase |
Phase is the high-level lifecycle phase. | Enum: [Pending Running Succeeded Failed] Optional: {} |
|
subPhase StorageNodeOpsSubPhase |
SubPhase tracks the active drain step when action=remove and phase=Running. | Enum: [Validating Suspending Migrating Verifying Removing Preparing Restarting Promoting] Optional: {} |
|
message string |
Message is a human-readable description of the current state or failure reason. | Optional: {} |
|
volumesMigrated integer |
VolumesMigrated is the count of volumes successfully migrated (drain only). | Optional: {} |
|
volumesPending integer |
VolumesPending is the count of volumes awaiting migration (drain only). | Optional: {} |
|
triggered boolean |
Triggered indicates the backend action POST has been sent (used during Suspending to avoid duplicate POSTs across reconcile iterations). |
Optional: {} |
|
startedAt Time ⧉ |
StartedAt is when the operation began. | Optional: {} |
|
completedAt Time ⧉ |
CompletedAt is when the operation finished (successfully or not). | Optional: {} |
StorageNodeOpsSubPhase
Underlying type: string
StorageNodeOpsSubPhase is the active sub-phase during a running op: the drain steps when action=remove, and the Preparing → Migrating → Promoting steps when action=migrate.
Validation: - Enum: [Validating Suspending Migrating Verifying Removing Preparing Restarting Promoting]
Appears in: - StorageNodeOpsStatus
| Field | Description |
|---|---|
Validating |
|
Suspending |
|
Migrating |
|
Verifying |
|
Removing |
|
Preparing |
StorageNodeOpsSubPhasePreparing marks that a migrate op is preparing the target worker: cloning per-node config, labeling it into the storage plane, and waiting until its storage-node-api pod is Ready and its per-pod DNS name is published in the EndpointSlice — the precondition for the control-plane restart to resolve node_address. |
Restarting |
StorageNodeOpsSubPhaseRestarting marks that a migrate op has issued the control-plane restart and confirmed the node entered in_restart; it is now waiting for the node to come back online on the target host. The restart is asynchronous, so the op only advances to Promoting after the node has left online (restart started) and returned to online (restart finished) — issuing /promote earlier races the in-flight restart's node writes and leaves the relocated devices stuck in "new". |
Promoting |
StorageNodeOpsSubPhasePromoting marks that a migrate op has issued the control-plane /promote for the relocated node (guards against re-promoting). |
StorageNodeOverrides
StorageNodeOverrides holds per-node configuration that overrides the parent StorageNodeSet fleet defaults for a specific worker node. Populated by the StorageNodeSetReconciler from StorageNodeSet.spec.nodeConfigs[workerNode] on every reconcile. The StorageNodeSet is the single source of truth — users should not edit this struct directly on the StorageNode.
Fields here mirror the configurable (non-immutable, non-infrastructure) fields of StorageNodeSetSpec. When a field is set here it takes precedence over the fleet default; when omitted the fleet default applies.
Appears in: - StorageNodeSetSpec - StorageNodeSpec
Example:
spdkImage: string
spdkProxyImage: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
deviceNames:
- string
enableCpuTopology: boolean
reservedSystemCPU: string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
failureDomain: integer
expand: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
spdkImage string |
SpdkImage overrides the SPDK image for this node (e.g. for phased rollouts). | Optional: {} |
|
spdkProxyImage string |
SpdkProxyImage overrides the SPDK proxy image for this node. | Optional: {} |
|
spdkSystemMemory string |
SpdkSystemMemory overrides the SPDK huge-page memory allocation for this node (e.g. "4G", "512M"). |
Pattern: ^[0-9]+(G\|GI\|GB\|GiB\|M\|MI\|MB\|MiB\|g\|gi\|gb\|gib\|m\|mi\|mb\|mib)?$ Optional: {} |
|
journalManager JournalManagerSpec |
JournalManagerSpec overrides journal manager tuning for this node. | Optional: {} |
|
pcieAllowList string array |
PcieAllowList overrides the list of PCI addresses allowed for use on this node. | Optional: {} |
|
pcieDenyList string array |
PcieDenyList overrides the list of PCI addresses excluded from use on this node. | Optional: {} |
|
pcieModel string |
PcieModel overrides the PCI model filter for this node. | Optional: {} |
|
driveSizeRange string |
DriveSizeRange overrides the drive size range filter for this node. | Optional: {} |
|
deviceNames string array |
DeviceNames explicitly defines the NVMe namespace names to use on this node (e.g. ["nvme0n1","nvme1n1"]). |
Optional: {} |
|
enableCpuTopology boolean |
EnableCpuTopology overrides topology-aware CPU handling for this node. | Optional: {} |
|
reservedSystemCPU string |
ReservedSystemCPU overrides the CPUs reserved for system workloads on this node. | Optional: {} |
|
ubuntuHost boolean |
UbuntuHost overrides the Ubuntu host OS flag for this node. | Optional: {} |
|
skipKubeletConfiguration boolean |
SkipKubeletConfiguration overrides whether kubelet configuration changes are skipped for this node. |
Optional: {} |
|
failureDomain integer |
FailureDomain is the failure-domain group index (≥ 0) for this node. Required when the parent StorageCluster has enableFailureDomains=true. Overrides StorageNodeSet.spec.nodeFailureDomains[workerNode] when both are set. |
Minimum: 0 Optional: {} |
|
expand boolean |
Expand marks this node as a cluster-expansion add. When true the backend node-add endpoint receives expand=true, triggering rebalancing behaviour appropriate for in-place cluster growth. Overrides StorageNodeSet.spec.expand. |
Optional: {} |
StorageNodePorts
StorageNodePorts groups the network port and address fields reported by the backend.
Appears in: - StorageNodeStatus
Example:
management: string
nvmeof: integer
lvol: integer
rpc: integer
| Field | Description | Default | Validation |
|---|---|---|---|
management string |
Management is the management IP address of the node. | Optional: {} |
|
nvmeof integer |
NvmeOf is the NVMe-oF fabric port. | Optional: {} |
|
lvol integer |
Lvol is the logical-volume subsystem port. | Optional: {} |
|
rpc integer |
Rpc is the RPC/management API port. | Optional: {} |
StorageNodeResources
StorageNodeResources groups compute and storage resource fields reported by the backend.
Appears in: - StorageNodeStatus
Example:
cpu: integer
memory: string
volumes: integer
devices: string
| Field | Description | Default | Validation |
|---|---|---|---|
cpu integer |
CPU is the number of SPDK CPU cores allocated to this node. | Optional: {} |
|
memory string |
Memory is the SPDK memory allocation reported by the backend. | Optional: {} |
|
volumes integer |
Volumes is the current number of logical volumes on this node. | Optional: {} |
|
devices string |
Devices is the device summary (online/total) reported by the backend. | Optional: {} |
StorageNodeSet
StorageNodeSet is the Schema for the storagenodesets API
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: StorageNodeSet
metadata:
name: string
spec:
clusterName: string
clusterImage: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
spdkImage: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
spdkProxyImage: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
mgmtIfname: string
enableJournalDevice: boolean
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
socketsToUse:
- string
nodesPerSocket: integer
dataIfname:
- string
workerNodes:
- string
openShiftCluster: boolean
openShiftMachineConfigPool: string
deviceNames:
- string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
forceFormat4K: boolean
enableCpuTopology: boolean
reservedSystemCPU: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
tolerations:
- Toleration
maxParallelNodeAdds: integer
containerResources: ResourceRequirements
initContainerResources: ResourceRequirements
imagePullPolicy: PullPolicy
nodeFailureDomains:
string: integer
expand: boolean
nodeConfigs:
string:
spdkImage: string
spdkProxyImage: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
deviceNames:
- string
enableCpuTopology: boolean
reservedSystemCPU: string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
failureDomain: integer
expand: boolean
status:
totalNodes: integer
onlineNodes: integer
offlineNodes: integer
suspendedNodes: integer
creatingNodes: integer
removedNodes: integer
nodes:
- uuid: string
health: boolean
status: string
cpu: integer
memory: string
volumes: integer
rpcPort: integer
lvolPort: integer
nvmfPort: integer
devices: string
uptime: string
hostname: string
mgmtIp: string
postedAt: Time
failureDomain: integer
drainCoordination:
- hostname: string
phase: string
startedAt: Time
message: string
activeNodeUUID: string
pendingNodeAdds:
string: Time
schedulingFailedWorkers:
string: boolean
latencyMetrics:
- nodeUUID: string
baselineP50NS: integer
baselineP99NS: integer
baselineMeasuredAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
StorageNodeSet |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec StorageNodeSetSpec |
spec defines the desired state of StorageNodeSet | Required: {} |
|
status StorageNodeSetStatus |
status defines the observed state of StorageNodeSet | Optional: {} |
StorageNodeSetSpec
StorageNodeSetSpec defines the desired state of StorageNodeSet
Appears in: - StorageNodeSet
Example:
clusterName: string
clusterImage: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
spdkImage: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
spdkProxyImage: '^($|(quay\.io/simplyblock-io|docker\.io/simplyblock|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]{64})?)$'
mgmtIfname: string
enableJournalDevice: boolean
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
socketsToUse:
- string
nodesPerSocket: integer
dataIfname:
- string
workerNodes:
- string
openShiftCluster: boolean
openShiftMachineConfigPool: string
deviceNames:
- string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
forceFormat4K: boolean
enableCpuTopology: boolean
reservedSystemCPU: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
tolerations:
- Toleration
maxParallelNodeAdds: integer
containerResources: ResourceRequirements
initContainerResources: ResourceRequirements
imagePullPolicy: PullPolicy
nodeFailureDomains:
string: integer
expand: boolean
nodeConfigs:
string:
spdkImage: string
spdkProxyImage: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
deviceNames:
- string
enableCpuTopology: boolean
reservedSystemCPU: string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
failureDomain: integer
expand: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
clusterName string |
ClusterName is the target storage cluster name. | ||
clusterImage string |
ClusterImage is the container image used for storage-node workloads. Must reference one of the trusted registries (quay.io/simplyblock-io, docker.io/simplyblock, public.ecr.aws/simply-block); digest pinning (@sha256:...) is recommended. |
Pattern: ^($\|(quay\.io/simplyblock-io\|docker\.io/simplyblock\|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]\{64\})?)$ |
|
spdkImage string |
SpdkImage is the SPDK image reference used by node services. Must reference one of the trusted registries (quay.io/simplyblock-io, docker.io/simplyblock, public.ecr.aws/simply-block); digest pinning (@sha256:...) is recommended. |
Pattern: ^($\|(quay\.io/simplyblock-io\|docker\.io/simplyblock\|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]\{64\})?)$ |
|
spdkProxyImage string |
SpdkProxyImage is the SPDK proxy image reference used by node services. Must reference one of the trusted registries (quay.io/simplyblock-io, docker.io/simplyblock, public.ecr.aws/simply-block); digest pinning (@sha256:...) is recommended. |
Pattern: ^($\|(quay\.io/simplyblock-io\|docker\.io/simplyblock\|public\.ecr\.aws/simply-block)/[a-z0-9][a-z0-9._-]*:[a-zA-Z0-9][a-zA-Z0-9._-]*(@sha256:[a-f0-9]\{64\})?)$ |
|
mgmtIfname string |
MgmtIfname is the management interface name used by storage nodes. | ||
enableJournalDevice boolean |
EnableJournalDevice dedicates a whole NVMe device to the journal manager instead of carving a journal partition out of every storage device. When true the smallest device on the node becomes the journal device, and the remaining devices are used whole; when false (the default) each device is GPT-partitioned into a journal slice plus a storage slice. |
||
journalManager JournalManagerSpec |
JournalManagerSpec configures journal manager behavior. | ||
pcieAllowList string array |
PcieAllowList is the list of PCI addresses allowed for use. | ||
pcieDenyList string array |
PcieDenyList is the list of PCI addresses excluded from use. | ||
pcieModel string |
PcieModel filters devices by PCI model. | ||
driveSizeRange string |
DriveSizeRange filters devices by size range. | ||
socketsToUse string array |
SocketsToUse restricts deployment to selected NUMA sockets. | ||
nodesPerSocket integer |
NodesPerSocket defines how many storage nodes are created per NUMA socket. | ||
dataIfname string array |
DataIfname lists data-plane network interfaces. | ||
workerNodes string array |
WorkerNodes is the set of Kubernetes worker nodes to manage. | MaxItems: 200 |
|
openShiftCluster boolean |
OpenShiftCluster indicates OpenShift-specific behavior should be enabled. | ||
openShiftMachineConfigPool string |
OpenShiftMachineConfigPool is the name of the MachineConfigPool that storage nodes belong to. Generated MachineConfig resources will carry the machineconfiguration.openshift.io/role label set to this value. Defaults to "worker" when unset. |
||
deviceNames string array |
DeviceNames explicitly defines a comma separated list of nvme namespace names like nvme0n1,nvme1n1... | ||
ubuntuHost boolean |
UbuntuHost indicates the node host OS is Ubuntu. | ||
skipKubeletConfiguration boolean |
SkipKubeletConfiguration skips kubelet configuration changes. | ||
forceFormat4K boolean |
ForceFormat4K forces 4K blocksize formatting of the NVMe device where supported. | ||
enableCpuTopology boolean |
EnableCpuTopology enables topology-aware CPU handling. | ||
reservedSystemCPU string |
ReservedSystemCPU defines CPUs reserved for system workloads. | ||
spdkSystemMemory string |
SpdkSystemMemory is the amount of memory reserved for SPDK system use (e.g. "4G", "512M"). When omitted the backend default is used. |
Pattern: ^[0-9]+(G\|GI\|GB\|GiB\|M\|MI\|MB\|MiB\|g\|gi\|gb\|gib\|m\|mi\|mb\|mib)?$ |
|
tolerations Toleration ⧉ array |
Tolerations configures pod tolerations for storage-node pods. | ||
maxParallelNodeAdds integer |
MaxParallelNodeAdds limits how many non-FDB worker nodes can be in the add process simultaneously. Defaults to 1 (fully sequential). FDB workers are always sequential regardless of this setting. |
1 | Minimum: 1 |
containerResources ResourceRequirements ⧉ |
ContainerResources sets CPU and memory requests/limits for the main storage-node container. When omitted no limits are enforced, which preserves the previous behaviour. |
||
initContainerResources ResourceRequirements ⧉ |
InitContainerResources sets CPU and memory requests/limits for the init container. When omitted no limits are enforced. |
||
imagePullPolicy PullPolicy ⧉ |
ImagePullPolicy controls when the container image is pulled. Defaults to IfNotPresent. | Enum: [Always Never IfNotPresent] |
|
nodeFailureDomains object (keys:string, values:integer) |
NodeFailureDomains assigns each worker node to a failure-domain group (integer ≥ 0). Required when the referenced StorageCluster has enableFailureDomains=true. Keys are Kubernetes worker node names; values are the failure-domain group index. Each node in the same physical failure domain (rack, AZ, power unit) should share the same group index so the control plane can spread erasure-coding chunks across independent fault groups. |
Optional: {} |
|
expand boolean |
Expand indicates that storage nodes added from this StorageNodeSet are being added to expand an already-active cluster. When true the backend node-add endpoint receives expand=true, which triggers the appropriate rebalancing behaviour for in-place cluster growth. |
Optional: {} |
|
nodeConfigs object (keys:string, values:StorageNodeOverrides) |
NodeConfigs allows per-worker-node configuration overrides keyed by the Kubernetes worker node name. Entries are propagated to the corresponding StorageNode.spec.overrides by the StorageNodeReconciler on every reconcile. The StorageNodeSet is the single source of truth for all per-node config, including failure domain assignment via nodeConfigs[worker].failureDomain. |
MaxProperties: 200 Optional: {} |
StorageNodeSetStatus
StorageNodeSetStatus defines the observed state of StorageNodeSet.
Appears in: - StorageNodeSet
Example:
totalNodes: integer
onlineNodes: integer
offlineNodes: integer
suspendedNodes: integer
creatingNodes: integer
removedNodes: integer
nodes:
- uuid: string
health: boolean
status: string
cpu: integer
memory: string
volumes: integer
rpcPort: integer
lvolPort: integer
nvmfPort: integer
devices: string
uptime: string
hostname: string
mgmtIp: string
postedAt: Time
failureDomain: integer
drainCoordination:
- hostname: string
phase: string
startedAt: Time
message: string
activeNodeUUID: string
pendingNodeAdds:
string: Time
schedulingFailedWorkers:
string: boolean
latencyMetrics:
- nodeUUID: string
baselineP50NS: integer
baselineP99NS: integer
baselineMeasuredAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
totalNodes integer |
TotalNodes is the total number of owned StorageNode CRs. | Optional: {} |
|
onlineNodes integer |
OnlineNodes is the count of StorageNode CRs with status "online". | Optional: {} |
|
offlineNodes integer |
OfflineNodes is the count of StorageNode CRs with status "offline". | Optional: {} |
|
suspendedNodes integer |
SuspendedNodes is the count of StorageNode CRs with status "suspended". | Optional: {} |
|
creatingNodes integer |
CreatingNodes is the count of StorageNode CRs with status "in_creation". | Optional: {} |
|
removedNodes integer |
RemovedNodes is the count of StorageNode CRs with status "removed". | Optional: {} |
|
nodes NodeStatus array |
Nodes is the observed state of each managed storage node. | ||
drainCoordination NodeDrainState array |
DrainCoordination tracks the upgrade-drain state per worker node. | ||
pendingNodeAdds object (keys:string, values:Time ⧉) |
PendingNodeAdds records the timestamp when a node-add POST was sent for each worker hostname. Entries are removed only when all socket nodes for that worker come online. This is the authoritative guard against duplicate POSTs — it is a separate map field so patches to Status.Nodes never inadvertently delete it. |
||
schedulingFailedWorkers object (keys:string, values:boolean) |
SchedulingFailedWorkers tracks worker hostnames whose SPDK pod experienced a FailedScheduling event during node add. Used to emit a recovery event when the node subsequently comes online. |
||
latencyMetrics NodeLatencyMetrics array |
LatencyMetrics holds per-backend-node fio-measured latency data for rebalancing decisions. |
StorageNodeSpec
StorageNodeSpec defines the desired state of a StorageNode.
Appears in: - StorageNode
Example:
storageNodeSetRef: string
workerNode: string
socketId: string
nodeIndex: integer
socketIndex: integer
overrides:
spdkImage: string
spdkProxyImage: string
spdkSystemMemory: '^[0-9]+(G|GI|GB|GiB|M|MI|MB|MiB|g|gi|gb|gib|m|mi|mb|mib)?$'
journalManager:
count: integer
percentPerDevice: integer
pcieAllowList:
- string
pcieDenyList:
- string
pcieModel: string
driveSizeRange: string
deviceNames:
- string
enableCpuTopology: boolean
reservedSystemCPU: string
ubuntuHost: boolean
skipKubeletConfiguration: boolean
failureDomain: integer
expand: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
storageNodeSetRef string |
StorageNodeSetRef is the name of the owning StorageNodeSet. Immutable. | Required: {} |
|
workerNode string |
WorkerNode is the Kubernetes node hostname this StorageNode runs on. Users may not change it directly — it is re-pointed only by the operator during a node migration (StorageNodeOps action=migrate). The StorageNode validating webhook rejects user-driven changes to this field. |
Required: {} |
|
socketId string |
SocketID is the NUMA socket identifier from spec.socketsToUse (e.g. "0", "1"). Immutable. | Optional: {} |
|
nodeIndex integer |
NodeIndex is the per-socket node index (0..nodesPerSocket-1). Immutable. | Optional: {} |
|
socketIndex integer |
SocketIndex is the global ordinal (socketPosition × nodesPerSocket + nodeIndex). Used internally by the operator to select the correct backend node from the RPC-port-sorted list in pollUUIDFromBackend. Immutable. |
Optional: {} |
|
overrides StorageNodeOverrides |
Overrides holds per-node configuration propagated from StorageNodeSet.spec.nodeConfigs[workerNode] on every reconcile. |
Optional: {} |
StorageNodeStatus
StorageNodeStatus holds the observed state of a StorageNode.
Appears in: - StorageNode
Example:
uuid: string
status: string
health: boolean
hostname: string
uptime: string
resources:
cpu: integer
memory: string
volumes: integer
devices: string
ports:
management: string
nvmeof: integer
lvol: integer
rpc: integer
postedAt: Time
activeOpsRef: string
latencyMetrics:
nodeUUID: string
baselineP50NS: integer
baselineP99NS: integer
baselineMeasuredAt: Time
failureDomain: integer
| Field | Description | Default | Validation |
|---|---|---|---|
uuid string |
UUID is the backend storage node UUID. Set once after node-add completes. | Optional: {} |
|
status string |
Status is the backend-reported node status (e.g. online, suspended, offline). | Optional: {} |
|
health boolean |
Health is the backend-reported node health flag. | Optional: {} |
|
hostname string |
Hostname is the node hostname as reported by the backend. | Optional: {} |
|
uptime string |
Uptime is the node uptime as reported by the backend. | Optional: {} |
|
resources StorageNodeResources |
Resources groups compute and storage resource metrics. | Optional: {} |
|
ports StorageNodePorts |
Ports groups network connectivity fields (addresses and ports). | Optional: {} |
|
postedAt Time ⧉ |
PostedAt is the timestamp when the node-add POST was sent. Used as a provisioning guard against duplicate POSTs. |
Optional: {} |
|
activeOpsRef string |
ActiveOpsRef is the name of the currently active StorageNodeOps CR targeting this node. Empty when no operation is in progress. Used for mutual exclusion. |
Optional: {} |
|
latencyMetrics NodeLatencyMetrics |
LatencyMetrics holds the fio-measured baseline NVMe-oF latency for this node, used by the volume rebalancer to make data-placement decisions. |
Optional: {} |
|
failureDomain integer |
FailureDomain is the effective failure-domain group index for this node as reported by the backend (≥ 0). Nil when the backend has not assigned one. |
Optional: {} |
StoragePool
StoragePool is the Schema for the storagepools API
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: StoragePool
metadata:
name: string
spec:
clusterName: string
status: string
capacityLimit: string
logicalVolumeMaxSize: string
dhchap: boolean
allowedNodes:
- string
qos:
iops: integer
throughput:
read: integer
readWrite: integer
write: integer
action: string
storageClassParameters:
qosRwIops: string
qosRwMbytes: string
qosRMbytes: string
qosWMbytes: string
encryption: boolean
fabric: string
maxNamespacePerSubsys: string
tune2fsReservedBlocks: string
filesystem: string
status:
uuid: string
status: string
qos:
host: string
iops: integer
throughput:
read: integer
readWrite: integer
write: integer
allowedNodes:
- string
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
StoragePool |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec StoragePoolSpec |
spec defines the desired state of StoragePool | Required: {} |
|
status StoragePoolStatus |
status defines the observed state of StoragePool | Optional: {} |
StoragePoolQoSSpec
StoragePoolQoSSpec defines pool QosSpec limits.
Appears in: - StoragePoolSpec
Example:
iops: integer
throughput:
read: integer
readWrite: integer
write: integer
| Field | Description | Default | Validation |
|---|---|---|---|
iops integer |
IOPS is the IOPS limit for the pool. | ||
throughput StoragePoolQoSThroughputSpec |
Throughput contains throughput limits for the pool. |
StoragePoolQoSStatus
StoragePoolQoSStatus defines observed pool QosSpec values.
Appears in: - StoragePoolStatus
Example:
host: string
iops: integer
throughput:
read: integer
readWrite: integer
write: integer
| Field | Description | Default | Validation |
|---|---|---|---|
host string |
Host is the backend host handling pool QosSpec enforcement. | ||
iops integer |
IOPS is the observed/configured IOPS value. | ||
throughput StoragePoolQoSThroughputStatus |
Throughput contains observed/configured throughput values. |
StoragePoolQoSThroughputSpec
StoragePoolQoSThroughputSpec defines throughput QosSpec limits in MiB/s.
Appears in: - StoragePoolQoSSpec
Example:
read: integer
readWrite: integer
write: integer
| Field | Description | Default | Validation |
|---|---|---|---|
read integer |
Read is the read throughput limit for the pool. | ||
readWrite integer |
ReadWrite is the combined read/write throughput limit for the pool. | ||
write integer |
Write is the write throughput limit for the pool. |
StoragePoolQoSThroughputStatus
StoragePoolQoSThroughputStatus defines observed throughput QosSpec values in MiB/s.
Appears in: - StoragePoolQoSStatus
Example:
read: integer
readWrite: integer
write: integer
| Field | Description | Default | Validation |
|---|---|---|---|
read integer |
Read is the observed/configured read throughput value. | ||
readWrite integer |
ReadWrite is the observed/configured combined read/write throughput value. | ||
write integer |
Write is the observed/configured write throughput value. |
StoragePoolSpec
StoragePoolSpec defines the desired state of StoragePool
Appears in: - StoragePool
Example:
clusterName: string
status: string
capacityLimit: string
logicalVolumeMaxSize: string
dhchap: boolean
allowedNodes:
- string
qos:
iops: integer
throughput:
read: integer
readWrite: integer
write: integer
action: string
storageClassParameters:
qosRwIops: string
qosRwMbytes: string
qosRMbytes: string
qosWMbytes: string
encryption: boolean
fabric: string
maxNamespacePerSubsys: string
tune2fsReservedBlocks: string
filesystem: string
| Field | Description | Default | Validation |
|---|---|---|---|
clusterName string |
ClusterName is the target storage cluster name. | ||
status string |
Status is an optional desired-status hint for backend workflows. FIXME: Unused for now |
||
capacityLimit string |
CapacityLimit is the maximum aggregate capacity that can be allocated from this pool. This maps to sbctl pool add --pool-max. Use sizes like 20M, 20G, or 0 for unlimited. |
||
logicalVolumeMaxSize string |
LogicalVolumeMaxSize is the maximum size allowed for any single logical volume created in this pool. This maps to sbctl pool add --lvol-max. Use sizes like 20M, 20G, or 0 for unlimited. |
||
dhchap boolean |
DHCHAP enables DH-HMAC-CHAP key generation for the pool. Authentication is only enforced when allowedNodes is non-empty. Also controls whether the StoragePool's StorageClass gets an allowedTopologies restriction, which — like StorageClass Parameters — is immutable in the Kubernetes API, hence this field is immutable too. |
false | |
allowedNodes string array |
AllowedNodes is the list of Kubernetes worker node names allowed to access volumes in this pool. The operator resolves each node name to a deterministic NQN derived from the node's UID: nqn.2014-08.io.simplyblock:uuid: The CSI node uses the same formula so no manual NQN management is required. |
||
qos StoragePoolQoSSpec |
QosSpec defines QosSpec limits for the pool. | ||
action string |
Action triggers an imperative pool operation. FIXME: Unused for now |
||
storageClassParameters StorageClassParameters |
StorageClassParameters sets default StorageClass parameter values for volumes in this pool. Immutable: the underlying StorageClass's Parameters/AllowedTopologies cannot be patched in the Kubernetes API once created, so there is no supported way to change these after the fact. Create a new StoragePool to provision volumes with different settings. |
{ } |
StoragePoolStatus
StoragePoolStatus defines the observed state of StoragePool.
Appears in: - StoragePool
Example:
uuid: string
status: string
qos:
host: string
iops: integer
throughput:
read: integer
readWrite: integer
write: integer
allowedNodes:
- string
| Field | Description | Default | Validation |
|---|---|---|---|
uuid string |
UUID is the backend pool UUID. | ||
status string |
Status is the backend lifecycle status. | ||
qos StoragePoolQoSStatus |
QoS contains observed/configured QoS values. | ||
allowedNodes string array |
AllowedNodes lists the Kubernetes node names currently registered on the backend. |
StripeSpec
Appears in: - StorageClusterSpec
Example:
dataChunks: integer
parityChunks: integer
| Field | Description | Default | Validation |
|---|---|---|---|
dataChunks integer |
DataChunks defines the number of data chunks in the erasure-coding layout. | ||
parityChunks integer |
ParityChunks defines the number of parity chunks in the erasure-coding layout. |
Task
Task is the Schema for the tasks API
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: Task
metadata:
name: string
spec:
clusterName: string
taskID: string
subtasks: boolean
status:
tasks:
- uuid: string
taskType: string
taskStatus: string
taskResult: string
canceled: boolean
parentTask: string
startedAt: Time
retried: integer
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
Task |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
Optional: {} |
|
spec TaskSpec |
spec defines the desired state of Task | Required: {} |
|
status TaskStatus |
status defines the observed state of Task | Optional: {} |
TaskEntry
Appears in: - TaskStatus
Example:
uuid: string
taskType: string
taskStatus: string
taskResult: string
canceled: boolean
parentTask: string
startedAt: Time
retried: integer
| Field | Description | Default | Validation |
|---|---|---|---|
uuid string |
UUID is the backend task UUID. | ||
taskType string |
TaskType is the backend task function/type name. | ||
taskStatus string |
TaskStatus is the backend lifecycle status for the task. | ||
taskResult string |
TaskResult is the backend result payload/message. | ||
canceled boolean |
Canceled indicates whether the task was canceled. | ||
parentTask string |
ParentTask is the parent task UUID when this task is a subtask. FIXME: Unused for now |
||
startedAt Time ⧉ |
StartedAt is the backend-reported task start timestamp. FIXME: Unused for now |
||
retried integer |
Retried is the number of retry attempts made for the task. |
TaskSpec
TaskSpec defines the desired state of Task
Appears in: - Task
Example:
clusterName: string
taskID: string
subtasks: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
clusterName string |
ClusterName is the target storage cluster name. | ||
taskID string |
TaskID filters results to a specific backend task when set. | ||
subtasks boolean |
Subtasks includes related child subtasks when supported by the backend. FIXME: Unused for now |
TaskStatus
TaskStatus defines the observed state of Task.
Appears in: - Task
Example:
tasks:
- uuid: string
taskType: string
taskStatus: string
taskResult: string
canceled: boolean
parentTask: string
startedAt: Time
retried: integer
| Field | Description | Default | Validation |
|---|---|---|---|
tasks TaskEntry array |
Tasks is the currently reported task list for the query scope. |
ValidationJob
ValidationJob is one NVMe path-validation Job and the worker node it runs on. The node is a consumer of some volume in the migrated subsystem — the volume named in the spec, or one of its siblings sharing the same NVMe subsystem.
Appears in: - VolumeMigrationStatus
Example:
node: string
jobName: string
succeeded: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
node string |
Node is the Kubernetes node name the Job is pinned to. | ||
jobName string |
JobName is the name of the Job object in the VolumeMigration's namespace. | ||
succeeded boolean |
Succeeded records that this node's validation passed. It is kept because the Job's own existence is not a reliable record: Jobs are reaped, and re-reading a reaped Job would otherwise look like "never validated" and start it again. |
Optional: {} |
VolumeAutoPlacementSettings
VolumeAutoPlacementSettings controls the automatic, latency-driven volume rebalancing behaviour. It is configured under StorageClusterSpec.VolumeAutoPlacement.
Appears in: - StorageClusterSpec
Example:
enabled: boolean
migrationEnabled: boolean
evaluationInterval: Duration
imbalanceThreshold: integer
minHotColdDifferencePct: integer
defaultCoolDownSeconds: integer
maxVolumeMigrationsPerCycle: integer
storageNodeCandidateCount: integer
metricsBackend: MetricsBackend
prometheusURL: string
latencyBenchmarkEnabled: boolean
latencyBenchmarkInterval: Duration
iopsWeight: float
throughputWeight: float
| Field | Description | Default | Validation |
|---|---|---|---|
enabled boolean |
Enabled activates automatic rebalancing for this cluster. Defaults to false. | Optional: {} |
|
migrationEnabled boolean |
MigrationEnabled controls whether the rebalancer actually creates VolumeMigration CRs. When false the rebalancer still runs every cycle — evaluating load, computing deviations, selecting candidates and emitting metrics — but discards the migrations instead of creating them (dry-run). Defaults to true. |
Optional: {} |
|
evaluationInterval Duration ⧉ |
EvaluationInterval is how often the rebalancer evaluates load. Defaults to 60s. | Optional: {} |
|
imbalanceThreshold integer |
ImbalanceThreshold is the minimum latency deviation from baseline (in percent) that a node must exhibit before it is considered a rebalancing source. Defaults to 80. |
Optional: {} |
|
minHotColdDifferencePct integer |
MinHotColdDifferencePct is the minimum latency-deviation gap (in percentage points) that a candidate target node must be below the hot source node before a migration is performed. Prevents migrating between near-equally-loaded nodes. Defaults to 20. |
Optional: {} |
|
defaultCoolDownSeconds integer |
DefaultCoolDownSeconds is the cool-down period (seconds) applied to a volume after it has been migrated. Defaults to 600. |
Optional: {} |
|
maxVolumeMigrationsPerCycle integer |
MaxVolumeMigrationsPerCycle is the maximum number of volumes moved per cycle. Defaults to 10. | Optional: {} |
|
storageNodeCandidateCount integer |
StorageNodeCandidateCount is the number of top-loaded nodes evaluated each cycle to find the best migration source. Defaults to 3. |
Optional: {} |
|
metricsBackend MetricsBackend |
MetricsBackend selects the data source for I/O metrics. Defaults to "prometheus". | Enum: [controlplane prometheus uniform] Optional: {} |
|
prometheusURL string |
PrometheusURL is required when MetricsBackend is "prometheus". | Optional: {} |
|
latencyBenchmarkEnabled boolean |
LatencyBenchmarkEnabled enables fio-based NVMe-oF latency measurement via Kubernetes Jobs. Defaults to false; set to true once a RebalancerImage is configured. |
Optional: {} |
|
latencyBenchmarkInterval Duration ⧉ |
LatencyBenchmarkInterval is how often fio benchmark Jobs run against each storage node. Defaults to 5m. |
Optional: {} |
|
iopsWeight float |
IOPSWeight is the weight applied to per-volume IOPS in the volume IO score. Defaults to 1.0. | Optional: {} |
|
throughputWeight float |
ThroughputWeight is the weight applied to per-volume throughput (MB/s) in the volume IO score. Defaults to 0.1. |
Optional: {} |
VolumeMigration
VolumeMigration triggers a storage-node migration for a single PersistentVolume. Create a VolumeMigration to move a volume's backing logical volume to a different storage node. The controller resolves the PV to a logical volume UUID, submits the migration via the storage API, and tracks progress until completion or failure. Set spec.abort=true to cancel an in-progress migration.
Example:
apiVersion: storage.simplyblock.io/v1alpha1
kind: VolumeMigration
metadata:
name: string
spec:
pvName: string
targetNodeUUID: string
abort: boolean
status:
phase: VolumeMigrationPhase
migrationUUID: string
clusterUUID: string
volumeUUID: string
poolUUID: string
subsystemNQN: string
sourceNodeUUID: string
memberCount: integer
errorMessage: string
connections:
- nqn: string
ip: string
port: integer
transport: string
nrIoQueues: integer
reconnectDelay: integer
ctrlLossTmo: integer
fastIOFailTmo: integer
keepAliveTmo: integer
validationJobs:
- node: string
jobName: string
succeeded: boolean
deferredSince: Time
startedAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
apiVersion string |
storage.simplyblock.io/v1alpha1 |
||
kind string |
VolumeMigration |
||
metadata ObjectMeta ⧉ |
Refer to Kubernetes API documentation for fields of metadata. |
||
spec VolumeMigrationSpec |
|||
status VolumeMigrationStatus |
VolumeMigrationPhase
Underlying type: string
VolumeMigrationPhase describes the lifecycle state of a VolumeMigration.
Appears in: - VolumeMigrationStatus
| Field | Description |
|---|---|
Pending |
VolumeMigrationPhasePending means the migration has been accepted but not yet submitted to the storage API. |
Validating |
VolumeMigrationPhaseValidating means CreateMigration has been called and the operator is validating the new NVMe-oF connection paths on the target node before calling ContinueMigration. |
Running |
VolumeMigrationPhaseRunning means ContinueMigration has been called and the data migration is in progress. |
Completed |
VolumeMigrationPhaseCompleted means the migration finished successfully. |
Failed |
VolumeMigrationPhaseFailed means the migration finished with an error. |
Aborted |
VolumeMigrationPhaseAborted means the migration was cancelled via spec.abort. |
VolumeMigrationSettings
VolumeMigrationSettings carries cluster-level settings for volume migration. Automatic load-based rebalancing is configured separately via StorageClusterSpec.VolumeAutoPlacement, keeping the manual-migration controls separate from the rebalancing policy.
Appears in: - StorageClusterSpec
Example:
enabled: boolean
rebalancerImage: string
dataRealignment:
enabled: boolean
interval: Duration
minMoves: integer
| Field | Description | Default | Validation |
|---|---|---|---|
enabled boolean |
Enabled turns on volume migration for this cluster. When false, the operator will not act on VolumeMigration resources for this cluster. Defaults to true. |
Optional: {} |
|
rebalancerImage string |
RebalancerImage is the container image used for the volume-migration path validation Job and the rebalancer latency/baseline Jobs. The image must include nvme-cli (and, for rebalancing, fio + jq). |
Optional: {} |
|
dataRealignment DataRealignmentSettings |
DataRealignment configures the periodic control-plane data realignment that runs after volumes have been moved. Realignment re-aligns the cluster's internal data structures to the current volume placement so fault-tolerance (FTT) and node-affinity guarantees are preserved. It applies to all volume moves — auto-rebalancing, manual VolumeMigrations, and drain/removal-triggered moves — so it lives here rather than under AutoRebalancing. Enabled by default. |
Optional: {} |
VolumeMigrationSpec
VolumeMigrationSpec defines the desired state of a VolumeMigration.
Appears in: - VolumeMigration
Example:
pvName: string
targetNodeUUID: string
abort: boolean
| Field | Description | Default | Validation |
|---|---|---|---|
pvName string |
PVName is the name of the PersistentVolume whose backing logical volume should be migrated. The PV must be provisioned by the simplyblock CSI driver. |
MinLength: 1 |
|
targetNodeUUID string |
TargetNodeUUID is the UUID of the storage node that should host the volume after migration. |
MinLength: 1 |
|
abort boolean |
Abort requests cancellation of an in-progress migration. Set to true to cancel; the phase will transition to Aborted once the backend confirms. |
Optional: {} |
VolumeMigrationStatus
VolumeMigrationStatus defines the observed state of a VolumeMigration.
Appears in: - VolumeMigration
Example:
phase: VolumeMigrationPhase
migrationUUID: string
clusterUUID: string
volumeUUID: string
poolUUID: string
subsystemNQN: string
sourceNodeUUID: string
memberCount: integer
errorMessage: string
connections:
- nqn: string
ip: string
port: integer
transport: string
nrIoQueues: integer
reconnectDelay: integer
ctrlLossTmo: integer
fastIOFailTmo: integer
keepAliveTmo: integer
validationJobs:
- node: string
jobName: string
succeeded: boolean
deferredSince: Time
startedAt: Time
completedAt: Time
| Field | Description | Default | Validation |
|---|---|---|---|
phase VolumeMigrationPhase |
Phase is the current lifecycle phase of the migration. | Enum: [Pending Validating Running Completed Failed Aborted] |
|
migrationUUID string |
MigrationUUID is the identifier returned by the storage API when the migration was submitted. Used for polling and cancellation. |
||
clusterUUID string |
ClusterUUID is the storage cluster UUID resolved from the PV. | ||
volumeUUID string |
VolumeUUID is the logical volume UUID resolved from the PV's CSI volume handle. | ||
poolUUID string |
PoolUUID is the storage pool UUID that contains the volume. | ||
subsystemNQN string |
SubsystemNQN is the NQN of the volume's NVMe subsystem, resolved from the storage API when the migration is submitted. The migration is addressed by it, and every volume sharing the subsystem moves with it. |
||
sourceNodeUUID string |
SourceNodeUUID is the storage node UUID where the volume resided before migration, as reported by the storage API. |
||
memberCount integer |
MemberCount is the number of volumes (namespaces) in the migrated subsystem, as reported by the storage API. More than one means the migration moves sibling volumes along with this one. |
||
errorMessage string |
ErrorMessage holds the failure reason when Phase is Failed. | ||
connections MigrationConnection array |
Connections holds the NVMe-oF connection parameters for the new target-side paths returned by CreateMigration. Used during the Validating phase to establish and verify the paths before calling ContinueMigration, and again to release them if the migration never cuts over. These are the parameters the paths are actually connected with, not verbatim what CreateMigration answered: ctrlLossTmo is replaced with the value every path in this system uses, because a target path becomes the volume's data path at cutover. The rest is passed through. |
||
validationJobs ValidationJob array |
ValidationJobs are the Jobs that run nvme connect for each connection pathand validate ANA state before ContinueMigration is called — one per worker node that consumes a volume of the migrated subsystem. A subsystem migrates as a unit, so every consuming node must have the new paths before cutover; all of these Jobs must succeed. Set during the Validating phase; cleared when the phase advances to Running. |
||
deferredSince Time ⧉ |
DeferredSince is when the storage API first refused to accept this migration because the cluster was busy with work that ends on its own (a data realignment or another node migration). While set, the migration is being retried and has not started. It bounds the retrying: past a fixed window the migration fails rather than waiting forever. Cleared once the migration is submitted. |
||
startedAt Time ⧉ |
StartedAt is the time the migration was submitted to the storage API. | ||
completedAt Time ⧉ |
CompletedAt is the time the migration finished (successfully or not). |