GKE Backup and Restore
Backup for GKE is a service for backing up and restoring workloads in GKE clusters. It has two components:
- A Google Cloud API serves as the control plane for the service.
- A GKE add-on (the Backup for GKE agent) must be enabled in each cluster for which you wish to perform backup and restore operations.
Backups of your workloads may be useful for disaster recovery, CI/CD pipelines, cloning workloads, or upgrade scenarios. Protecting your workloads can help you achieve business-critical recovery point objectives.
- Enable Backup for a GKE cluster
- Deploy a stateful application with a database on GKE
- Plan and backup GKE workloads
- Restore a backup
Set up the environment
A GKE cluster and a static external IP address were provisioned as part of the lab setup.
- Run the following commands to set the required environment variables:
Welcome to Cloud Shell! Type "help" to get started.
Your Cloud Platform project in this session is set to qwiklabs-gcp-03-3f9aaf332b35.
Use “gcloud config set project [PROJECT_ID]” to change to a different project.
student_01_802c2e6ada6b@cloudshell:~ (qwiklabs-gcp-03-3f9aaf332b35)$ echo "export ZONE=us-central1-a" >> ~/.bashrc
echo "export REGION=us-central1" >> ~/.bashrc
echo "export PROJECT_ID=`gcloud config get-value core/project`" >> ~/.bashrc
echo "export BACKUP_PLAN=my-backup-plan" >> ~/.bashrc
source ~/.bashrc
echo "export EXTERNAL_ADDRESS=$(gcloud compute addresses describe app-address --format='value(address)' --region $REGION)" >> ~/.bashrc
source ~/.bashrc
Your active configuration is: [cloudshell-3558]
student_01_802c2e6ada6b@cs-52335668542-default:~$
Enable Backup for GKE
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud services enable gkebackup.googleapis.com
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container clusters update lab-cluster \
--project=$PROJECT_ID \
--update-addons=BackupRestore=ENABLED \
--zone=$ZONE
Updating lab-cluster...working...
Updating lab-cluster...working..
Updating lab-cluster...working Updating lab-cluster...done.
Updated [https://container.googleapis.com/v1beta1/projects/qwiklabs-gcp-03-3f9aaf332b35/zones/us-central1-a/clusters/lab-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-a/lab-cluster?project=qwiklabs-gcp-03-3f9aaf332b35
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container clusters describe lab-cluster \
--project=$PROJECT_ID \
--zone=$ZONE | grep -A 1 gkeBackupAgentConfig:
gkeBackupAgentConfig:
enabled: true
student_01_802c2e6ada6b@cs-52335668542-default:~$
Create a backup plan
- Run the following to create a backup plan:
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore backup-plans create $BACKUP_PLAN \
--project=$PROJECT_ID \
--location=$REGION \
--cluster=projects/${PROJECT_ID}/locations/${ZONE}/clusters/lab-cluster \
--all-namespaces \
--include-secrets \
--include-volume-data \
--cron-schedule="10 3 * * *" \
--backup-retain-days=30
Create request issued for: [my-backup-plan]
Waiting for operation [projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/operations/operation-1716852455392-61977dcbc43f4-be64dcd7
-bced39eb] to complete...done.
Created backup plan [my-backup-plan].
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore backup-plans list \
--project=$PROJECT_ID \
--location=$REGION
NAME: my-backup-plan
LOCATION: us-central1
CLUSTER: lab-cluster
ACTIVE: Y
PAUSED: N
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore backup-plans describe $BACKUP_PLAN \
--project=$PROJECT_ID \
--location=$REGION
backupConfig:
allNamespaces: true
includeSecrets: true
includeVolumeData: true
backupSchedule:
cronSchedule: 10 3 * * *
nextScheduledBackupTime: '2024-05-28T03:10:00Z'
cluster: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1-a/clusters/lab-cluster
createTime: '2024-05-27T23:27:36.657552088Z'
etag: '2'
name: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/backupPlans/my-backup-plan
retentionPolicy:
backupRetainDays: 30
rpoRiskLevel: 2
rpoRiskReason: No RPO config is defined. Switch to RPO schedule for better protection.
state: READY
stateReason: Resource has been created successfully.
uid: 16e421c9-6c9d-4772-9ae4-f647f87adf43
updateTime: '2024-05-27T23:29:30.476506293Z'
student_01_802c2e6ada6b@cs-52335668542-default:~$
Deploy WordPress with MySQL to the cluster
student_01_802c2e6ada6b@cs-52335668542-default:~$ # Password for lab only. Change to a strong one in your environment.
YOUR_SECRET_PASSWORD=1234567890
kubectl create secret generic mysql-pass --from-literal=password=${YOUR_SECRET_PASSWORD?}
kubectl apply -f https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
secret/mysql-pass created
service/wordpress-mysql created
persistentvolumeclaim/mysql-pv-claim created
deployment.apps/wordpress-mysql created
service/wordpress created
persistentvolumeclaim/wp-pv-claim created
deployment.apps/wordpress created
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ patch_file=/tmp/loadbalancer-patch.yaml
cat <<EOF > ${patch_file}
spec:
loadBalancerIP: ${EXTERNAL_ADDRESS}
EOF
kubectl patch service/wordpress --patch "$(cat ${patch_file})"
service/wordpress patched
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ while ! curl --fail --max-time 5 --output /dev/null --show-error --silent http://${EXTERNAL_ADDRESS}; do
sleep 5
done
echo -e "\nhttp://${EXTERNAL_ADDRESS} is accessible\n"
curl: (28) Connection timed out after 5001 milliseconds
curl: (28) Connection timed out after 5001 milliseconds
http://35.184.216.238 is accessible
student_01_802c2e6ada6b@cs-52335668542-default:~$
Verify the deployed workload
- In the Cloud console, navigate to Kubernetes Engine > Workload. You should see the WordPress application and its database.
- Open a browser window and paste in the URL from the previous step. You should see the following page:
- Click the Continue button and type in the required info. For example:
Make a note of the password and click the Install WordPress button.
After you log in to the WordPress application, try to create some new posts and add a few comments to existing posts. After backup/restore, you want to verify your input still exists.
Create a backup
- Create a backup based on the backup plan:
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore backups create my-backup1 \
--project=$PROJECT_ID \
--location=$REGION \
--backup-plan=$BACKUP_PLAN \
--wait-for-completion
Create in progress for backup my-backup1 [projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/operations/operation-1716853146830-6197805f2c6be-bd5a0b0e-75b5ca8c].
Creating backup my-backup1...done.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Waiting for backup to complete... Backup state: IN_PROGRESS.
Backup completed. Backup state: SUCCEEDED
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore backups list \
--project=$PROJECT_ID \
--location=$REGION \
--backup-plan=$BACKUP_PLAN
NAME: my-backup1
LOCATION: us-central1
BACKUP_PLAN: my-backup-plan
CREATE_TIME: 2024-05-27T23:39:06 UTC
COMPLETE_TIME: 2024-05-27T23:40:30 UTC
STATE: SUCCEEDED
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore backups describe my-backup1 \
--project=$PROJECT_ID \
--location=$REGION \
--backup-plan=$BACKUP_PLAN
allNamespaces: true
clusterMetadata:
backupCrdVersions:
backupjobs.gkebackup.gke.io: v1
protectedapplicationgroups.gkebackup.gke.io: v1
protectedapplications.gkebackup.gke.io: v1
restorejobs.gkebackup.gke.io: v1
cluster: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1-a/clusters/lab-cluster
gkeVersion: v1.28.8-gke.1095000
k8sVersion: '1.28'
completeTime: '2024-05-27T23:40:30.604094428Z'
configBackupSizeBytes: '519094'
containsSecrets: true
containsVolumeData: true
createTime: '2024-05-27T23:39:06.836575056Z'
deleteLockExpireTime: '2024-05-27T23:39:06.825687927Z'
etag: '8'
manual: true
name: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/backupPlans/my-backup-plan/backups/my-backup1
podCount: 2
resourceCount: 426
retainDays: 30
retainExpireTime: '2024-06-27T00:03:06.825687927Z'
sizeBytes: '56571766'
state: SUCCEEDED
uid: 3a518917-7ec8-4bd0-b314-131c135ec00b
updateTime: '2024-05-27T23:40:32.846357333Z'
volumeCount: 2
student_01_802c2e6ada6b@cs-52335668542-default:~$
Delete the application
You can restore the backup on the same cluster or a different one. In this lab, you will perform a restore on the same cluster.
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl delete secret mysql-pass
kubectl delete -f https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
kubectl delete -f https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
secret "mysql-pass" deleted
service "wordpress-mysql" deleted
persistentvolumeclaim "mysql-pv-claim" deleted
deployment.apps "wordpress-mysql" deleted
service "wordpress" deleted
persistentvolumeclaim "wp-pv-claim" deleted
deployment.apps "wordpress" deleted
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
No resources found in default namespace.
student_01_802c2e6ada6b@cs-52335668542-default:~$ echo -e "\nWordPress URL: http://${EXTERNAL_ADDRESS}\n"
WordPress URL: http://35.184.216.238
student_01_802c2e6ada6b@cs-52335668542-default:~$
Plan a restore
- Create a restore plan:
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore restore-plans create my-restore-plan1 \
--project=$PROJECT_ID \
--location=$REGION \
--backup-plan=projects/${PROJECT_ID}/locations/${REGION}/backupPlans/$BACKUP_PLAN \
--cluster=projects/${PROJECT_ID}/locations/${ZONE}/clusters/lab-cluster \
--namespaced-resource-restore-mode=delete-and-restore \
--volume-data-restore-policy=restore-volume-data-from-backup \
--all-namespaces
Create request issued for: [my-restore-plan1]
Waiting for operation [projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/operations/operation-1716853464816-6197818e6db20-f923f1bc
-e846236c] to complete...done.
Created restore plan [my-restore-plan1].
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore restore-plans list \
--project=$PROJECT_ID \
--location=$REGION
NAME: my-restore-plan1
LOCATION: us-central1
CLUSTER: lab-cluster
BACKUP_PLAN: my-backup-plan
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore restore-plans describe my-restore-plan1 \
--project=$PROJECT_ID \
--location=$REGION
backupPlan: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/backupPlans/my-backup-plan
cluster: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1-a/clusters/lab-cluster
createTime: '2024-05-27T23:44:24.860740618Z'
etag: '2'
name: projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/restorePlans/my-restore-plan1
restoreConfig:
allNamespaces: true
namespacedResourceRestoreMode: DELETE_AND_RESTORE
volumeDataRestorePolicy: RESTORE_VOLUME_DATA_FROM_BACKUP
state: READY
stateReason: Resource has been created successfully.
uid: f4fa83d2-d509-471b-9c32-bf7bc9695ec4
updateTime: '2024-05-27T23:44:25.312226455Z'
student_01_802c2e6ada6b@cs-52335668542-default:~$
Restore a backup
- Restore from the backup
student_01_802c2e6ada6b@cs-52335668542-default:~$ gcloud beta container backup-restore restores create my-restore1 \
--project=$PROJECT_ID \
--location=$REGION \
--restore-plan=my-restore-plan1 \
--backup=projects/${PROJECT_ID}/locations/${REGION}/backupPlans/${BACKUP_PLAN}/backups/my-backup1 \
--wait-for-completion
Create in progress for restore my-restore1 [projects/qwiklabs-gcp-03-3f9aaf332b35/locations/us-central1/operations/operation-1716853583086-619781ff3841d-4beabcdd-a75869d2].
Creating restore my-restore1...done.
Restore completed. Restore state: SUCCEEDED
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 Pending 0 20s
wordpress-mysql-68fd75cb99-dc69f 0/1 Pending 0 20s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 Pending 0 35s
wordpress-mysql-68fd75cb99-dc69f 0/1 Pending 0 35s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 ContainerCreating 0 40s
wordpress-mysql-68fd75cb99-dc69f 0/1 ContainerCreating 0 40s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 ContainerCreating 0 43s
wordpress-mysql-68fd75cb99-dc69f 0/1 ContainerCreating 0 43s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 ContainerCreating 0 46s
wordpress-mysql-68fd75cb99-dc69f 0/1 ContainerCreating 0 46s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 ContainerCreating 0 55s
wordpress-mysql-68fd75cb99-dc69f 0/1 ContainerCreating 0 55s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 0/1 ContainerCreating 0 60s
wordpress-mysql-68fd75cb99-dc69f 1/1 Running 0 60s
student_01_802c2e6ada6b@cs-52335668542-default:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-7867b7f788-nxclr 1/1 Running 0 63s
wordpress-mysql-68fd75cb99-dc69f 1/1 Running 0 63s
student_01_802c2e6ada6b@cs-52335668542-default:~$
student_01_802c2e6ada6b@cs-52335668542-default:~$ echo -e "\nWordPress URL: http://${EXTERNAL_ADDRESS}\n"
WordPress URL: http://35.184.216.238
student_01_802c2e6ada6b@cs-52335668542-default:~$
History
student_01_802c2e6ada6b@cs-52335668542-default:~$ history
1 echo "export ZONE=us-central1-a" >> ~/.bashrc
2 echo "export REGION=us-central1" >> ~/.bashrc
3 echo "export PROJECT_ID=`gcloud config get-value core/project`" >> ~/.bashrc
4 echo "export BACKUP_PLAN=my-backup-plan" >> ~/.bashrc
5 source ~/.bashrc
6 echo "export EXTERNAL_ADDRESS=$(gcloud compute addresses describe app-address --format='value(address)' --region $REGION)" >> ~/.bashrc
7 source ~/.bashrc
8 gcloud services enable gkebackup.googleapis.com
9 gcloud beta container clusters update lab-cluster --project=$PROJECT_ID --update-addons=BackupRestore=ENABLED --zone=$ZONE
10 gcloud beta container clusters describe lab-cluster --project=$PROJECT_ID --zone=$ZONE | grep -A 1 gkeBackupAgentConfig:
11 gcloud beta container backup-restore backup-plans create $BACKUP_PLAN --project=$PROJECT_ID --location=$REGION --cluster=projects/${PROJECT_ID}/locations/${ZONE}/clusters/lab-cluster --all-namespaces --include-secrets --include-volume-data --cron-schedule="10 3 * * *" --backup-retain-days=30
12 gcloud beta container backup-restore backup-plans list --project=$PROJECT_ID --location=$REGION
13 gcloud beta container backup-restore backup-plans describe $BACKUP_PLAN --project=$PROJECT_ID --location=$REGION
14 gcloud container clusters get-credentials lab-cluster --zone=$ZONE
15 echo "EXTERNAL_ADDRESS=${EXTERNAL_ADDRESS}"
16 # Password for lab only. Change to a strong one in your environment.
17 YOUR_SECRET_PASSWORD=1234567890
18 kubectl create secret generic mysql-pass --from-literal=password=${YOUR_SECRET_PASSWORD?}
19 kubectl apply -f https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
20 kubectl apply -f https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
21 patch_file=/tmp/loadbalancer-patch.yaml
22 cat <<EOF > ${patch_file}
spec:
loadBalancerIP: ${EXTERNAL_ADDRESS}
EOF
23 kubectl patch service/wordpress --patch "$(cat ${patch_file})"
24 while ! curl --fail --max-time 5 --output /dev/null --show-error --silent http://${EXTERNAL_ADDRESS}; do sleep 5; done
25 echo -e "\nhttp://${EXTERNAL_ADDRESS} is accessible\n"
26 gcloud beta container backup-restore backups create my-backup1 --project=$PROJECT_ID --location=$REGION --backup-plan=$BACKUP_PLAN --wait-for-completion
27 gcloud beta container backup-restore backups list --project=$PROJECT_ID --location=$REGION --backup-plan=$BACKUP_PLAN
28 gcloud beta container backup-restore backups describe my-backup1 --project=$PROJECT_ID --location=$REGION --backup-plan=$BACKUP_PLAN
29 kubectl delete secret mysql-pass
30 kubectl delete -f https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
31 kubectl delete -f https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
32 kubectl get pods
33 echo -e "\nWordPress URL: http://${EXTERNAL_ADDRESS}\n"
34 gcloud beta container backup-restore restore-plans create my-restore-plan1 --project=$PROJECT_ID --location=$REGION --backup-plan=projects/${PROJECT_ID}/locations/${REGION}/backupPlans/$BACKUP_PLAN --cluster=projects/${PROJECT_ID}/locations/${ZONE}/clusters/lab-cluster --namespaced-resource-restore-mode=delete-and-restore --volume-data-restore-policy=restore-volume-data-from-backup --all-namespaces
35 gcloud beta container backup-restore restore-plans list --project=$PROJECT_ID --location=$REGION
36 gcloud beta container backup-restore restore-plans describe my-restore-plan1 --project=$PROJECT_ID --location=$REGION
37 gcloud beta container backup-restore restores create my-restore1 --project=$PROJECT_ID --location=$REGION --restore-plan=my-restore-plan1 --backup=projects/${PROJECT_ID}/locations/${REGION}/backupPlans/${BACKUP_PLAN}/backups/my-backup1 --wait-for-completion
38 kubectl get pods
39 echo -e "\nWordPress URL: http://${EXTERNAL_ADDRESS}\n"
40 history
student_01_802c2e6ada6b@cs-52335668542-default:~$