Dynamic Persistent Volume Provisioning in Google Kubernetes Engine (GKE)

In this practical exercise, I worked with Google Cloud Platform (GCP), Google Kubernetes Engine (GKE), Kubernetes StorageClass, PersistentVolume (PV), PersistentVolumeClaim (PVC), and Pod storage.

The main goal was to understand how Kubernetes can dynamically create persistent storage and attach that storage to a Pod.


šŸš€ Architecture

The complete flow of this practical is:

Google Cloud
     │
     ā–¼
Google Kubernetes Engine (GKE)
     │
     ā–¼
Standard Kubernetes Cluster
     │
     ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
     │               │
     ā–¼               ā–¼
StorageClass       PVC
   "fast"         "claim1"
     │               │
     ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
             ā–¼
      Dynamic Provisioning
             │
             ā–¼
     Google Persistent Disk
             │
             ā–¼
        PersistentVolume
             │
             ā–¼
          Pod
        "webpod"
             │
             ā–¼
           Nginx

1. Create a GKE Standard Cluster

First, I created a Standard GKE cluster in Google Cloud.

After connecting Cloud Shell to the cluster, I verified the Kubernetes nodes:

kubectl get nodes

Example output:

NAME                                      STATUS   ROLES    AGE
gke-mycluster-default-pool-...            Ready    <none>   ...
gke-mycluster-default-pool-...            Ready    <none>   ...
gke-mycluster-default-pool-...            Ready    <none>   ...

All three nodes were in the:

Ready

state.

This confirmed that my Kubernetes cluster was working properly.


2. Check Kubernetes Resources

Next, I checked the resources in the cluster:

kubectl get all

Then I checked whether any PersistentVolumes existed:

kubectl get pv

PVCs:

kubectl get pvc

Pods:

kubectl get pod

Initially, there were no PVs, PVCs, or application Pods because I had not created them yet.


3. Check StorageClasses

I then checked the available StorageClasses:

kubectl get sc

A GKE cluster already provides StorageClasses. In my practical, I wanted to create my own StorageClass called:

fast

The purpose of the StorageClass is to tell Kubernetes how to dynamically provision storage.


4. Create a PersistentVolumeClaim

I created a PVC configuration file:

vim pvc-dynamic.yaml

The configuration was:

apiVersion: v1
kind: PersistentVolumeClaim

metadata:
  name: claim1

spec:
  storageClassName: fast
  accessModes:
    - ReadWriteOnce

  resources:
    requests:
      storage: 1Gi

What does this mean?

The PVC is requesting:

  • PVC name: claim1
  • StorageClass: fast
  • Storage: 1Gi
  • Access mode: ReadWriteOnce

The important part is:

storageClassName: fast

This tells Kubernetes:

“Use the StorageClass named fast to provide my storage.”


5. Create the StorageClass

Next, I created:

vim sc.yaml

with:

apiVersion: storage.k8s.io/v1
kind: StorageClass

metadata:
  name: fast

provisioner: kubernetes.io/gce-pd

parameters:
  type: pd-ssd

Here:

name: fast

creates a StorageClass named fast.

And:

provisioner: kubernetes.io/gce-pd

tells Kubernetes to use the Google Compute Engine Persistent Disk provisioner.

The parameter:

type: pd-ssd

requests an SSD-backed Persistent Disk.

Important: For current GKE clusters, Google recommends the GKE Persistent Disk CSI driver (pd.csi.storage.gke.io) rather than the older kubernetes.io/gce-pd provisioner. Your exercise demonstrates the older provisioner concept, while your current cluster also showed standard-rwo using the CSI driver.


6. Dynamic Provisioning

This is the most important concept in this practical.

Normally, we could manually create:

PersistentVolume → PersistentVolumeClaim → Pod

But with dynamic provisioning, Kubernetes can automatically create the PersistentVolume when the PVC requests storage through a StorageClass.

The process is:

PVC claim1
     │
     ā–¼
StorageClass fast
     │
     ā–¼
Provisioner
     │
     ā–¼
Google Persistent Disk
     │
     ā–¼
PersistentVolume
     │
     ā–¼
PVC becomes Bound

So we don’t have to manually create a PV YAML file for this dynamic provisioning exercise.


7. Check PV and PVC

After creating the StorageClass and PVC, I checked:

kubectl get pv

and:

kubectl get pvc

The PVC should eventually become:

STATUS: Bound

For example:

NAME      STATUS   VOLUME                                     CAPACITY
claim1    Bound    pvc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   1Gi

This means Kubernetes successfully created storage for the PVC.


8. Create a Pod Using the PVC

Next, I created:

vim pod-pv.yaml

with the following configuration:

apiVersion: v1
kind: Pod

metadata:
  name: webpod

spec:
  volumes:
    - name: vol1
      persistentVolumeClaim:
        claimName: claim1

  containers:
    - name: nginx
      image: nginx

      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: vol1

Here the Pod is called:

webpod

and it uses the PVC:

claim1

The PVC is mounted inside the Nginx container at:

/usr/share/nginx/html

9. Apply the Pod Configuration

I applied the configuration:

kubectl apply -f pod-pv.yaml

Then checked the Pod:

kubectl get pod

To continuously watch the Pod status, I used:

kubectl get pod -w

Eventually, the Pod should become:

webpod    1/1    Running

10. Describe the Pod

To understand how the storage was attached to the Pod, I used:

kubectl describe pod webpod

This command is useful for troubleshooting because it shows information such as:

  • Pod status
  • Node
  • Containers
  • Volumes
  • Volume mounts
  • Events
  • Scheduling information

The volume section shows that the Pod is using the PVC claim1.


11. Check the PVC

I also checked:

kubectl get pvc

The PVC should show:

claim1    Bound

The relationship is:

Pod
 │
 ā–¼
PVC: claim1
 │
 ā–¼
PV
 │
 ā–¼
Google Persistent Disk

12. Delete the Resources

After completing the practical, I practiced deleting the resources.

First, I attempted to delete the PVC:

kubectl delete pvc claim1

Then checked:

kubectl get pods

Next, I deleted the Pod:

kubectl delete pod webpod

Then:

kubectl get pods

Finally, I deleted the PVC:

kubectl delete pvc claim1

and checked:

kubectl get pvc

Then:

kubectl get pv

13. Delete the StorageClass

Finally, I checked the StorageClasses:

kubectl get sc

Then deleted my custom StorageClass:

kubectl delete sc fast

And verified:

kubectl get sc

The custom fast StorageClass was removed.


šŸ”„ Complete Practical Flow

The entire practical can be summarized as:

                 Google Cloud
                      │
                      ā–¼
             GKE Standard Cluster
                      │
                      ā–¼
              Create StorageClass
                  "fast"
                      │
                      ā–¼
             Create PVC "claim1"
                  1Gi storage
                      │
                      ā–¼
             Dynamic Provisioning
                      │
                      ā–¼
          Google Persistent Disk
                      │
                      ā–¼
             PersistentVolume
                      │
                      ā–¼
             PVC → Bound
                      │
                      ā–¼
              Create Pod "webpod"
                      │
                      ā–¼
                  Nginx
                      │
                      ā–¼
        Mount PVC at /usr/share/nginx/html

šŸŽÆ What I Learned

From this practical, I learned:

  1. How to create and work with a GKE Standard cluster.
  2. How to check Kubernetes nodes using kubectl get nodes.
  3. What a PersistentVolume (PV) is.
  4. What a PersistentVolumeClaim (PVC) is.
  5. How a StorageClass works.
  6. How dynamic volume provisioning works.
  7. How to request storage using a PVC.
  8. How Kubernetes automatically provisions persistent storage.
  9. How to mount a PVC inside an Nginx Pod.
  10. How to inspect a Pod using kubectl describe.
  11. How to delete Pods, PVCs, PVs, and StorageClasses.

⭐ Key Concept

The most important thing I learned is:

A PVC requests storage, while a StorageClass defines how Kubernetes should dynamically create that storage.

This makes Kubernetes storage much easier to manage because applications can request storage without manually creating every PersistentVolume.

Total Page Visits: 76 - Today Page Visits: 36

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *