Container Storage Interface

The Container Storage Interface (CSI) is a standard that enables you to use compliant block and file storage systems with containerized workloads. Kubernetes provides CSI support starting with v1.13, allowing a containerized CSI driver to interface with Kubernetes controllers in charge of the following:

  • Dynamic provisioning and deprovisioning of a volume

  • Attaching or detaching a volume from a node

  • Mounting/unmounting a volume from a node

  • Consumption of both block and mountable volumes

  • Expanding or resizing volumes

  • Creating and deleting volume point-in-time snapshots

  • Provisioning new volumes from a snapshot

Note

For more information about Kubernetes CSI, refer to the Kubernetes CSI documentation.

Starting with Diamanti v2.3.0, the default storage class uses the Diamanti CSI driver. In addition, new static volumes created using dctl commands use the CSI driver by default. You should likewise create all new storage classes in your cluster using the Diamanti CSI driver.

Use the Diamanti CSI Driver

This section provides a series of examples of how to use the Diamanti CSI driver to do the following:
  • Create a custom StorageClass object

  • Perform dynamic volume provisioning

  • Perform static volume provisioning

  • Create a pod with filesystem volumeMode

  • Create a pod with block volumeMode

  • Expand or resize a volume

  • Create a custom SnapshotClass object

  • Create a snapshot

  • Provision a new volume from a snapshot

Important: The example specification files used in this section are available at:

/usr/share/diamanti/manifests/examples/csi/

Create a Custom StorageClass Object

This section provides examples of how to create StorageClass objects that use the Diamanti CSI driver to provision volumes dynamically using the supported parameters.

Note

Volumes with a single plex or single data copy are provisioned at the time of pod creation; these volumes are not provisioned when the PVC object is created. This is known as delayed provisioning. For mirrored volumes and volumes with node selector parameters, volume is provisioned instantly during PVC object creation.

Use the sc-delayed-provisioning.yaml file as an example to create a StorageClass object to allow delayed volume provisioning. The following shows the file contents:

apiVersion: storage.k8s.io/v1 kind: StorageClass
metadata:
  name: csi-sc-delayed-provisioning
provisioner: dcx.csi.diamanti.com
reclaimPolicy: Delete
parameters:
  mirrorCount: "1"
  perfTier: "high"
  fsType: "ext4"
allowVolumeExpansion:true

Similarly, use the sc-instant-provisioning.yaml file as an example to create a StorageClass object to allow instant volume provisioning. The following shows the file contents:

apiVersion: storage.k8s.io/v1 kind: StorageClass
metadata:
  name: csi-sc-instant-provisioning
provisioner: dcx.csi.diamanti.com
reclaimPolicy: Delete
parameters:
  mirrorCount: "1"
  perfTier: "high"
  selectors:'{"node":"node1"}’
  fsType: "ext4"
allowVolumeExpansion: true

Note that the following field is required in the StorageClass specification to allow resizing of a PersistentVolumeClaim by the Diamanti CSI driver:

allowVolumeExpansion: true

Use the following kubectl command to create a StorageClass object using the Diamanti CSI driver:

kubectl create -f <storage-class-specification-file>

For example, use the following command to create a StorageClass object that allows instant volume provisioning:

kubectl create -f sc-instant-provisioning.yaml

You can use the following kubectl commands to display storage class information:

$ kubectl get storageclasses.storage.k8s.io
$ kubectl describe storageclasses.storage.k8s.io csi-sc-delayed-provisioning
$ kubectl describe storageclasses.storage.k8s.io csi-sc-instant-provisioning

Perform Dynamic Volume Provisioning

This section shows an example of how to provision volumes dynamically for the filesystem volumeMode with the Diamanti CSI driver. Note that the StorageClass (default or custom) in the PersistentVolumeClaim specification uses the Diamanti CSI driver to perform the dynamic provisioning of the volume.

Use the following PersistentVolumeClaim specification as an example to provision volumes dynamically. The following shows the contents of the pvc-filesystem-delayedprovisioning.yaml file:

apiVersion: v1
kind:PersistentVolumeClaim
metadata:
  name: csi-pvc-filesystem-delayed-provisioning
  spec:
    accessModes:     - ReadWriteOnce
    resources:
      requests:
        storage: 5Gi
    storageClassName: csi-sc-delayed-provisioning

The following shows the contents of the pvc-block-instant-provisioning.yaml file:

apiVersion: v1
kind:PersistentVolumeClaim
metadata:
  name: csi-pvc-block-instant-provisioning
spec:
  accessModes:     - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 5Gi
  storageClassName: csi-sc-instant-provisioning

Use the following kubectl command to create a PVC using the Diamanti CSI driver:

kubectl create -f <pvc-specification-file>

For example, use the following commands to create the respective PersistentVolumeClaims:

$ kubectl create -f pvc-filesystem-delayed-provisioning.yaml

$ kubectl create -f pvc-block-instant-provisioning.yaml

Perform Static Volume Provisioning

The following example shows how to provision a static volume for filesystem usage with the Diamanti CSI driver.

  1. Create the volume using the following command:

    dctl volume create <volume-name> -s <size>
    

For example:

$ dctl volume create pvc-filesystem-static -s 5Gi
  1. (Optional) Display the specification using the following command:

    $ dctl -o json volume describe pvc-filesystem-static | jq -r '.spec'
    {
      "type": "Static",
      "size": 5368709120,
      "fsType": "ext4",
      "volumeMode": "Filesystem",
      "volumeUser": "default",
      "perfTier": "best-effort",
      "plexCount": 1,
      "thinProvision": true,
      "allocRatio": 100,
      "driver": "csi"
    }
    

3.(Optional) Display information about the persistent volume using the following command:

$ kubectl get pv pvc-filesystem-static -o json | jq -r '.spec'
{
  "accessModes": [
    "ReadWriteOnce"
  ],
  "capacity": {
    "storage": "5Gi"
  },
  "csi": {
    "driver": "dcx.csi.diamanti.com",
    "fsType": "ext4",
    "volumeAttributes": {
      "name": "pvc-filesystem-static",
      "perfTier": "best-effort"
    },
    "volumeHandle": "pvc-filesystem-static"
  },
  "persistentVolumeReclaimPolicy": "Retain",
  "volumeMode": "Filesystem"
}
  1. Create a PersistentVolumeClaim object using the following command:

    kubectl create -f <pvc-specification-file>
    

For example:

$ kubectl create -f pvc-filesystem-static.yaml

For reference, the contents of the pvc-test-filesystem.yaml file is as follows:

apiVersion: v1
kind:PersistentVolumeClaim
metadata:
  name: csi-pvc-filesystem-static
spec:
  accessModes:  -ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  volumeMode: Filesystem
  volumeName: pvc-filesystem-static
  storageClassName: ""
  1. Display the PersistentVolumeClaim object using the following command:

    $ kubectl get pvc
    NAME                        STATUS   VOLUME                  CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    csi-pvc-filesystem-static   Bound    pvc-filesystem-static   5Gi        RWO                           91m
    

The following example shows how to provision a static volume for raw block device usage with the Diamanti CSI driver.

  1. Create the volume using the following command:

    dctl volume create <volume-name> -b -s <size>
    

For example:

$ dctl volume create pvc-block-static -b -s 5Gi
  1. (Optional) Display the specification using the following command:

    $ dctl -o json volume describe pvc-block-static | jq -r '.spec'
    {
      "type": "Static",
      "size": 5368709120,
      "volumeMode": "Block",
      "volumeUser": "default",
      "perfTier": "best-effort",
      "plexCount": 1,
      "thinProvision": true,
      "allocRatio": 100,
      "driver": "csi"
    }
    
  2. (Optional) Display information about the persistent volume using the following command:

    $ kubectl get pv pvc-testvol-blk -o json | jq -r '.spec'
    {
      "accessModes": [
        "ReadWriteOnce"
      ],
      "capacity": {
        "storage": "5Gi"
      },
      "csi": {
        "driver": "dcx.csi.diamanti.com",
        "volumeAttributes": {
          "name": "pvc-block-static",
          "perfTier": "best-effort"
        },
        "volumeHandle": "pvc-block-static"
      },
      "persistentVolumeReclaimPolicy": "Retain",
      "volumeMode": "Block"
    }
    
  3. Create a persistent volume claim using the following command:

    kubectl create -f <pvc-specification-file>
    

For example:

$ kubectl create -f pvc-block-static.yaml

pvc-block-static.yaml file is as follows:

apiVersion: v1
kind: PersistentVolumeClaim metadata:
  name: csi-pvc-block-static
spec:
  accessModes: -ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  volumeMode: Block
  volumeName: pvc-block-static
  storageClassName: ""
  1. Display the persistent volume claim using the following commands:

    $ kubectl get pvc
    NAME                   STATUS   VOLUME             CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    csi-pvc-block-static   Bound    pvc-block-static   5Gi        RWO                           98m
    

Create a Pod with Filesystem volumeMode

Note

Before performing the procedure in this section, ensure that you first create the PeristentVolumeClaim included in the pod specification.

  1. Create a pod with the persistent volume claim using the following command:

    kubectl create -f <pod-specification-file>
    

For example:

$ kubectl create -f pod-fs-static.yaml

pod-fs-static.yaml file is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: csi-pod-filesystem-static
spec:
  containers:
  - name: web-server
    image: nginx
    volumeMounts:
    - name: datavol-filesystem-static
      mountPath: /var/lib/www
  volumes:
    - name: datavol-filesystem-static
      persistentVolumeClaim:
        claimName: csi-pvc-filesystem-static
      readOnly: false
  1. Display the pod information using the following command:

    $ kubectl get pod
    NAME                        READY   STATUS    RESTARTS   AGE
    csi-pod-filesystem-static   1/1     Running   0          71s
    
  2. Display the mount point within the pod using the following command:

    $ kubectl exec -it csi-pod-filesystem-static -- df -kh | grep '/var/ lib/www'
    /dev/nvme1n1                       4.9G   21M  4.6G   1% /var/lib/www
    

Create a Pod with Block volumeMode

  1. Create a pod with the persistent volume claim using the following command:

    kubectl create -f <pod-specification-file>
    

For example:

$ kubectl create -f pod-blk-static.yaml

pod-blk-static.yaml file is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: csi-pod-block-static
spec:
  containers:
  - name: web-server
    image: nginx
    volumeDevices:
    - devicePath: /dev/vdisk1
      name: datavol-block-static
  volumes:
  - name: datavol-block-static
    persistentVolumeClaim:
      claimName: csi-pvc-block-static
      readOnly: false
  1. Display the pod information using the following command:

    $ kubectl get pod
    NAME                    READY   STATUS    RESTARTS   AGE
    csi-pod-block-static    1/1     Running   0          73m
    
  2. Display the raw block device within the pod using the following command:

    $ kubectl exec -it csi-pod-block-static -- lsblk /dev/vdisk1 NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme1n1 259:0    0   5G  0 disk
    

Expand or Resize a Volume

Note

Before performing the procedure in this section, ensure that you first create a storageClass object that uses the Diamanti CSI driver as described in Create a Custom StorageClass Object.

To expand or resize a volume, do the following:

  1. Bring down the pod to allow a volume to be resized offline. Use the following kubectl command:

    kubectl delete pod <pod-name>
    

For example:

$ kubectl delete pod csi-pod-filesystem-instant-provisioning
  1. Expand the PersistentVolumeClaim using the following command:

    kubectl patch pvc <pvc-name> -p '{ "spec":
    

    { “resources”: { “requests”: { “storage”: “<new-volume-size>” }}}}’

For example:

$ kubectl patch pvc csi-pvc-filesystem-instant-provisioning
-p '{ "spec": { "resources": { "requests": { "storage": "8Gi" }}}}'
  1. Verify the updated PersistentVolumeClaim resource storage capacity using the following command:

    kubectl get pvc <pvc-name>
    

For example:

$ kubectl get pvc csi-pvc-filesystem-instant-provisioning
  1. Start the pod using the following command:

    kubectl create -f <pod-name>
    

For example:

$ kubectl create -f pod-fs-instant-provisioning.yaml
  1. Verify the updated filesystem size within the container using the following command:

    kubectl exec -it <pod-name> -- /bin/bash
    

Note

After resize the targeted node goes into pending state for some time.

Create a Custom SnapshotClass Object

Use the csi-snapshotclass.yaml file as an example to create a SnapshotClass object. The following shows the file contents:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: default-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
driver: dcx.csi.diamanti.com
deletionPolicy: Delete

Use the following kubectl command to create a snapshot class using the Diamanti CSI driver:

$ kubectl create -f csi-snapshotclass.yaml

You can use the following kubectl commands to display snapshot class information:

$ kubectl get volumesnapshotclasses.snapshot.storage.k8s.io
$ kubectl describe volumesnapshotclasses.snapshot.storage.k8s.io csisnapshotclass

Create a Snapshot

This section provide an example of how to create a snapshot.

Before performing the procedure in this section, ensure that the default SnapshotClass object default-snapclass is already created. You can also optionally create a custom SnapshotClass object using the Kubernetes CLI or Kubernetes API, but the Diamanti default-snapclass generally serves all purposes for creating volume snapshots.

Note

Diamanti offers the default-snapclass for creating snapshots in cases when the snapshot specification does not contain a snapshotClassName field.

Use the following command to verify that the default SnapshotClass object defaultsnapclass is already created and exists.

$ kubectl get volumesnapshotclasses.snapshot.storage.k8s.io defaultsnapclass
  NAME          AGE
  default-snapclass   7h24m

The following shows the default SnapshotClass specification file contents:

$ cat /usr/share/diamanti/manifests/system/csisnapshotclass.yaml
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: default-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
driver: dcx.csi.diamanti.com
deletionPolicy: Delete

To create a snapshot, do the following:

  1. Use the pvc-filesystem-snapshot.yaml file as an example to create a snapshot. The following shows the file contents:

    $ cat /usr/share/diamanti/manifests/examples/csi/snapshot/filesystem/pvc-filesystem-snapshot.yaml
    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: csi-pvc-filesystem-snapshot
    spec:
      volumeSnapshotClassName: csi-snapshotclass
      source:
    
  2. Create a snapshot with the Diamanti CSI driver using the following kubectl command:

    kubectl create -f <snapshot-specification-file>
    

For example, use the following command to create a snapshot of a PersistentVolumeClaim:

$ kubectl create -f pvc-filesystem-snapshot.yaml
  1. (Optional) Display snapshot information using the following kubectl commands:

    $ kubectl get volumesnapshots.snapshot.storage.k8s.io csi-pvcfilesystem-snapshot
    
    $ kubectl describe volumesnapshots.snapshot.storage.k8s.io csi-pvcfilesystem-snapshot
    

Provision a New Volume from a Snapshot

Use the pvc-filesystem-newvol-lcv.yaml file as an example to create a new

PersistentVolumeClaim object from a volume snapshot. In the following example, the new PVC is created using a snapshot named csi-pvc-filesystem-snapshot as the data source.

The following shows the file contents:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-pvc-filesystem-lcv
  spec:
    storageClassName: csi-sc-instant-provisioning
    dataSource:
      name: csi-pvc-filesystem-snapshot

kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Use the following kubectl command to create a new PersistentVolumeClaim object from a snapshot using the Diamanti CSI driver:

kubectl create -f <specification-file>

You can use the following kubectl commands to display the PersistentVolumeClaim object being created using the snapshot:

$ kubectl get pvc csi-pvc-filesystem-lcv

$ kubectl describe pvc csi-pvc-filesystem-lcv