GKE Persistent Volumes provisioned with the Persistent Disk CSI driver are actually just standard GKE Persistent Volumes, but they use a different mechanism to create and manage the underlying Google Compute Engine Persistent Disks.

Let’s see this in action. Here’s a simple PersistentVolumeClaim (PVC) definition:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard-rwo # Or whatever your StorageClass is named

When you apply this, if your StorageClass is configured to use the GKE Persistent Disk CSI driver (which is the default for many StorageClass names like standard-rwo), GKE doesn’t directly interact with the GCE API itself. Instead, it instructs the CSI driver within the cluster to make that call. The CSI driver then talks to the GCE API to create a PersistentDisk resource.

The core problem this solves is decoupling the Kubernetes storage primitives from the underlying cloud provider’s storage implementation. For GKE, this means:

  • Standardization: You can write your Kubernetes manifests without knowing exactly how GCE Persistent Disks work under the hood. The CSI driver abstracts this.
  • Portability: While this specific example is GKE-specific, the CSI model is designed to allow you to swap out the underlying storage provider (e.g., from GCE Persistent Disks to NFS, or even a SAN) by just changing the StorageClass and installing the corresponding CSI driver. Your application pods remain unaware.
  • Dynamic Provisioning: You don’t need to pre-create every single disk. When a pod requests storage via a PVC, the CSI driver dynamically provisions a new GCE Persistent Disk and attaches it to the node where the pod is scheduled.

Internally, here’s a simplified flow:

  1. Pod requests storage: A pod’s YAML specifies a volume that references a PersistentVolumeClaim (like my-pvc above).
  2. Kubernetes API Server: When the PVC is created, the Kubernetes API server sees it.
  3. Controller Manager (CSI Sidecar): A CSI controller component (often running as a Deployment within GKE) watches for new PVCs.
  4. CSI Driver: The CSI controller for the GCE Persistent Disk driver receives the request. It translates the PVC’s spec (size, access modes) into a GCE API call.
  5. GCE API: The GCE API creates a PersistentDisk resource in your GCP project.
  6. Node Plugin: When the pod is scheduled to a specific node, the CSI node plugin on that node is invoked.
  7. Attach/Mount: The node plugin tells GCE to attach the newly created Persistent Disk to the node. Once attached, it mounts the disk into the pod’s filesystem.

The exact levers you control are primarily through the StorageClass definition. For GCE Persistent Disks, common parameters include:

  • type: pd-standard (HDD), pd-balanced (SSD), pd-ssd (SSD).
  • replication-type: regional-pd (for Regional Persistent Disks).
  • fs-type: ext4 or xfs.
  • provisioned-iops and provisioned-throughput: For pd-balanced and pd-ssd.

For instance, to provision a 50Gi pd-ssd with ReadWriteOnce access, your StorageClass might look like this:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ssd-rwo
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
  replication-type: none # or regional-pd
  fs-type: ext4
allowVolumeExpansion: true
volumeBindingMode: Immediate

And your PVC would reference it:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-ssd-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
  storageClassName: ssd-rwo

The most surprising thing to many users is that the CSI driver doesn’t just provide a way to use GCE disks; it’s the only way GKE handles dynamic provisioning for its native persistent disks now. Older in-tree volume plugins are deprecated.

When you’re debugging issues, remember that the PersistentVolume object itself is a Kubernetes abstraction. The real work, and often the source of errors, happens when the CSI driver communicates with the GCE API. You can inspect PersistentVolume and PersistentVolumeClaim events for clues, but ultimately, the underlying GCE disk’s status in the GCP console is the ground truth.

The next step is understanding how to manage snapshots and restores for these dynamically provisioned disks.

Want structured learning?

Take the full Gke course →