Configure topology-aware volume provisioning
Learn how to use the Kubernetes Container Storage Interface (CSI) topology feature to control where volumes are provisioned based on availability zones.
In multi-zone cloud environments, this feature enhances fault tolerance and performance by limiting volume access to specific nodes within a designated region or zone. Topology-aware provisioning uses the waitForFirstConsumer
volume binding mode, which delays volume creation until Kubernetes schedules the workload. This ensures the volume is provisioned in the correct location relative to the pod that consumes it.
Prerequisites
Kubernetes v1.17 or a later version.
Topology labels on Kubernetes nodes. Most Kubernetes distributions create these labels by default during installation.
WEKA Operator v1.7.0 or a later version.
1. Confirm topology labels on Kubernetes nodes
Verify that your Kubernetes nodes have the required topology labels. The following command checks for topology.kubernetes.io/region
and topology.kubernetes.io/zone
labels on all nodes in the cluster.
$ kubectl get nodes -Ltopology.kubernetes.io/region -Ltopology.kubernetes.io/zone
Example output
NAME STATUS ROLES AGE VERSION REGION ZONE
54.160.132.190 Ready control-plane,etcd,master 46m v1.33.4+k3s1 us-east-1 us-east-1a
54.161.26.50 Ready worker 45m v1.33.4+k3s1 us-east-1 us-east-1b
54.162.121.142 Ready worker 45m v1.33.4+k3s1 us-east-1 us-east-1b
54.167.56.31 Ready control-plane,etcd,master 46m v1.33.4+k3s1 us-east-1 us-east-1a
54.235.34.153 Ready worker 45m v1.33.4+k3s1 us-east-1 us-east-1b
54.89.113.136 Ready control-plane,etcd,master 46m v1.33.4+k3s1 us-east-1 us-east-1a
In this example, the cluster has six nodes distributed across two availability zones: us-east-1a
and us-east-1b
.
2. Create a StorageClass with WaitForFirstConsumer
A StorageClass volumeBindingMode
can be set to Immediate
or WaitForFirstConsumer
. For topology-aware provisioning, you must use WaitForFirstConsumer
to delay volume creation until the consuming workload is scheduled.
The following manifest defines a StorageClass named weka-topology-aware
with the correct binding mode.
$ cat sc.yaml
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: weka-topology-aware
parameters:
capacityEnforcement: HARD
csi.storage.k8s.io/controller-expand-secret-name: weka-csi-cluster
csi.storage.k8s.io/controller-expand-secret-namespace: weka
csi.storage.k8s.io/controller-publish-secret-name: weka-csi-cluster
csi.storage.k8s.io/controller-publish-secret-namespace: weka
csi.storage.k8s.io/node-publish-secret-name: weka-csi-cluster
csi.storage.k8s.io/node-publish-secret-namespace: weka
csi.storage.k8s.io/node-stage-secret-name: weka-csi-cluster
csi.storage.k8s.io/node-stage-secret-namespace: weka
csi.storage.k8s.io/provisioner-secret-name: weka-csi-cluster
csi.storage.k8s.io/provisioner-secret-namespace: weka
filesystemName: default
volumeType: dir/v1
provisioner: csi.weka.io
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
Create the StorageClass.
$ kubectl create -f sc.yaml
storageclass.storage.k8s.io/weka-topology-aware created
3. Create a PersistentVolumeClaim (PVC)
To demonstrate the delayed binding, create a PVC without a corresponding workload.
$ cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
name: weka-pvc
namespace: weka
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: weka-topology-aware
volumeMode: Filesystem
Create the PVC.
$ kubectl create -f pvc.yaml
persistentvolumeclaim/weka-pvc created
Examine the PVC status.
$ kubectl get pvc -n weka
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
weka-pvc Pending weka-topology-aware <unset> 5s
Observe that the PVC status is Pending
. The persistentvolume-controller
waits for a workload to consume the PVC before provisioning and binding the volume.
Example description of the pending PVC
$ kubectl describe pvc -n weka
Name: weka-pvc
Namespace: weka
StorageClass: weka-topology-aware
Status: Pending
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal WaitForFirstConsumer 12s persistentvolume-controller waiting for first consumer to be created before binding
4. Define and create a workload
To trigger volume provisioning, define a workload that consumes the PVC. The following Pod manifest uses spec.affinity
to specify its preferred deployment location, ensuring it is scheduled in the correct zone.
$ cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox-weka
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values:
- us-east-1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
- us-east-1b
volumes:
- name: vol1
persistentVolumeClaim:
claimName: weka-pvc
containers:
- name: busybox
image: busybox
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: vol1
mountPath: /data/demo
Create the Pod and then check the status of both the Pod and the PVC.
$ kubectl create -f pod.yaml -n weka
pod/busybox-weka created
$ kubectl get pod,pvc -n weka -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/busybox-weka 1/1 Running 0 18s 10.32.1.9 54.89.113.136 <none> <none>
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE VOLUMEMODE
persistentvolumeclaim/weka-pvc Bound pvc-1c6fa6b1-e561-4d98-a127-2bbbb9352b87 5Gi RWX weka-topology-aware <unset> 14m Filesystem
After the Pod is scheduled and running, the PVC status changes to Bound
, indicating that the volume has been provisioned and is accessible to the Pod.
Last updated