Using preexisting persistent disks as PersistentVolumes

This page explains how to create a PersistentVolume using an existing Compute Engine persistent disk populated with data, and how to use the PersistentVolume in a Pod.

Creating the PersistentVolume and PersistentVolumeClaim

If you already have a 500-GB persistent disk named pd-name, the following manifest file (named existing-pd.yaml) describes a corresponding PersistentVolume and PersistentVolumeClaim.

This example uses a claimRef. By referencing a PersistentVolumeClaim in the PersistentVolume, you can ensure that the PersistentVolume can only be bound with the PersistentVolumeClaim that you specify.

A StorageClass object with a name matching storageClassName is only necessary if you require functionality configured by the StorageClass, for example allowVolumeExpansion for volume resizing.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-demo
spec:
  storageClassName: "example-storageclass"
  capacity:
    storage: 500G
  accessModes:
    - ReadWriteOnce
  claimRef:
    namespace: default
    name: pv-claim-demo
  gcePersistentDisk:
    pdName: pd-name
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim-demo
spec:
  storageClassName: "example-storageclass"
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500G

To create the PersistentVolume and PersistentVolumeClaim use kubectl apply -f existing-pd.yaml.

Using the PersistentVolume in a Pod

After the PersistentVolume and PersistentVolumeClaim exist in the cluster, you can give a Pod's containers access to the volume by specifying values in the volumeMounts field. In this example, these fields specify that the volume named task-pv-storage is mounted at the file path /usr/share/nginx/html.

kind: Pod
apiVersion: v1
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
       claimName: pv-claim-demo
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

When you apply this manifest to a cluster, the Pod is created, and the task-pv-container container has access to the volume in its /usr/share/nginx/html/ directory.

Using a preexisting disk in a StatefulSet

To use a preexisting disk in a StatefulSet, complete the following tasks:

  1. Decide on the StatefulSet name, volumeClaimTemplates.name, and the number of replicas for your StatefulSet and record the values. Do not create the StatefulSet until you have finished creating the PersistentVolumeClaim.
  2. Work out the StatefulSet's automatically generated PersistentVolumeClaim name. In StatefulSets, the PersistentVolumeClaim name follows a predictable pattern: volumeclaimtemplates-name-statefulset-name-replica-index. For example, if you decide the StatefulSet's name is "web", the StatefulSet's volumeClaimTemplates.name is "www", and there are two StatefulSet replicas, the two PersistentVolumeClaim names are www-web-0 and www-web-1.
  3. Create PersistentVolumes with a claimRef field and set claimRef.name to the generated PersistentVolumeClaim name. When there is more than one replica, you need to create a PersistentVolume for each replica.

    The following example PersistentVolumes are for an environment with the following features:

    • A StatefulSet that will be in the default namespace.
    • A StatefulSet that will have two replicas.
    • A StatefulSet where the automatically generated PersistentVolumeClaim names are www-web-0 and www-web-1.
    • Two existing persistent disks named pd-zero and pd-one.
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-statefulset-demo-0
    spec:
      storageClassName: "example-storageclass"
      capacity:
        storage: 100Gi
      accessModes:
        - ReadWriteOnce
      claimRef:
        namespace: default
        name: www-web-0
      gcePersistentDisk:
        pdName: pd-zero
        fsType: ext4
    
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-statefulset-demo-1
    spec:
      storageClassName: "example-storageclass"
      capacity:
        storage: 100Gi
      accessModes:
        - ReadWriteOnce
      claimRef:
        namespace: default
        name: www-web-1
      gcePersistentDisk:
        pdName: pd-one
        fsType: ext4
    
  4. Create a StatefulSet using the values you chose in the first step. Ensure the storage you specify in the volumeClaimTemplates is less than or equal to the capacity of your PersistentVolumes. For example:

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      selector:
        matchLabels:
          app: nginx
      serviceName: "nginx"
      replicas: 2
      template:
        metadata:
          labels:
            app: nginx
        spec:
          terminationGracePeriodSeconds: 10
          containers:
          - name: nginx
            image: k8s.gcr.io/nginx-slim:0.8
            ports:
            - containerPort: 80
              name: web
            volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
      - metadata:
          name: www
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 100Gi