Configuring Persistent Storage for Google Kubernetes Engine
PersistentVolumes are storage that is available to a Kubernetes cluster. PersistentVolumeClaims enable Pods to access PersistentVolumes. Without PersistentVolumeClaims Pods are mostly ephemeral, so you should use PersistentVolumeClaims for any data that you expect to survive Pod scaling, updating, or migrating.
- Create manifests for PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs) for Google Cloud persistent disks (dynamically created or existing)
- Mount Google Cloud persistent disk PVCs as volumes in Pods
- Use manifests to create StatefulSets
- Mount Google Cloud persistent disk PVCs as volumes in StatefulSets
- Verify the connection of Pods in StatefulSets to particular PVs as the Pods are stopped and restarted
Create PVs and PVCs
Welcome to Cloud Shell! Type "help" to get started.
Your Cloud Platform project in this session is set to qwiklabs-gcp-01-41684334779c.
Use “gcloud config set project [PROJECT_ID]” to change to a different project.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ export my_region=us-east1
export my_cluster=autopilot-cluster-1
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ source <(kubectl completion bash)
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ gcloud container clusters get-credentials $my_cluster --region $my_region
Fetching cluster endpoint and auth data.
kubeconfig entry generated for autopilot-cluster-1.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Create and apply a manifest with a PVC
Most of the time, you don’t need to directly configure PV objects or create Compute Engine persistent disks. Instead, you can create a PVC, and Kubernetes automatically provisions a persistent disk for you.
Let’s creates a 30 gigabyte PVC called hello-web-disk
that can be mounted as a read-write volume on a single node at a time.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ cat pvc-demo.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: hello-web-disk
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Gi
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get persistentvolumeclaim
No resources found in default namespace.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl apply -f pvc-demo.yaml
persistentvolumeclaim/hello-web-disk created
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get persistentvolumeclaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
hello-web-disk Pending standard-rwo <unset> 4s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
The status will remain pending until after the next step.
Mount and verify Google Cloud persistent disk PVCs in Pods
In this task, you attach your persistent disk PVC to a Pod. You mount the PVC as a volume as part of the manifest for the Pod.
Mount the PVC to a Pod
Create a manifest file pod-volume-demo.yaml
to deploy an nginx container, attach the pvc-demo-volume
to the Pod and mount that volume to the path /var/www/html
inside the nginx container. Files saved to this directory inside the container will be saved to the persistent volume and persist even if the Pod and the container are shutdown and recreated.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ cat pod-volume-demo.yaml
kind: Pod
apiVersion: v1
metadata:
name: pvc-demo-pod
spec:
containers:
- name: frontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: pvc-demo-volume
volumes:
- name: pvc-demo-volume
persistentVolumeClaim:
claimName: hello-web-disk
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
To create the Pod with the volume, execute the following command
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 0/1 Pending 0 6s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 0/1 Pending 0 11s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 0/1 Pending 0 32s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Pending standard-rwo <unset> 3m28s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Pending standard-rwo <unset> 3m35s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Pending standard-rwo <unset> 3m42s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Pending standard-rwo <unset> 3m57s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Pending standard-rwo <unset> 4m
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 0/1 Pending 0 75s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl describe pods pvc-demo-pod
Name: pvc-demo-pod
Namespace: default
Priority: 0
Service Account: default
Node: <none>
Labels: <none>
Annotations: autopilot.gke.io/resource-adjustment:
{"input":{"containers":[{"name":"frontend"}]},"output":{"containers":[{"limits":{"cpu":"500m","ephemeral-storage":"1Gi","memory":"2Gi"},"r...
autopilot.gke.io/warden-version: 2.9.37
Status: Pending
SeccompProfile: RuntimeDefault
IP:
IPs: <none>
Containers:
frontend:
Image: nginx
Port: <none>
Host Port: <none>
Limits:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
Requests:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-qbvwz (ro)
/var/www/html from pvc-demo-volume (rw)
Conditions:
Type Status
PodScheduled False
Volumes:
pvc-demo-volume:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: hello-web-disk
ReadOnly: false
kube-api-access-qbvwz:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: kubernetes.io/arch=amd64:NoSchedule
node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 90s gke.io/optimize-utilization-scheduler no nodes available to schedule pods
Warning FailedScheduling 86s (x2 over 88s) gke.io/optimize-utilization-scheduler no nodes available to schedule pods
Normal TriggeredScaleUp 49s cluster-autoscaler pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/qwiklabs-gcp-01-41684334779c/zones/us-east1-b/instanceGroups/gk3-autopilot-cluster-1-nap-l8h3ctae-3077ca01-grp 0->1 (max: 1000)}]
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
If you do this quickly after creating the Pod, you will see the status listed as “ContainerCreating” while the volume is mounted before the status changes to “Running”.
after sometime,
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 1/1 Running 0 6m35s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
persistentvolume/pvc-efe382e6-a099-4055-a17d-742273e9ec65 30Gi RWO Delete Bound default/hello-web-disk standard-rwo <unset> 4m33s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Bound pvc-efe382e6-a099-4055-a17d-742273e9ec65 30Gi RWO standard-rwo <unset> 9m28s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl describe pod pvc-demo-pod
Name: pvc-demo-pod
Namespace: default
Priority: 0
Service Account: default
Node: gk3-autopilot-cluster-1-nap-l8h3ctae-3077ca01-l9jp/10.142.0.4
Start Time: Sun, 23 Jun 2024 13:33:37 +0000
Labels: <none>
Annotations: autopilot.gke.io/resource-adjustment:
{"input":{"containers":[{"name":"frontend"}]},"output":{"containers":[{"limits":{"cpu":"500m","ephemeral-storage":"1Gi","memory":"2Gi"},"r...
autopilot.gke.io/warden-version: 2.9.37
cloud.google.com/cluster_autoscaler_unhelpable_since: 2024-06-23T13:33:33+0000
cloud.google.com/cluster_autoscaler_unhelpable_until: Inf
Status: Running
SeccompProfile: RuntimeDefault
IP: 10.113.0.14
IPs:
IP: 10.113.0.14
Containers:
frontend:
Container ID: containerd://42ef705f72099ef1d88a81df97e75cb78e86ed55e76f226cdb4ceeb88258e45a
Image: nginx
Image ID: docker.io/library/nginx@sha256:9c367186df9a6b18c6735357b8eb7f407347e84aea09beb184961cb83543d46e
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 23 Jun 2024 13:34:14 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
Requests:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-qbvwz (ro)
/var/www/html from pvc-demo-volume (rw)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
pvc-demo-volume:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: hello-web-disk
ReadOnly: false
kube-api-access-qbvwz:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: kubernetes.io/arch=amd64:NoSchedule
node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 7m8s gke.io/optimize-utilization-scheduler no nodes available to schedule pods
Warning FailedScheduling 5m43s (x11 over 7m7s) gke.io/optimize-utilization-scheduler no nodes available to schedule pods
Normal Scheduled 5m gke.io/optimize-utilization-scheduler Successfully assigned default/pvc-demo-pod to gk3-autopilot-cluster-1-nap-l8h3ctae-3077ca01-l9jp
Normal TriggeredScaleUp 6m28s cluster-autoscaler pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/qwiklabs-gcp-01-41684334779c/zones/us-east1-b/instanceGroups/gk3-autopilot-cluster-1-nap-l8h3ctae-3077ca01-grp 0->1 (max: 1000)}]
Normal NotTriggerScaleUp 5m5s cluster-autoscaler pod didn't trigger scale-up (it wouldn't fit if a new node is added): 3 Insufficient memory, 1 node(s) had untolerated taint {cloud.google.com/gke-quick-remove: true}, 18 node(s) didn't find available persistent volumes to bind, 3 Insufficient cpu
Normal SuccessfulAttachVolume 4m53s attachdetach-controller AttachVolume.Attach succeeded for volume "pvc-efe382e6-a099-4055-a17d-742273e9ec65"
Normal Pulling 4m45s kubelet Pulling image "nginx"
Normal Pulled 4m24s kubelet Successfully pulled image "nginx" in 15.328s (21.091s including waiting)
Normal Created 4m24s kubelet Created container frontend
Normal Started 4m24s kubelet Started container frontend
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl exec -it pvc-demo-pod -- sh
# echo Test webpage in a persistent volume!>/var/www/html/index.html
chmod +x /var/www/html/index.html#
# cat /var/www/html/index.html
Test webpage in a persistent volume!
# exit
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
You will now delete the Pod from the cluster, confirm that the PV still exists, then redeploy the Pod and verify the contents of the PV remain intact.
Test the persistence of the PV
You will now delete the Pod from the cluster, confirm that the PV still exists, then redeploy the Pod and verify the contents of the PV remain intact.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl delete pod pvc-demo-pod
pod "pvc-demo-pod" deleted
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
No resources found in default namespace.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
There should be no Pods on the cluster. Your PVC still exists, and was not deleted when the Pod was deleted.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get persistentvolumeclaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
hello-web-disk Bound pvc-efe382e6-a099-4055-a17d-742273e9ec65 30Gi RWO standard-rwo <unset> 12m
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
persistentvolume/pvc-efe382e6-a099-4055-a17d-742273e9ec65 30Gi RWO Delete Bound default/hello-web-disk standard-rwo <unset> 8m13s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/hello-web-disk Bound pvc-efe382e6-a099-4055-a17d-742273e9ec65 30Gi RWO standard-rwo <unset> 13m
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Redeploy the pvc-demo-pod:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl apply -f pod-volume-demo.yaml
Warning: autopilot-default-resources-mutator:Autopilot updated Pod default/pvc-demo-pod: defaulted unspecified 'cpu' resource for containers [frontend] (see http://g.co/gke/autopilot-defaults).
pod/pvc-demo-pod created
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 0/1 ContainerCreating 0 5s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 0/1 ContainerCreating 0 8s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-demo-pod 1/1 Running 0 15s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
The Pod will deploy and the status will change to “Running” faster this time because the PV already exists and does not need to be created.
- To verify the PVC is still accessible within the Pod, you must gain shell access to your Pod. To start the shell session, execute the following command:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl exec -it pvc-demo-pod -- sh
# cat /var/www/html/index.html
Test webpage in a persistent volume!
# exit
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
The contents of the persistent volume were not removed, even though the Pod was deleted from the cluster and recreated.
Create StatefulSets with PVCs
In this task, you use your PVC in a StatefulSet. A StatefulSet is like a Deployment, except that the Pods are given unique identifiers.
Release the PVC
Before you can use the PVC with the statefulset, you must delete the Pod that is currently using it. Execute the following command to delete the Pod:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl delete pod pvc-demo-pod
pod "pvc-demo-pod" deleted
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
No resources found in default namespace.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Create a StatefulSet
Let’s create a manifest file statefulset-demo.yaml
that creates a StatefulSet that includes a LoadBalancer service and three replicas of a Pod containing an nginx container and a volumeClaimTemplate for 30 gigabyte PVCs with the name hello-web-disk
. The nginx containers mount the PVC called hello-web-disk
at /var/www/html
as in the previous task.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ cat statefulset-demo.yaml
kind: Service
apiVersion: v1
metadata:
name: statefulset-demo-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
type: LoadBalancer
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-demo
spec:
selector:
matchLabels:
app: MyApp
serviceName: statefulset-demo-service
replicas: 3
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: MyApp
spec:
containers:
- name: stateful-set-container
image: nginx
ports:
- containerPort: 80
name: http
volumeMounts:
- name: hello-web-disk
mountPath: "/var/www/html"
volumeClaimTemplates:
- metadata:
name: hello-web-disk
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 30Gi
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
To create the StatefulSet with the volume, execute the following command:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl apply -f statefulset-demo.yaml
service/statefulset-demo-service created
Warning: autopilot-default-resources-mutator:Autopilot updated StatefulSet default/statefulset-demo: defaulted unspecified 'cpu' resource for containers [stateful-set-container] (see http://g.co/gke/autopilot-defaults).
statefulset.apps/statefulset-demo created
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Verify the connection of Pods in StatefulSets
- Use “kubectl describe” to view the details of the StatefulSet:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl describe statefulset statefulset-demo
Name: statefulset-demo
Namespace: default
CreationTimestamp: Sun, 23 Jun 2024 13:49:57 +0000
Selector: app=MyApp
Labels: <none>
Annotations: autopilot.gke.io/resource-adjustment:
{"input":{"containers":[{"name":"stateful-set-container"}]},"output":{"containers":[{"limits":{"cpu":"500m","ephemeral-storage":"1Gi","mem...
autopilot.gke.io/warden-version: 2.9.37
Replicas: 3 desired | 2 total
Update Strategy: RollingUpdate
Pods Status: 1 Running / 1 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=MyApp
Containers:
stateful-set-container:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Limits:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
Requests:
cpu: 500m
ephemeral-storage: 1Gi
memory: 2Gi
Environment: <none>
Mounts:
/var/www/html from hello-web-disk (rw)
Volumes: <none>
Volume Claims:
Name: hello-web-disk
StorageClass:
Labels: <none>
Annotations: <none>
Capacity: 30Gi
Access Modes: [ReadWriteOnce]
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 20s statefulset-controller create Claim hello-web-disk-statefulset-demo-0 Pod statefulset-demo-0 in StatefulSet statefulset-demo success
Normal SuccessfulCreate 19s statefulset-controller create Pod statefulset-demo-0 in StatefulSet statefulset-demo successful
Normal SuccessfulCreate 5s statefulset-controller create Claim hello-web-disk-statefulset-demo-1 Pod statefulset-demo-1 in StatefulSet statefulset-demo success
Normal SuccessfulCreate 4s statefulset-controller create Pod statefulset-demo-1 in StatefulSet statefulset-demo successful
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Note the event status at the end of the output. The service and statefulset created successfully.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
statefulset-demo-0 1/1 Running 0 80s
statefulset-demo-1 1/1 Running 0 65s
statefulset-demo-2 0/1 Pending 0 51s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
hello-web-disk Bound pvc-efe382e6-a099-4055-a17d-742273e9ec65 30Gi RWO standard-rwo <unset> 23m
hello-web-disk-statefulset-demo-0 Bound pvc-2c552959-5f21-4434-b99f-6b0c74d3a4d6 30Gi RWO standard-rwo <unset> 2m1s
hello-web-disk-statefulset-demo-1 Bound pvc-bf6c9e65-1be5-41c1-82d7-8b9cc6f03303 30Gi RWO standard-rwo <unset> 106s
hello-web-disk-statefulset-demo-2 Pending standard-rwo <unset> 91s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
The original hello-web-disk is still there and you can now see the individual PVCs that were created for each Pod in the new statefulset Pod.
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl describe pvc hello-web-disk-statefulset-demo-0
Name: hello-web-disk-statefulset-demo-0
Namespace: default
StorageClass: standard-rwo
Status: Bound
Volume: pvc-2c552959-5f21-4434-b99f-6b0c74d3a4d6
Labels: app=MyApp
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: pd.csi.storage.gke.io
volume.kubernetes.io/selected-node: gk3-autopilot-cluster-1-nap-l8h3ctae-3077ca01-l9jp
volume.kubernetes.io/storage-provisioner: pd.csi.storage.gke.io
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 30Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: statefulset-demo-0
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal WaitForFirstConsumer 2m40s persistentvolume-controller waiting for first consumer to be created before binding
Normal Provisioning 2m39s pd.csi.storage.gke.io_gke-108836dd682049699d1e-bde5-8604-vm_07f99d8a-4f7c-4e8d-bb52-f7671552978c External provisioner is provisioning volume for claim "default/hello-web-disk-statefulset-demo-0"
Normal ExternalProvisioning 2m39s persistentvolume-controller Waiting for a volume to be created either by the external provisioner 'pd.csi.storage.gke.io' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
Normal ProvisioningSucceeded 2m36s pd.csi.storage.gke.io_gke-108836dd682049699d1e-bde5-8604-vm_07f99d8a-4f7c-4e8d-bb52-f7671552978c Successfully provisioned volume pvc-2c552959-5f21-4434-b99f-6b0c74d3a4d6
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Verify the persistence of Persistent Volume connections to Pods managed by StatefulSets
In this task, you verify the connection of Pods in StatefulSets to particular PVs as the Pods are stopped and restarted.
To verify that the PVC is accessible within the Pod, you must gain shell access to your Pod. To start the shell session, execute the following command: Verify that there is no index.html
text file in the /var/www/html
directory: To create a simple text message as a web page in the Pod enter the following commands: Verify the text file contains your message:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl exec -it statefulset-demo-0 -- sh
# cat /var/www/html/index.html
cat: /var/www/html/index.html: No such file or directory
# echo Test webpage in a persistent volume!>/var/www/html/index.html
chmod +x /var/www/html/index.html#
# cat /var/www/html/index.html
Test webpage in a persistent volume!
# exit
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
Delete the Pod where you updated the file on the PVC:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl delete pod statefulset-demo-0
pod "statefulset-demo-0" deleted
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl get pods
NAME READY STATUS RESTARTS AGE
statefulset-demo-0 1/1 Running 0 28s
statefulset-demo-1 1/1 Running 0 6m22s
statefulset-demo-2 1/1 Running 0 7m19s
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
You will see that the StatefulSet is automatically restarting the statefulset-demo-0
Pod.
The StatefulSet restarts the Pod and reconnects the existing dedicated PVC to the new Pod, ensuring that the data for that Pod is preserved. Verify that the text file still contains your message:
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ kubectl exec -it statefulset-demo-0 -- sh
# cat /var/www/html/index.html
Test webpage in a persistent volume!
# exit
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$
History
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$ history
1 export my_region=us-east1
2 export my_cluster=autopilot-cluster-1
3 source <(kubectl completion bash)
4 gcloud container clusters get-credentials $my_cluster --region $my_region
5 nano pvc-demo.yaml
6 cat pvc-demo.yaml
7 kubectl get persistentvolumeclaim
8 kubectl apply -f pvc-demo.yaml
9 kubectl get persistentvolumeclaim
10 nano pod-volume-demo.yaml
11 cat pod-volume-demo.yaml
12 kubectl apply -f pod-volume-demo.yaml
13 kubectl get pods
14 kubectl get pv,pvc
15 kubectl get pods
16 kubectl describe pods pvc-demo-pod
17 kubectl get pods
18 kubectl get pv,pvc
19 kubectl describe pod pvc-demo-pod
20 kubectl exec -it pvc-demo-pod -- sh
21 kubectl get pods
22 kubectl get pods -o wide
23 curl 10.113.0.14
24 kubectl delete pod pvc-demo-pod
25 kubectl get pods
26 kubectl get persistentvolumeclaim
27 kubectl get pv,pvc
28 kubectl apply -f pod-volume-demo.yaml
29 kubectl get pods
30 kubectl exec -it pvc-demo-pod -- sh
31 kubectl delete pod pvc-demo-pod
32 kubectl get pods
33 nano statefulset-demo.yaml
34 cat statefulset-demo.yaml
35 kubectl apply -f statefulset-demo.yaml
36 kubectl describe statefulset statefulset-demo
37 kubectl get pods
38 kubectl get pvc
39 kubectl describe pvc hello-web-disk-statefulset-demo-0
40 kubectl exec -it statefulset-demo-0 -- sh
41 kubectl delete pod statefulset-demo-0
42 kubectl get pods
43 kubectl exec -it statefulset-demo-0 -- sh
44 history
student_03_995ecaa6bfd9@cloudshell:~ (qwiklabs-gcp-01-41684334779c)$