Connecting to an External Control Plane
The simplyblock CSI driver is deployed and managed by the Simplyblock Operator through the SimplyblockDriver
resource. The separate CSI Helm chart used by earlier releases is replaced by the operator chart. For a Kubernetes
cluster that does not host its own control plane, the operator chart is installed with the managed profile. The
chart then installs the operator and the CSI driver, and the ControlPlane resource points at a management API that
runs elsewhere.
Note
For Kubernetes-native deployments where the control plane runs in the same cluster, use the default standalone
profile described in Install Simplyblock Operator.
CSI Driver System Requirements
The CSI driver consists of two parts:
- Controller plugin: Communicates with the control plane through the Management API. Runs as a StatefulSet.
- Node plugin: Attaches and mounts volumes. Runs as a DaemonSet on every node with pods that use simplyblock storage.
The workers that run the node plugin must satisfy the following requirements:
Preparing the Credentials
The managed profile needs the base URL of the remote Management API. The endpoint must not be a loopback or link-local address. Two optional Secrets in the operator's namespace complete the connection:
- Credentials Secret: Holds the bearer token for the Management API under the key
tokenorsecret. Without it, no token is sent. - CA bundle Secret: Holds the CA certificate the endpoint is verified against under the key
ca.crtortls.crt. Without it, the system trust store is used.
kubectl create namespace simplyblock
kubectl -n simplyblock create secret generic cp-token \
--from-literal=token='<MANAGEMENT-API-TOKEN>'
kubectl -n simplyblock create secret generic cp-ca \
--from-file=ca.crt=./control-plane-ca.crt
A named Secret that does not exist or cannot be used is reported as an error.
Installing With the Managed Profile
helm repo add simplyblock https://install.simplyblock.io/helm
helm repo update
helm install simplyblock-operator simplyblock/simplyblock-operator \
--namespace simplyblock \
--set deployment.profile=managed \
--set controlplane.managed.endpoint=https://cp.example.com \
--set controlplane.managed.credentialsSecretRef=cp-token \
--set controlplane.managed.caBundleSecretRef=cp-ca
The chart renders the ControlPlane resource with a managed source:
apiVersion: storage.simplyblock.io/v1alpha2
kind: ControlPlane
metadata:
name: simplyblock
namespace: simplyblock
spec:
source:
managed:
endpoint: "https://cp.example.com"
credentialsSecretRef:
name: cp-token
caBundleSecretRef:
name: cp-ca
The operator installs nothing for the control plane. It resolves and probes the endpoint and reports the result:
kubectl -n simplyblock get controlplane simplyblock
kubectl -n simplyblock get simplyblockdriver simplyblock
The ControlPlane reaches the phase Available once the endpoint answers. An unreachable endpoint is reported with
the event EndpointUnreachable. ControlPlaneOps actions are rejected for a managed control plane, because the
operator owns none of its workloads. The source (local or managed) cannot be changed after installation.
The TLS settings of the CSI driver come from the tls.* Helm values, see Securing the Control Plane. The
prometheus.enabled value can be set to false if the remote control plane collects the metrics itself.
Configuring the CSI Driver
The Helm values under driver.* are copied into the SimplyblockDriver resource. The most important fields are:
| Field | Default | Description |
|---|---|---|
driverName |
csi.simplyblock.io |
The CSI driver name. Immutable. |
image |
Operator release | The plugin image. Empty uses the image shipped with the operator release. |
controllerReplicas |
1 |
Number of controller plugin instances. |
nodeSelector, tolerations |
Placement of the node plugin. Empty runs it on every schedulable worker. | |
controllerNodeSelector, controllerTolerations |
Placement of the controller plugin. | |
enableVolumeSnapshots |
true |
Installs the VolumeSnapshotClass, and the snapshot CRDs and controller where the cluster serves none. |
enableServiceAccountAuth |
false |
Authenticates the plugins with their service account tokens instead of the static cluster secret. The control plane must trust them (controlplane.trustCSIServiceAccounts). |
sidecarImages |
Operator release | Overrides for the six CSI sidecar images. |
Storage Clusters Behind the Managed Control Plane
Storage clusters are described by StorageCluster resources in the Kubernetes cluster, regardless of where the
control plane runs. A storage cluster whose storage nodes run in this Kubernetes cluster is created from an approved
ClusterDeploymentConfig, exactly as described in Create a Storage Cluster.
For every StorageCluster, the operator writes the cluster ID, the endpoint, and the cluster secret into the Secret
simplyblock-csi-secret-v2, which the CSI driver reads. The Secret is maintained by the operator and does not need to
be edited manually.
Multi-Cluster Storage Classes
The CSI driver can serve several simplyblock clusters at once. Which cluster a volume is provisioned on is selected by the StorageClass parameters.
Cluster ID-Based Selection
Each StorageClass names one cluster with cluster_id (the cluster's status.uuid). This is ideal for setups where
workloads are directed to specific clusters.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: simplyblock-cluster1
provisioner: csi.simplyblock.io
parameters:
cluster_id: "<cluster-uuid-1>"
pool_name: "<pool-name>"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
Zone-Aware Selection
A single StorageClass selects the cluster based on the Kubernetes zone the workload is scheduled in. The parameter
zone_cluster_map maps each zone to a cluster ID, and allowedTopologies restricts provisioning to those zones.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: simplyblock-zonal
provisioner: csi.simplyblock.io
parameters:
zone_cluster_map: |
{"us-east-1a":"<cluster-uuid-1>","us-east-1b":"<cluster-uuid-2>"}
pool_name: "<pool-name>"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/zone
values:
- us-east-1a
- us-east-1b
Region-Aware Selection
The same approach works with regions. The parameter region_cluster_map maps each region to a cluster ID.
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: simplyblock-regional
provisioner: csi.simplyblock.io
parameters:
region_cluster_map: |
{"us-east-1":"<cluster-uuid-a>","us-west-2":"<cluster-uuid-b>"}
pool_name: "<pool-name>"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
allowedTopologies:
- matchLabelExpressions:
- key: topology.kubernetes.io/region
values:
- us-east-1
- us-west-2
Tip
The keys of zone_cluster_map and region_cluster_map must match the zone and region labels on the Kubernetes
nodes (typically topology.kubernetes.io/zone and topology.kubernetes.io/region). Every referenced cluster ID
must have an entry in simplyblock-csi-secret-v2.
For the full list of StorageClass parameters, see Storage Class.