vSphere Container Storage Plug-in supports volume expansion only for block volumes that are created dynamically or statically.

Kubernetes supports offline and online modes of volume expansion. When the PVC is used by a pod and is mounted on a node, the volume expansion operation is categorized as online. In all other cases, it is an offline expansion.

The following table shows the minimum versions of vSphere Container Storage Plug-in, vCenter Server, and ESXi that support volume expansion.
Feature Minimum vSphere Container Storage Plug-in Version Minimum vCenter Server Version Minimum ESXi Version
Offline volume expansion v2.0 7.0 7.0
Online volume expansion v2.2 7.0 Update 2 7.0 Update 2
Ensure that all ESXi hosts of the cluster are of the same version as vCenter Server. For volume expansion to work, vCenter Server and all ESXi hosts of the cluster must be of the vSphere version 7.0 and later. Otherwise, volume resize operation fails with A general system error occurred: Failed to lock the file: api = DiskLib_Grow error.

For more information, see Compatibility Matrix for vSphere Container Storage Plug-in.

The following considerations apply when you use volume expansion:

Feature Gate
Expand CSI Volumes feature is enabled by default since it was promoted to beta in Kubernetes 1.16. For Kubernetes releases before 1.16, enable Expand CSI Volumes feature gate to support volume expansion in CSI plug-in.
Sidecar Container
An external resizer sidecar container implements the logic of watching the Kubernetes API for PVC edits, issuing the ControllerExpandVolume RPC call against a CSI endpoint, and updating the PersistentVolume object to reflect the new size. This container is already deployed as part of the vsphere-csi-controller pod.

Procedure

  1. Create a PVC.
    1. Create a new StorageClass or edit the existing StorageClass to set allowVolumeExpansion to true.
      kind: StorageClass
      apiVersion: storage.k8s.io/v1
      metadata:
        name: example-block-sc
      provisioner: csi.vsphere.vmware.com
      allowVolumeExpansion: true
    2. Create or edit a PVC that references the StorageClass.
    Ensure that the PVC is in bound state. If you are using a statically provisioned PVC, ensure that the PVC and the PV specifications have the storageClassName parameter pointing to the StorageClass with the allowVolumeExpansion set to true.
  2. Expand the PVC in online or offline mode.
    Option Description
    To expand PVC in online mode, deploy a PVC with a StorageClass where the allowVolumeExpansion parameter is set to true. Later, create a pod to use this PVC.
    $ kubectl get pvc,pv,pod
    NAME                                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS           AGE
    persistentvolumeclaim/example-block-pvc   Bound    pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd   1Gi        RWO            example-block-sc       8m5s
    
    NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                       STORAGECLASS           REASON   AGE
    persistentvolume/pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd   1Gi        RWO            Delete           Bound    default/example-block-pvc   example-block-sc                7m59s
    
    NAME                    READY   STATUS    RESTARTS   AGE
    pod/example-block-pod   1/1     Running   0          7m1s
    1. Patch the PVC to increase the storage size, in this example, to 2Gi.
      $ kubectl patch pvc example-block-pvc -p '{"spec": {"resources": {"requests": {"storage": "2Gi"}}}}'
      persistentvolumeclaim/example-block-pvc patched

      This action triggers an expansion in the volume associated with the PVC in vSphere Cloud Native Storage.

    2. Describe the PVC.
      The output looks similar to the following. The PVC shows the increase in size after the volume underneath is expanded.
      $ kubectl describe pvc example-block-pvc
      Name:          example-block-pvc
      Namespace:     default
      StorageClass:  example-block-sc
      Status:        Bound
      Volume:        pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd
      Labels:        <none>
      Annotations:   pv.kubernetes.io/bind-completed: yes
                     pv.kubernetes.io/bound-by-controller: yes
                     volume.beta.kubernetes.io/storage-provisioner: csi.vsphere.vmware.com
      Finalizers:    [kubernetes.io/pvc-protection]
      Capacity:      2Gi
      Access Modes:  RWO
      VolumeMode:    Filesystem
      Mounted By:    example-block-pod
      Events:
        Type     Reason                      Age   From                                                                                                Message
        ----     ------                      ----  ----                                                                                                -------
        Normal   ExternalProvisioning        19m   persistentvolume-controller                                                                         waiting for a volume to be created, either by external provisioner "csi.vsphere.vmware.com" or manually created by system administrator
        Normal   Provisioning                19m   csi.vsphere.vmware.com_vsphere-csi-controller-5d8c5c7d6-9r9kv_7adc4efc-10a6-4615-b90b-790032cc4569  External provisioner is provisioning volume for claim "default/example-block-pvc"
        Normal   ProvisioningSucceeded       19m   csi.vsphere.vmware.com_vsphere-csi-controller-5d8c5c7d6-9r9kv_7adc4efc-10a6-4615-b90b-790032cc4569  Successfully provisioned volume pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd
        Warning  ExternalExpanding           75s   volume_expand                                                                                       Ignoring the PVC: didn't find a plugin capable of expanding the volume; waiting for an external controller to process this PVC.
        Normal   Resizing                    75s   external-resizer csi.vsphere.vmware.com                                                             External resizer is resizing volume pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd
        Normal   FileSystemResizeRequired    69s   external-resizer csi.vsphere.vmware.com                                                             Require file system resize of volume on node
        Normal   FileSystemResizeSuccessful  6s    kubelet, k8s-node-072                                                                               MountVolume.NodeExpandVolume succeeded for volume "pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd"

      The PVC goes through events Resizing to FileSystemResizeRequired to FileSystemResizeSuccessful.

    3. Display the PV to verify the expanded size.
      $ kubectl get pv
      NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                       STORAGECLASS           REASON   AGE
      pvc-84c89bf9-8455-4633-a8c8-cd623e155dbd   2Gi        RWO            Delete           Bound    default/example-block-pvc   example-block-sc                25m
    To expand the PVC in offline mode, deploy a PVC with a StorageClass where allowVolumeExpansion is set to true.
    $ kubectl get pvc,pv
    NAME                                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS           AGE
    persistentvolumeclaim/example-block-pvc   Bound    pvc-9e9a325d-ee1c-11e9-a223-005056ad1fc1   1Gi        RWO            example-block-sc       5m5s
    
    NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                       STORAGECLASS           REASON   AGE
    persistentvolume/pvc-9e9a325d-ee1c-11e9-a223-005056ad1fc1   1Gi        RWO            Delete           Bound    default/example-block-pvc   example-block-sc                5m18s
    1. Patch the PVC to increase the storage size, in this example, to 2Gi.
      $ kubectl patch pvc example-block-pvc -p '{"spec": {"resources": {"requests": {"storage": "2Gi"}}}}'
      persistentvolumeclaim/example-block-pvc patched

      This action triggers an expansion in the volume associated with the PVC in vSphere Cloud Native Storage.

    2. The capacity of the corresponding PV object changes. However, the capacity of the PVC does not change until the PVC is used by a pod and mounted on a node.
      $ kubectl get pv
      NAME                                       CAPACITY ACCESS MODES RECLAIM POLICY STATUS   CLAIM                       STORAGECLASS           REASON AGE
      pvc-9e9a325d-ee1c-11e9-a223-005056ad1fc1   2Gi           RWO         Delete     Bound    default/example-block-pvc   example-block-sc              6m44s
      
      $ kubectl get pvc
      NAME                STATUS VOLUME                                     CAPACITY ACCESS MODES   STORAGECLASS       AGE
      example-block-pvc   Bound  pvc-9e9a325d-ee1c-11e9-a223-005056ad1fc1   1Gi           RWO       example-block-sc   6m57s

      You can also see a FilesystemResizePending condition applied on the PVC when you describe it.

    3. Create a pod to use the PVC.
      apiVersion: v1
      kind: Pod
      metadata:
        name: example-block-pod
      spec:
        containers:
        - name: test-container
          image: gcr.io/google_containers/busybox:1.24
          command: ["/bin/sh", "-c", "echo 'hello' > /mnt/volume1/index.html  && chmod o+rX /mnt /mnt/volume1/index.html && while true ; do sleep 2 ; done"]
          volumeMounts:
          - name: test-volume
            mountPath: /mnt/volume1
        restartPolicy: Never
        volumes:
        - name: test-volume
          persistentVolumeClaim:
            claimName: example-block-pvc
      $ kubectl create -f example-pod.yaml
      pod/example-block-pod created
      The Kubelet on the node triggers the filesystem expansion on the volume when the PVC is attached to the pod.
      $ kubectl get pvc
      NAME                STATUS VOLUME                                    CAPACITY ACCESS MODES STORAGECLASS     AGE
      example-block-pvc   Bound  pvc-24114458-9753-428e-9c90-9f568cb25788   2Gi         RWO      example-block-sc 2m12s
      
      $ kubectl get pv
      NAME                                       CAPACITY ACCESS MODES RECLAIM POLICY STATUS   CLAIM                     STORAGECLASS           REASON AGE
      pvc-24114458-9753-428e-9c90-9f568cb25788   2Gi           RWO        Delete      Bound    default/example-block-pvc example-block-sc              2m3s
      $ kubectl get pod
      NAME               READY STATUS  RESTARTS AGE
      example-block-pod   1/1  Running 0        65s

      The capacity of PVC is modified and the FilesystemResizePending condition is removed from the PVC. Offline volume expansion is complete.