Implement DevOps Workflows in Google Cloud: Challenge Lab

This is from the Arcade October 2024 Series and also Implement DevOps Workflows in Google Cloud course.
This tutorial covers the Lab "Implement DevOps Workflows in Google Cloud: Challenge Lab", code: GSP330.
Overview
In a challenge lab, you’re presented with a scenario and a series of tasks. Rather than following detailed instructions, you’ll apply the skills you’ve acquired from the course labs to complete the tasks independently. An automated scoring system will give you feedback on your task completion.
During a challenge lab, no new Google Cloud concepts are introduced. Instead, you’re expected to enhance your existing skills, such as modifying default values and troubleshooting errors through research and problem-solving.
Challenge scenario
As a recent hire as a DevOps Engineer for Cymbal Superstore a few months ago, you have learned the ins and outs of how the company operates its e-commerce website. Specifically, the DevOps team is working on a large scale CI/CD pipeline that they would like your assistance with building. This allows the company to help developers automate tasks, collaborate more effectively with other teams, and release software more frequently and reliably. Your experience with Cloud Source Repositories, Artifact Registry, Docker, and Cloud Build is going to be a large help since Cymbal Superstore would like to use all native Google Cloud Services for their pipeline.
Your challenge
Your tasks include the following:
- Creating a GKE cluster based on a set of configurations provided.
- Creating a Google Source Repository to host your Go application code.
- Creating Cloud Build Triggers that deploy a production and development application.
- Pushing updates to the app and creating new builds.
- Rolling back the production application to a previous version.
Overall, you are creating a simple CI/CD pipeline using Cloud Source Repositories, Artifact Registry, and Cloud Build.
Before we start tackling the tasks, we will define the variables which will be used throughout the tasks:
export CLUSTER=hello-cluster
export REPO=my-repository
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_ID=$DEVSHELL_PROJECT_ID
export REGION="${ZONE%-*}"
Task 1. Create the lab resources
In this section, you initialize your Google Cloud project for the demo environment. You enable the required APIs, configure Git in Cloud Shell, create an Artifact Registry Docker repository, and create a GKE cluster to run your production and development applications on.
Run the following command to enable the APIs for GKE, Cloud Build, and Cloud Source Repositories:
gcloud services enable container.googleapis.com \
cloudbuild.googleapis.com \
sourcerepo.googleapis.com
SAMPLE OUTPUT:
Operation "operations/acat.p2-633507786321-b1c8ce71-aeef-48d8-b72e-bf32bcea55a4" finished successfully.
Add the Kubernetes Developer role for the Cloud Build service account:
export PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$(gcloud projects describe $PROJECT_ID \
--format="value(projectNumber)")@cloudbuild.gserviceaccount.com --role="roles/container.developer"
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$(gcloud projects describe $PROJECT_ID \
--format="value(projectNumber)")@cloudbuild.gserviceaccount.com --role="roles/container.developer"
Updated IAM policy for project [qwiklabs-gcp-00-da3fb3d8188d].
bindings:
- members:
- serviceAccount:qwiklabs-gcp-00-da3fb3d8188d@qwiklabs-gcp-00-da3fb3d8188d.iam.gserviceaccount.com
role: roles/bigquery.admin
- members:
- serviceAccount:[email protected]
role: roles/cloudbuild.builds.builder
- members:
- serviceAccount:[email protected]
role: roles/cloudbuild.serviceAgent
- members:
- serviceAccount:[email protected]
role: roles/compute.serviceAgent
- members:
- serviceAccount:[email protected]
role: roles/container.developer
- members:
- serviceAccount:service-633507786321@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
- members:
- serviceAccount:[email protected]
- serviceAccount:[email protected]
role: roles/editor
- members:
- serviceAccount:[email protected]
- serviceAccount:qwiklabs-gcp-00-da3fb3d8188d@qwiklabs-gcp-00-da3fb3d8188d.iam.gserviceaccount.com
- user:[email protected]
role: roles/owner
- members:
- serviceAccount:qwiklabs-gcp-00-da3fb3d8188d@qwiklabs-gcp-00-da3fb3d8188d.iam.gserviceaccount.com
role: roles/storage.admin
- members:
- user:[email protected]
role: roles/viewer
etag: BwYjiw1Bfm0=
version: 1
Run the following to configure Git in Cloud Shell, replacing <email>
with your generated lab email address and <name>
with your name.
git config --global user.email <email>
git config --global user.name <name>
Create an Artifact Registry Docker repository named my-repository in the region to store your container images.
gcloud artifacts repositories create $REPO \
--repository-format=docker \
--location=$REGION \
--description="Awesome Lab"
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ gcloud artifacts repositories create $REPO \
--repository-format=docker \
--location=$REGION \
--description="Awesome Lab"
Create request issued for: [my-repository]
Waiting for operation [projects/qwiklabs-gcp-00-da3fb3d8188d/locations/us-central1/operations
/b9c54dba-9a92-49b5-a503-f5569d6d2ea4] to complete...done.
Created repository [my-repository].
Create a GKE Standard cluster named hello-cluster
with the following command:
The following should work:
gcloud beta container --project "$PROJECT_ID" clusters create "$CLUSTER" --zone "$ZONE" --no-enable-basic-auth --cluster-version latest --release-channel "regular" --enable-autoscaling --min-nodes "2" --max-nodes "6"
If the above does not work use the following:
gcloud beta container --project "$PROJECT_ID" clusters create "$CLUSTER" --zone "$ZONE" --no-enable-basic-auth --cluster-version latest --release-channel "regular" --machine-type "e2-medium" --image-type "COS_CONTAINERD" --disk-type "pd-balanced" --disk-size "100" --metadata disable-legacy-endpoints=true --logging=SYSTEM,WORKLOAD --monitoring=SYSTEM --enable-ip-alias --network "projects/$PROJECT_ID/global/networks/default" --subnetwork "projects/$PROJECT_ID/regions/$REGION/subnetworks/default" --no-enable-intra-node-visibility --default-max-pods-per-node "110" --enable-autoscaling --min-nodes "2" --max-nodes "6" --location-policy "BALANCED" --no-enable-master-authorized-networks --addons HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver --enable-autoupgrade --enable-autorepair --max-surge-upgrade 1 --max-unavailable-upgrade 0 --enable-shielded-nodes --node-locations "$ZONE"
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ gcloud beta container --project "$PROJECT_ID" clusters create "$CLUSTER" --zone "$ZONE" --no-enable-basic-auth --cluster-version latest --release-channel "regular" --machine-type "e2-medium" --image-type "COS_CONTAINERD" --disk-type "pd-balanced" --disk-size "100" --metadata disable-legacy-endpoints=true --logging=SYSTEM,WORKLOAD --monitoring=SYSTEM --enable-ip-alias --network "projects/$PROJECT_ID/global/networks/default" --subnetwork "projects/$PROJECT_ID/regions/$REGION/subnetworks/default" --no-enable-intra-node-visibility --default-max-pods-per-node "110" --enable-autoscaling --min-nodes "2" --max-nodes "6" --location-policy "BALANCED" --no-enable-master-authorized-networks --addons HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver --enable-autoupgrade --enable-autorepair --max-surge-upgrade 1 --max-unavailable-upgrade 0 --enable-shielded-nodes --node-locations "$ZONE"
Note: The Kubelet readonly port (10255) is now deprecated. Please update your workloads to use the recommended alternatives. See https://cloud.google.com/kubernetes-engine/docs/how-to/disable-kubelet-readonly-port for ways to check usage and for migration instructions.
Creating cluster hello-cluster in us-central1-c... Cluster is being health-checked...working.
...
Creating cluster hello-cluster in us-central1-c... Cluster is being health-checked (Kubernete
s Control Plane is healthy)...done.
Created [https://container.googleapis.com/v1beta1/projects/qwiklabs-gcp-00-da3fb3d8188d/zones/us-central1-c/clusters/hello-cluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=qwiklabs-gcp-00-da3fb3d8188d
kubeconfig entry generated for hello-cluster.
NAME: hello-cluster
LOCATION: us-central1-c
MASTER_VERSION: 1.30.5-gke.1014001
MASTER_IP: 34.27.148.100
MACHINE_TYPE: e2-medium
NODE_VERSION: 1.30.5-gke.1014001
NUM_NODES: 3
STATUS: RUNNING
Create the prod
and dev
namespaces on your cluster.
kubectl create namespace prod
kubectl create namespace dev
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ kubectl create namespace prod
namespace/prod created
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ kubectl create namespace dev
namespace/dev created
Task 2. Create a repository in Cloud Source Repositories
In this task, you create a repository sample-app in Cloud Source Repositories and initialize it with some sample code. This repository holds your Go application code, and be the primary source for triggering builds.
Create an empty repository named sample-app in Cloud Source Repositories.
gcloud source repos create sample-app
Clone the sample-app Cloud Source Repository in Cloud Shell.
git clone https://source.developers.google.com/p/$PROJECT_ID/r/sample-app
Use the following command to copy the sample code into your sample-app
directory:
cd ~
gsutil cp -r gs://spls/gsp330/sample-app/* sample-app
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ gcloud source repos create sample-app
Created [sample-app].
WARNING: You may be billed for this repository. See https://cloud.google.com/source-repositories/docs/pricing for details.
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ git clone https://source.developers.google.com/p/$PROJECT_ID/r/sample-app
Cloning into 'sample-app'...
warning: You appear to have cloned an empty repository.
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ cd ~
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ gsutil cp -r gs://spls/gsp330/sample-app/* sample-app
Copying gs://spls/gsp330/sample-app/Dockerfile...
Copying gs://spls/gsp330/sample-app/cloudbuild-dev.yaml...
Copying gs://spls/gsp330/sample-app/cloudbuild.yaml...
Copying gs://spls/gsp330/sample-app/main.go...
- [4 files][ 3.7 KiB/ 3.7 KiB]
==> NOTE: You are performing a sequence of gsutil operations that may
run significantly faster if you instead use gsutil -m cp ... Please
see the -m section under "gsutil help options" for further information
about when gsutil -m can be advantageous.
Copying gs://spls/gsp330/sample-app/dev/deployment.yaml...
Copying gs://spls/gsp330/sample-app/prod/deployment.yaml...
\ [6 files][ 4.4 KiB/ 4.4 KiB]
Operation completed over 6 objects/4.4 KiB.
Run the following command, which will automatically replace the <your-region>
and <your-zone>
placeholders in the cloudbuild-dev.yaml
and cloudbuild.yaml
files with the assigned region and zone of your project:
for file in sample-app/cloudbuild-dev.yaml sample-app/cloudbuild.yaml; do
sed -i "s/<your-region>/${REGION}/g" "$file"
sed -i "s/<your-zone>/${ZONE}/g" "$file"
done
Make your first commit with the sample code added to your sample-app
directory, and push the changes to the master branch.
git init
cd sample-app/
git add .
git commit -m "Awesome Lab"
git push -u origin master
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/student_00_1c15d785d4f0/.git/
student_00_1c15d785d4f0@cloudshell:~ (qwiklabs-gcp-00-da3fb3d8188d)$ cd sample-app/
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git add .
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git commit -m "Awesome Lab"
[master (root-commit) f200772] Awesome Lab
6 files changed, 150 insertions(+)
create mode 100644 Dockerfile
create mode 100644 cloudbuild-dev.yaml
create mode 100644 cloudbuild.yaml
create mode 100644 dev/deployment.yaml
create mode 100644 main.go
create mode 100644 prod/deployment.yaml
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git push -u origin master
Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 2 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 2.14 KiB | 438.00 KiB/s, done.
Total 10 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3)
remote: Waiting for private key checker: 6/6 objects left
To https://source.developers.google.com/p/qwiklabs-gcp-00-da3fb3d8188d/r/sample-app
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git branch dev
Create a branch named dev. Make a commit with the sample code added to your sample-app
directory and push the changes to the dev branch.
git checkout dev
git push -u origin dev
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git checkout dev
Switched to branch 'dev'
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git push -u origin dev
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To https://source.developers.google.com/p/qwiklabs-gcp-00-da3fb3d8188d/r/sample-app
* [new branch] dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Verify you have the sample code and branches stored in the Source Repository.
The code you just cloned contains a simple Go application that has two entry points: Red and Blue. Each displays a simple colored square on the web page depending on the entry point you go to.
Task 3. Create the Cloud Build Triggers
In this section, you create two Cloud Build Triggers.
The first trigger listens for changes on the master
branch and builds a Docker image of your application, pushes it to Google Artifact Registry, and deploys the latest version of the image to the prod namespace in your GKE cluster.
The second trigger listens for changes on the dev
branch and build a Docker image of your application and push it to Google Artifact Registry, and deploy the latest version of the image to the dev namespace in your GKE cluster.
Create a Cloud Build Trigger named sample-app-prod-deploy that with the following configurations:
- Event: Push to a branch
- Source Repository:
sample-app
- Branch:
^master$
- Cloud Build Configuration File:
cloudbuild.yaml
gcloud builds triggers create cloud-source-repositories \
--name="sample-app-prod-deploy" \
--service-account="projects/$PROJECT_ID/serviceAccounts/$PROJECT_ID@$PROJECT_ID.iam.gserviceaccount.com" \
--description="Cloud Build Trigger for production deployment" \
--repo="sample-app" \
--branch-pattern="^master$" \
--build-config="cloudbuild.yaml"
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ gcloud builds triggers create cloud-source-repositories \
--name="sample-app-prod-deploy" \
--service-account="projects/$PROJECT_ID/serviceAccounts/$PROJECT_ID@$PROJECT_ID.iam.gserviceaccount.com" \
--description="Cloud Build Trigger for production deployment" \
--repo="sample-app" \
--branch-pattern="^master$" \
--build-config="cloudbuild.yaml"
Created [https://cloudbuild.googleapis.com/v1/projects/qwiklabs-gcp-00-da3fb3d8188d/locations/global/triggers/72b81a4d-f2bb-434d-973a-44c29b04fce7].
NAME: sample-app-prod-deploy
CREATE_TIME: 2024-10-03T04:43:18+00:00
STATUS:
Create a Cloud Build Trigger named sample-app-dev-deploy that with the following configurations:
- Event: Push to a branch
- Source Repository:
sample-app
- Branch:
^dev$
- Cloud Build Configuration File:
cloudbuild-dev.yam
gcloud builds triggers create cloud-source-repositories \
--name="sample-app-dev-deploy" \
--service-account="projects/$PROJECT_ID/serviceAccounts/$PROJECT_ID@$PROJECT_ID.iam.gserviceaccount.com" \
--description="Cloud Build Trigger for development deployment" \
--repo="sample-app" \
--branch-pattern="^dev$" \
--build-config="cloudbuild-dev.yaml"
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ gcloud builds triggers create cloud-source-repositories \
--name="sample-app-dev-deploy" \
--service-account="projects/$PROJECT_ID/serviceAccounts/$PROJECT_ID@$PROJECT_ID.iam.gserviceaccount.com" \
--description="Cloud Build Trigger for development deployment" \
--repo="sample-app" \
--branch-pattern="^dev$" \
--build-config="cloudbuild-dev.yaml"
Created [https://cloudbuild.googleapis.com/v1/projects/qwiklabs-gcp-00-da3fb3d8188d/locations/global/triggers/05081d18-b4e1-4ce3-8d89-e17a47532af3].
NAME: sample-app-dev-deploy
CREATE_TIME: 2024-10-03T04:43:33+00:00
STATUS:
After setting up the triggers, any changes to the branches trigger the corresponding Cloud Build pipeline, which builds and deploy the application as specified in the cloudbuild.yaml
files.
Click Check my progress to verify the objective.
Task 4. Deploy the first versions of the application
In this section, you build the first version of the production application and the development application.
Build the first development deployment
In Cloud Shell, inspect the cloudbuild-dev.yaml
file located in the sample-app directory to see the steps in the build process. In cloudbuild-dev.yaml
file, replace the <version>
on lines 9 and 13 with v1.0
.
sed -i "9c\ args: ['build', '-t', '$REGION-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild-dev:v1.0', '.']" cloudbuild-dev.yaml
sed -i "13c\ args: ['push', '$REGION-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild-dev:v1.0']" cloudbuild-dev.yaml
Navigate to the dev/deployment.yaml
file and Update the <todo>
on line 17 with the correct container image name. Also, replace the PROJECT_ID
variable with actual project ID in the container image name
sed -i "17s| image: <todo>| image: $REGION-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild-dev:v1.0|" dev/deployment.yaml
Make a commit with your changes on the dev
branch and push changes to trigger the sample-app-dev-deploy build job.
git add .
git commit -m "Awesome Lab"
git push -u origin dev
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git add .
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git commit -m "Awesome Lab"
[dev bfd8154] Awesome Lab
2 files changed, 3 insertions(+), 3 deletions(-)
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git push -u origin dev
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 2 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 556 bytes | 278.00 KiB/s, done.
Total 5 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3)
remote: Waiting for private key checker: 2/2 objects left
To https://source.developers.google.com/p/qwiklabs-gcp-00-da3fb3d8188d/r/sample-app
f200772..bfd8154 dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Verify your build executed successfully in Cloud build History page, and verify the development-deployment application was deployed onto the dev
namespace of the cluster.
Expose the development-deployment deployment to a LoadBalancer service named dev-deployment-service
on port 8080, and set the target port of the container to the one specified in the Dockerfile.
git checkout master
kubectl expose deployment development-deployment -n dev --name=dev-deployment-service --type=LoadBalancer --port 8080 --target-port 8080
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ kubectl expose deployment development-deployment -n dev --name=dev-deployment-service --type=LoadBalancer --port 8080 --target-port 8080
service/dev-deployment-service exposed
Build the first production deployment
Switch to the master
branch. Inspect the cloudbuild.yaml
file located in the sample-app directory to see the steps in the build process. In cloudbuild.yaml
file, replace the <version>
on lines 11 and 16 with v1.0
.
sed -i "11c\ args: ['build', '-t', '$REGION-docker.pkg.dev/\$PROJECT_ID/my-repository/hello-cloudbuild:v1.0', '.']" cloudbuild.yaml
sed -i "16c\ args: ['push', '$REGION-docker.pkg.dev/\$PROJECT_ID/my-repository/hello-cloudbuild:v1.0']" cloudbuild.yaml
Navigate to the prod/deployment.yaml
file and update the <todo>
on line 17 with the correct container image name. Also, replace the PROJECT_ID
variable with actual project ID in the container image name
sed -i "17c\ image: $REGION-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:v1.0" prod/deployment.yaml
Make a commit with your changes on the master
branch and push changes to trigger the sample-app-prod-deploy build job.
git add .
git commit -m "Awesome Lab"
git push -u origin master
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git add .
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git commit -m "Awesome Lab"
[master 2cf5c52] Awesome Lab
2 files changed, 3 insertions(+), 3 deletions(-)
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git push -u origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 2 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 517 bytes | 172.00 KiB/s, done.
Total 5 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3)
remote: Waiting for private key checker: 2/2 objects left
To https://source.developers.google.com/p/qwiklabs-gcp-00-da3fb3d8188d/r/sample-app
f200772..2cf5c52 master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
Verify your build executed successfully in Cloud build History page, and verify the production-deployment application was deployed onto the prod
namespace of the cluster.
Expose the production-deployment deployment on the prod
namespace to a LoadBalancer service named prod-deployment-service
on port 8080, and set the target port of the container to the one specified in the Dockerfile.
kubectl expose deployment production-deployment -n prod --name=prod-deployment-service --type=LoadBalancer --port 8080 --target-port 8080
Navigate to the Load Balancer IP of the service and add the /blue
entry point at the end of the URL to verify the application is up and running. It should resemble something like the following: http://34.135.245.19:8080/blue
.
Click Check my progress to verify the objective.
Task 5. Deploy the second versions of the application
In this section, you build the second version of the production application and the development application.
Build the second development deployment
Switch back to the dev
branch
git checkout dev
In the main.go
file, update the main()
function to the following. Add the following function inside of the main.go
file:
sed -i '32a\
func redHandler(w http.ResponseWriter, r *http.Request) { \
img := image.NewRGBA(image.Rect(0, 0, 100, 100)) \
draw.Draw(img, img.Bounds(), &image.Uniform{color.RGBA{255, 0, 0, 255}}, image.ZP, draw.Src) \
w.Header().Set("Content-Type", "image/png") \
png.Encode(w, img) \
}' main.go
Inspect the cloudbuild-dev.yaml
file to see the steps in the build process. Update the version of the Docker image to v2.0
.
sed -i "9c\ args: ['build', '-t', '$REGION-docker.pkg.dev/\$PROJECT_ID/my-repository/hello-cloudbuild-dev:v2.0', '.']" cloudbuild-dev.yaml
sed -i "13c\ args: ['push', '$REGION-docker.pkg.dev/\$PROJECT_ID/my-repository/hello-cloudbuild-dev:v2.0']" cloudbuild-dev.yaml
Navigate to the dev/deployment.yaml
file and update the container image name to the new version (v2.0
).
sed -i "17c\ image: $REGION-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:v2.0" dev/deployment.yaml
Make a commit with your changes on the dev
branch and push changes to trigger the sample-app-dev-deploy build job.
git add .
git commit -m "Awesome Lab"
git push -u origin dev
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git add .
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git commit -m "Awesome Lab"
[dev b9b4e80] Awesome Lab
3 files changed, 10 insertions(+), 3 deletions(-)
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git push -u origin dev
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 2 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 710 bytes | 355.00 KiB/s, done.
Total 6 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3)
remote: Waiting for private key checker: 3/3 objects left
To https://source.developers.google.com/p/qwiklabs-gcp-00-da3fb3d8188d/r/sample-app
bfd8154..b9b4e80 dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Verify your build executed successfully in Cloud build History page, and verify the development-deployment application was deployed onto the dev
namespace of the cluster and is using the v2.0
image.
Navigate to the Load Balancer IP of the service and add the /red
entry point at the end of the URL to verify the application is up and running. It should resemble something like the following: http://34.135.97.199:8080/red
.
Build the second production deployment
- Switch to the
master
branch.
git checkout master
Make the following changes to main.go
:
sed -i '28a\ http.HandleFunc("/red", redHandler)' main.go
sed -i '32a\
func redHandler(w http.ResponseWriter, r *http.Request) { \
img := image.NewRGBA(image.Rect(0, 0, 100, 100)) \
draw.Draw(img, img.Bounds(), &image.Uniform{color.RGBA{255, 0, 0, 255}}, image.ZP, draw.Src) \
w.Header().Set("Content-Type", "image/png") \
png.Encode(w, img) \
}' main.go
Inspect the cloudbuild.yaml
file to see the steps in the build process. Update the version of the Docker image to v2.0
.
sed -i "11c\ args: ['build', '-t', '$REGION-docker.pkg.dev/\$PROJECT_ID/my-repository/hello-cloudbuild:v2.0', '.']" cloudbuild.yaml
sed -i "16c\ args: ['push', '$REGION-docker.pkg.dev/\$PROJECT_ID/my-repository/hello-cloudbuild:v2.0']" cloudbuild.yaml
Navigate to the prod/deployment.yaml
file and update the container image name to the new version (v2.0
).
sed -i "17c\ image: $REGION-docker.pkg.dev/$PROJECT_ID/my-repository/hello-cloudbuild:v2.0" prod/deployment.yaml
Make a commit with your changes on the master
branch and push changes to trigger the sample-app-prod-deploy build job.
git add .
git commit -m "Awesome Lab"
git push -u origin master
SAMPLE OUTPUT:
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git add .
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git commit -m "Awesome Lab"
[master 3f7e681] Awesome Lab
3 files changed, 10 insertions(+), 3 deletions(-)
student_00_1c15d785d4f0@cloudshell:~/sample-app (qwiklabs-gcp-00-da3fb3d8188d)$ git push -u origin master
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 2 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 605 bytes | 302.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4)
remote: Waiting for private key checker: 3/3 objects left
To https://source.developers.google.com/p/qwiklabs-gcp-00-da3fb3d8188d/r/sample-app
2cf5c52..3f7e681 master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'
Verify your build executed successfully in Cloud build History page, and verify the production-deployment application was deployed onto the prod
namespace of the cluster and is using the v2.0
image.
Navigate to the Load Balancer IP of the service and add the /red
entry point at the end of the URL to verify the application is up and running. It should resemble something like the following: http://34.135.245.19:8080/red
.
Note: it may take a couple of minutes for the updates to propagate to your load balancer.
Great! You have successfully created fully functioning production and development CI/CD pipelines.
Click Check my progress to verify the objective.
Task 6. Roll back the production deployment
In this section, you roll back the production deployment to a previous version.
- Roll back the production-deployment to use the
v1.0
version of the application.
kubectl -n prod rollout undo deployment/production-deployment
Navigate to the Load Balancer IP of the service and add the /red
entry point at the end of the URL of the production deployment and response on the page should be 404
.
Click Check my progress to verify the objective.