Use persistent disks with multiple readers


This page explains how to add a persistent disk to your cluster using the ReadOnlyMany access mode. This mode allows multiple Pods on different nodes to mount the disk for reading.

For more information on this mode, refer to persistent volume access modes.

Requirements

Format and populate a source persistent disk

To use a persistent disk in read-only mode, you must populate a source persistent disk with data, then either clone the volume or use a volume snapshot to move the data into a new ReadOnlyMany PersistentVolume.

  1. Create a PersistentVolume using an existing persistent disk or using dynamic provisioning.

  2. Format the disk and populate it with data. To format the disk, reference the disk as a ReadWriteOnce PersistentVolume in a Pod. GKE automatically formats the underlying disk, and lets the Pod write data to the disk. When the Pod starts, make sure the Pod writes the data you want to the disk.

Create a ReadOnlyMany PersistentVolume

You can create a ReadOnlyMany PersistentVolume using one of the following methods:

  • A volume snapshot of a source PersistentVolume that you populate with data.
  • A volume clone of a source PersistentVolume that you populate with data.
  • A pre-existing persistent disk that was already populated with data.

Volume snapshot

  1. Create a volume snapshot of the source PersistentVolume.

  2. Save the following PersistentVolumeClaim manifest as snapshot-pvc.yaml:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      namespace: PVC_NAMESPACE
      name: PVC_NAME
    spec:
      dataSource:
        apiGroup: snapshot.storage.k8s.io
        kind: VolumeSnapshot
        name: SNAPSHOT_NAME
      accessModes:
        - ReadOnlyMany
      storageClassName: premium-rwo
      resources:
        requests:
          storage: STORAGE_SIZE
    

    Replace the following:

    • PVC_NAMESPACE: the namespace of the new PersistentVolumeClaim.
    • PVC_NAME: the name of the new PersistentVolumeClaim.
    • SNAPSHOT_NAME:the name of your VolumeSnapshot object.
    • STORAGE_SIZE: the amount of storage to request. This must be the same as the amount requested in the source PersistentVolumeClaim.
  3. Apply the manifest to your cluster:

    kubectl apply -f snapshot-pvc.yaml
    

This creates a new PersistentVolumeClaim named PVC_NAME in your cluster, which GKE uses to dynamically provision a new PersistentVolume that contains the data from the snapshot of the source persistent disk.

Volume cloning

Before using volume cloning, make sure to familiarize yourself with the limitations of this approach.

  1. Save the following manifest as cloning-pvc.yaml:

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      namespace: PVC_NAMESPACE
      name: PVC_NAME
    spec:
      dataSource:
        name: SOURCE_PVC
        kind: PersistentVolumeClaim
      accessModes:
        - ReadOnlyMany
      storageClassName: STORAGE_CLASS_NAME
      resources:
        requests:
          storage: STORAGE_SIZE
    

    Replace the following:

    • PVC_NAMESPACE: the namespace of the new PersistentVolumeClaim.
    • PVC_NAME: the name of the new PersistentVolumeClaim.
    • SOURCE_PVC: the name of the source PersistentVolumeClaim populated with data.
    • STORAGE_CLASS_NAME: the storage class for the new PersistentVolumeClaim. This must be the same as the storage class of the source PersistentVolumeClaim.
    • STORAGE_SIZE: the amount of storage for the new PersistentVolumeClaim. This must be the same amount requested by the source PersistentVolumeClaim.
  2. Apply the manifest to your cluster:

    kubectl apply -f cloning-pvc.yaml
    

This creates a PersistentVolumeClaim named PVC_NAME that GKE uses to create a new PersistentVolume in ReadOnlyMany mode with the data in the source PersistentVolume.

For more detailed information about Volume Cloning, see Create clones of persistent volumes.

Pre-existing persistent disk

  1. Save the following manifest as preexisting-disk-pv-pvc.yaml:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: PV_NAME
    spec:
      storageClassName: "STORAGE_CLASS_NAME"
      capacity:
        storage: DISK_SIZE
      accessModes:
        - ReadOnlyMany
      claimRef:
        namespace: PVC_NAMESPACE
        name: PVC_NAME
      csi:
        driver: pd.csi.storage.gke.io
        volumeHandle: DISK_ID
        fsType: FS_TYPE
        readOnly: true
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      namespace: PVC_NAMESPACE
      name: PVC_NAME
    spec:
      storageClassName: "STORAGE_CLASS_NAME"
      volumeName: PV_NAME
      accessModes:
        - ReadOnlyMany
      resources:
        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 persistent disk. For example, 500G.
    • PVC_NAMESPACE: the namespace of the new PersistentVolumeClaim.
    • PVC_NAME: the name of your new PersistentVolumeClaim.
    • DISK_ID: the identifier of your pre-existing persistent disk. The format is projects/{project_id}/zones/{zone_name}/disks/{disk_name} for Zonal persistent disks, or projects/{project_id}/regions/{region_name}/disks/{disk_name} for Regional persistent disks.
    • FS_TYPE: the filesystem type. You can leave this as the default (ext4), or use xfs. If your clusters use a Windows Server node pool, you must change this to NTFS.
  2. Apply the manifest to your cluster:

    kubectl apply -f preexisting-disk-pv-pvc.yaml
    

This creates a PersistentVolumeClaim named PVC_NAME and a PersistentVolume named PV_NAME in ReadOnlyMany mode.

For more detailed information about using a pre-existing persistent disk, see existing persistent disk.

Use the PersistentVolumeClaim in a Pod

You can now reference the new PersistentVolumeClaim in read-only mode in multiple Pods on multiple nodes at the same time. You cannot attach persistent disks in ReadWriteOnce mode to multiple nodes at the same time. For more information, refer to Deployments vs. StatefulSets.

In your Pod specification, you must specify readOnly: true in the volumeMounts section and the volumes section, such as in the following example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: multi-read
  labels:
    app: web-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-server
  template:
    metadata:
      labels:
        app: web-server
    spec:
      containers:
      - name: web-server
        image: nginx
        volumeMounts:
        - mountPath: /test-mnt
          name: my-volume
          readOnly: true
      volumes:
      - name: my-volume
        persistentVolumeClaim:
          claimName: PVC_NAME
          readOnly: true

What's next