Using pre-existing persistent disks as PersistentVolumes

This page explains how to create aPersistentVolumeusing existing persistent disks populated with data, and how to use thePersistentVolume in a Pod.

Overview

There are two common scenarios which use a pre-existing persistent disk.

The examples in this page use existingCompute Engine persistent disks.

Whileext4 is the default filesystem type, you can use a pre-existingpersistent disk with thexfs filesystem instead as long as yournode image supports it. To use anxfs disk, changespec.csi.fsTypetoxfs in the PersistentVolume manifest.

Windows does not support theext4 filesystem type. You must use theNTFS filesystem for Windows Server node pools.To use anNTFS disk, changespec.csi.fsType toNTFSin the PersistentVolume manifest.

Note: If the filesystem type for the persistent disk you use doesn't match thefsType you specify in the PersistentVolume manifest, pods you create thatconsume the volumes will not start, and you will see errors in the Pod description.Similarly, Persistent Disk CSI volumes only support a single partition. Volumes createdoutside of GKE with multiple partitions cannot be used with this technique.

Before you begin

Before you start, make sure that you have performed the following tasks:

Using a PersistentVolumeClaim bound to the PersistentVolume

For a container to access your pre-existing persistent disk, you'll need to do the following:

  1. Provision the existing persistent disk as a PersistentVolume.
  2. Bind the PersistentVolume to a PersistentVolumeClaim.
  3. Give the containers in the Pod access to the PersistentVolume.

Create the PersistentVolume and PersistentVolumeClaim

There are several ways to bind a PersistentVolumeClaim to a specificPersistentVolume. For example, the following YAML manifest creates a newPersistentVolume and PersistentVolumeClaim, and then binds the volume to theclaim using theclaimRef defined on the PersistentVolume.

To bind a PersistentVolume to a PersistentVolumeClaim, thestorageClassName of the two resources must match, as well ascapacity,accessModes, andvolumeMode. You can omit thestorageClassName, but youmust specify"" to prevent Kubernetes from using the default StorageClass.

ThestorageClassName does not need to refer to an existing StorageClassobject. If all you need is to bind the claim to a volume, you can use any nameyou want. However, if you need extra functionality configured by a StorageClass,like volume resizing, thenstorageClassName must refer to an existingStorageClass object.

For more details, see theKubernetes documentation on PersistentVolumes.

Note: The persistent disk must be in the samezoneas the cluster nodes.
  1. Save the following YAML manifest:

    apiVersion:v1kind:PersistentVolumemetadata:name:PV_NAMEspec:storageClassName:"STORAGE_CLASS_NAME"capacity:storage:DISK_SIZEaccessModes:-ReadWriteOnceclaimRef:name:PV_CLAIM_NAMEnamespace:defaultcsi:driver:pd.csi.storage.gke.iovolumeHandle:DISK_IDfsType:FS_TYPE---apiVersion:v1kind:PersistentVolumeClaimmetadata:namespace:defaultname:PV_CLAIM_NAMEspec:storageClassName:"STORAGE_CLASS_NAME"accessModes:-ReadWriteOnceresources:requests:storage:DISK_SIZE

    Replace the following:

    • PV_NAME: the name of your new PersistentVolume.
    • STORAGE_CLASS_NAME: the name of your new StorageClass.
    • DISK_SIZE: the size of your pre-existing persistentdisk. For example,500G.
    • PV_CLAIM_NAME: the name of your newPersistentVolumeClaim.
    • DISK_ID: the identifier of your pre-existing persistentdisk. The format isprojects/{project_id}/zones/{zone_name}/disks/{disk_name} forZonal persistent disks, orprojects/{project_id}/regions/{region_name}/disks/{disk_name} forRegional persistent disks.
    • FS_TYPE: the filesystem type. You can leave this as the default (ext4), or usexfs.If your clusters use a Windows Server node pool, you must change this toNTFS.
  2. To apply the configuration and create the PersistentVolume andPersistentVolumeClaim resources, run the following command:

    kubectlapply-fFILE_PATH

    ReplaceFILE_PATH with the path to the YAML file.

Use the PersistentVolume in a Pod

After you create and bind the PersistentVolume and PersistentVolumeClaim, youcan give a Pod's containers access to the volume by specifying values in thevolumeMounts field.

The following YAML configuration creates a new Pod and a container running annginx image, and then mounts the PersistentVolume on the Pod:

kind:PodapiVersion:v1metadata:name:POD_NAMEspec:volumes:-name:VOLUME_NAMEpersistentVolumeClaim:claimName:PV_CLAIM_NAMEcontainers:-name:CONTAINER_NAMEimage:nginxports:-containerPort:80name:"http-server"volumeMounts:-mountPath:"/usr/share/nginx/html"name:VOLUME_NAME

Replace the following:

  • POD_NAME: the name of your new Pod.
  • VOLUME_NAME: the name of the volume.
  • PV_CLAIM_NAME: the name of the PersistentVolumeClaimyou created in the previous step.
  • CONTAINER_NAME: the name of your new container.

Apply the configuration:

kubectlapply-fFILE_PATH

ReplaceFILE_PATH with the path to the YAML file.

To verify that the volume was mounted, run the following command:

kubectldescribepodsPOD_NAME

In the output, check that the PersistentVolumeClaim was mounted:

...Volumes:VOLUME_NAME:    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)    ClaimName:PV_CLAIM_NAME    ReadOnly:   falseEvents:  Type    Reason                  Age   From                     Message  ----    ------                  ----  ----                     -------  Normal  Scheduled               29s   default-scheduler        Successfully assigned default/POD_NAME to gke-cluster-1-default-pool-d5cde866-o4g4  Normal  SuccessfulAttachVolume  21s   attachdetach-controller  AttachVolume.Attach succeeded for volume "PV_NAME"  Normal  Pulling                 19s   kubelet                  Pulling image "nginx"  Normal  Pulled                  19s   kubelet                  Successfully pulled image "nginx"  Normal  Created                 18s   kubelet                  Created containerCONTAINER_NAME  Normal  Started                 18s   kubelet                  Started containerCONTAINER_NAME

Using a pre-existing disk in a StatefulSet

You can use pre-existing Compute Engine persistent disks in aStatefulSet usingPersistentVolumes. The StatefulSet automatically generates aPersistentVolumeClaim for each replica. You can predict the names of thegenerated PersistentVolumeClaims and bind them to the PersistentVolumes usingclaimRef.

In the following example, you take two pre-existing persistent disks, createPersistentVolumes to use the disks, and then mount the volumes on a StatefulSetwith two replicas in the default namespace.

  1. Decide on a name for your new StatefulSet, a name for yourPersistentVolumeClaim template, and the number of replicas in the StatefulSet.
  2. Work out the names of the automatically generated PersistentVolumeClaims. TheStatefulSet uses the following format for PersistentVolumeClaim names:

    PVC_TEMPLATE_NAME-STATEFULSET_NAME-REPLICA_INDEX

    Replace the following:

    • PVC_TEMPLATE_NAME: the name of your new PersistentVolumeClaim template.
    • STATEFULSET_NAME: the name of your new StatefulSet.
    • REPLICA_INDEX: the index of the StatefulSet's replica. For this example, use0 and1.
  3. Create the PersistentVolumes. You must create a PersistentVolume for each replica in the StatefulSet.

    1. Save the following YAML manifest:

      apiVersion:v1kind:PersistentVolumemetadata:name:pv-ss-demo-0spec:storageClassName:"STORAGE_CLASS_NAME"capacity:storage:DISK1_SIZEaccessModes:-ReadWriteOnceclaimRef:namespace:defaultname:PVC_TEMPLATE_NAME-STATEFULSET_NAME-0csi:driver:pd.csi.storage.gke.iovolumeHandle:DISK1_IDfsType:FS_TYPE---apiVersion:v1kind:PersistentVolumemetadata:name:pv-ss-demo-1spec:storageClassName:"STORAGE_CLASS_NAME"capacity:storage:DISK2_SIZEaccessModes:-ReadWriteOnceclaimRef:namespace:defaultname:PVC_TEMPLATE_NAME-STATEFULSET_NAME-1csi:driver:pd.csi.storage.gke.iovolumeHandle:DISK2_IDfsType:FS_TYPE

      Replace the following:

      • DISK1_SIZE andDISK2_SIZE: the sizes ofyour pre-existing persistent disks.
      • DISK1_ID andDISK2_ID: the identifiers ofyour pre-existing persistent disks.
      • PVC_TEMPLATE_NAME-STATEFULSET_NAME-0 andPVC_TEMPLATE_NAME-STATEFULSET_NAME-1: the names of the automatically generated PersistentVolumeClaims in the format defined in the previous step.
      • STORAGE_CLASS_NAME: the name of your StorageClass.
    2. Apply the configuration:

      kubectlapply-fFILE_PATH

      ReplaceFILE_PATH with the path to the YAML file.

  4. Create a StatefulSetusing the values you chose in step 1. Ensure that the storage you specifyin thevolumeClaimTemplates is less than or equal to the total capacity of yourPersistentVolumes.

    1. Save the following YAML manifest:

      apiVersion:apps/v1kind:StatefulSetmetadata:name:STATEFULSET_NAMEspec:selector:matchLabels:app:nginxserviceName:"nginx"replicas:2template:metadata:labels:app:nginxspec:terminationGracePeriodSeconds:10containers:-name:nginximage:registry.k8s.io/nginx-slim:0.8ports:-containerPort:80name:webvolumeMounts:-name:PVC_TEMPLATE_NAMEmountPath:/usr/share/nginx/htmlvolumeClaimTemplates:-metadata:name:PVC_TEMPLATE_NAMEspec:accessModes:["ReadWriteOnce"]storageClassName:"STORAGE_CLASS_NAME"resources:requests:storage:100Gi

      Replace the following:

      • STATEFULSET_NAME: the name of your new StatefulSet.
      • PVC_TEMPLATE_NAME: the name of your newPersistentVolumeClaim template.
      • STORAGE_CLASS_NAME: the name of your StorageClass.
      Note: Make sure that your StatefulSet name and PersistentVolumeClaim namematch the values you decided in step 1.
    2. Apply the configuration:

      kubectlapply-fFILE_PATH

      ReplaceFILE_PATH with the path to the YAML file.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-11-06 UTC.