Releasing with Cloud Deploy

1. Objectives

In this tutorial you will create three GKE clusters named preview, canary and prod. Then, create a Cloud Deploy target corresponding to each cluster and a Cloud Deploy pipeline that will define the sequence of steps to perform deployment in those targets.

The deployment flow will be triggered by a cloudbuild pipeline that will create Cloud Deploy release and perform the deployment in the preview cluster. After you have verified that the deployment in preview was successful and working as expected, you will manually promote the release in the canary cluster. Promotion of the release in the prod cluster will require approval, you will approve the prod pipeline in Cloud Deploy UI and finally promote it.

The objectives of this tutorial can be broken down into the following steps:

  • Prepare your workspace
  • Define Cloud Deploy targets
  • Define Cloud Deploy pipeline
  • Create a Release
  • Promote a deployment
  • Approve a production release

Self-paced environment setup

  1. Sign-in to the Google Cloud Console and create a new project or reuse an existing one. If you don't already have a Gmail or Google Workspace account, you must create one.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • The Project name is the display name for this project's participants. It is a character string not used by Google APIs, and you can update it at any time.
  • The Project ID must be unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference the Project ID (and it is typically identified as PROJECT_ID), so if you don't like it, generate another random one, or, you can try your own and see if it's available. Then it's "frozen" after the project is created.
  • There is a third value, a Project Number which some APIs use. Learn more about all three of these values in the documentation.
  1. Next, you'll need to enable billing in the Cloud Console in order to use Cloud resources/APIs. Running through this codelab shouldn't cost much, if anything at all. To shut down resources so you don't incur billing beyond this tutorial, follow any "clean-up" instructions found at the end of the codelab. New users of Google Cloud are eligible for the $300 USD Free Trial program.

2. Platform Setup

Preparing your workspace

We will set up our environment here required to run this tutorial. When this step is completed, we will have a GKE cluster created where we can run the deployments.

  1. Set gcloud config defaults

gcloud config set project <your project>

gcloud config set deploy/region us-central1

  1. Clone Repo

git clone https://github.com/gushob21/software-delivery-workshop

cd software-delivery-workshop/labs/cloud-deploy/

cloudshell workspace .

rm -rf deploy && mkdir deploy

  1. Set environment variables

export PROJECT_ID=$(gcloud config get-value project)

export PROJECT_NUMBER=$(gcloud projects list --filter="$PROJECT_ID" --format="value(PROJECT_NUMBER)")

  1. Enable APIs

gcloud services enable \

cloudresourcemanager.googleapis.com \

    `container.googleapis.com \`

    `cloudbuild.googleapis.com \`

    `containerregistry.googleapis.com \`

    `secretmanager.googleapis.com \`

    `clouddeploy.googleapis.com` 
  1. Create GKE clusters
     `gcloud container clusters create preview \`
    

--zone=us-central1-a --async

    `gcloud container clusters create canary \`

--zone=us-central1-b --async

    `gcloud container clusters create prod \`

--zone=us-central1-c

Defining Cloud Deploy Targets

  1. Create a file in the deploy directory named preview.yaml with the following command in cloudshell:

cat <<EOF >deploy/preview.yaml

apiVersion: deploy.cloud.google.com/v1beta1

kind: Target

metadata:

name: preview

annotations: {}

labels: {}

description: Target for preview environment

gke:

cluster: projects/$PROJECT_ID/locations/us-central1-a/clusters/preview

EOF

    As you noticed, the "kind" tag is "Target". It allows us to add some metadata to the target, a description and finally the GKE cluster where the deployment is supposed to happen for this target.
  1. Create a file in the deploy directory named canary.yaml with the following command in cloudshell:

cat <<EOF >deploy/canary.yaml

apiVersion: deploy.cloud.google.com/v1beta1

kind: Target

metadata:

name: canary

annotations: {}

labels: {}

description: Target for canary environment

gke:

cluster: projects/$PROJECT_ID/locations/us-central1-b/clusters/canary

EOF

  1. Create a file in the deploy directory named prod.yaml with the following command in cloudshell:

cat <<EOF >deploy/prod.yaml

apiVersion: deploy.cloud.google.com/v1beta1

kind: Target

metadata:

name: prod

annotations: {}

labels: {}

description: Target for prod environment

requireApproval: true

gke:

cluster: projects/$PROJECT_ID/locations/us-central1-c/clusters/prod

EOF

Notice the tag requireApproval which is set to true. This will not allow promotion into prod target until the approval is granted. You require roles/clouddeploy.approver role to approve a release.

  1. Create the Deploy Targets
         `gcloud config set deploy/region us-central1` 
    

gcloud beta deploy apply --file deploy/preview.yaml

gcloud beta deploy apply --file deploy/canary.yaml

gcloud beta deploy apply --file deploy/prod.yaml

3. App Creation

As part of the creation of a new application the CICD pipeline is typically setup to perform automatic builds, integration testing and deployments. The following steps are considered part of the setup process for a new app. Each new application will have a deployment pipeline configured.

Defining Cloud Deploy pipeline

  1. Create a file in the deploy directory named pipeline.yaml with the following command in cloudshell:

cat <<EOF >>deploy/pipeline.yaml

apiVersion: deploy.cloud.google.com/v1beta1

kind: DeliveryPipeline

metadata:

name: sample-app

labels:

`app: sample-app`

description: delivery pipeline

serialPipeline:

stages:

- targetId: preview

`profiles:`

`- preview`

- targetId: canary

`profiles:`

`- canary`

- targetId: prod

`profiles:`

`- prod`

EOF

    As you noticed, the "kind" tag is "DeliveryPipeline". It lets you define the metadata for the pipeline, a description and an order of deployment into various targets via serialPipeline tag.

serialPipeline tag contains a tag named stages which is a list of all targets to which this delivery pipeline is configured to deploy.

targetId identifies the specific target to use for this stage of the delivery pipeline. The value is the metadata.name property from the target definition.

profiles is a list of zero or more Skaffold profile names, from skaffold.yaml. Cloud Deploy uses the profile with skaffold render when creating the release.

  1. Apply Pipeline

gcloud beta deploy apply --file deploy/pipeline.yaml

4. Development Phase

As the applications are developed automated CICD toolchains will build and store assets. The following commands are executed to build the application using skaffold and store assets for deployment with Cloud Deploy. This step would be performed by your CICD process for every application build.

  1. Build and store the application with skaffold

skaffold build \

--file-output=artifacts.json \

--default-repo gcr.io/$PROJECT_ID \

--push=true

5. Release Phase

At the end of your CICD process, typically when the code is Tagged for production, you will initiate the release process by calling the cloud deploy release command. Later once the deployment has been validated and approved you'll move the release through the various target environments by promoting and approving the action through automated processes or manual approvals.

Creating a release

We created Cloud Deploy files in this tutorial earlier to get an understanding of how Cloud Deploy works. For the purpose of demo, we have created the same Cloud Deploy files and pushed them to a github repo with a sample go application and we will use Cloud Deploy to do the release of that application.

export REL_TIMESTAMP=$(date '+%Y%m%d-%H%M%S')

gcloud beta deploy releases create \

sample-app-release-${REL_TIMESTAMP} \

--delivery-pipeline=sample-app \

--description="Release demo" \

--build-artifacts=artifacts.json \

--annotations="release-id=rel-${REL_TIMESTAMP}"

Review the release

When a Cloud Deploy release is created, it automatically rolls it out in the first target which is preview.

  1. Go to <Cloud Deploy> in Google cloud console
  2. Click on "sample-app"

On this screen you will see a graphic representation of your pipeline.

  1. Confirm a green outline on the left side of the preview box which means that the release has been deployed to that environment.
  2. Optionally review additional details about the release by clicking on the release name under Release Details in the lower section of the screen
  3. Verify that the release successfully deployed the application, run the following command it cloushell

gcloud container clusters get-credentials preview --zone us-central1-a && kubectl port-forward --namespace default $(kubectl get pod --namespace default --selector="app=cloud-deploy-tutorial" --output jsonpath='{.items[0].metadata.name}') 8080:8080

  1. Click on the web preview icon in the upper right of the screen.
  2. Select Preview on port 8080

This will take you to a new page which shows the message "Hello World!"

  1. Use ctrl+c in the terminal to end the port-forward.

Promoting a release

Now that your release is deployed to the first target (preview) in the pipeline, you can promote it to the next target (canary). Run the following command to begin the process.

gcloud beta deploy releases promote \

--release=sample-app-release-${REL_TIMESTAMP} \

--delivery-pipeline=sample-app \

--quiet

Review the release promotion

  1. Go to the sample-app pipeline in the Google Cloud console
  2. Confirm a green outline on the left side of the Canary box which means that the release has been deployed to that environment.
  3. Verify the application is deployed correctly by creating a tunnel to it

gcloud container clusters get-credentials canary --zone us-central1-b && kubectl port-forward --namespace default $(kubectl get pod --namespace default --selector="app=cloud-deploy-tutorial" --output jsonpath='{.items[0].metadata.name}') 8080:8080

  1. Click on the web preview icon in the upper right of the screen.
  2. Select Preview on port 8080

This will take you to a new page which shows the message "Hello World!"

  1. Use ctrl+c in the terminal to end the port-forward.

Approving a production release

Remember when we created prod target via prod.yaml, we specified the tag requireApproval as true. This will force a requirement of approval for promotion in prod.

  1. Promote the canary release to production with the following command

gcloud beta deploy releases promote \

--release=sample-app-release-${REL_TIMESTAMP} \

--delivery-pipeline=sample-app \

--quiet

  1. Go to the sample-app pipeline in the Google Cloud console
  2. Notice the yellow indicator noting "1 pending".

This message indicates there is a release queued for deployment to production but requires review and approval.

  1. Click on the "Review" button just below the yellow notice.
  2. In the next screen click "Review" again to access the approval screen for production
  3. Optionally review the Manifest Diff to review the changes. In this case a whole new file.
  4. Click on the "Approve" button
  5. Return to the sample-app pipeline page where you will see the release to prod in progress.

Review the production release

As with the other environments you can review the deployment when it completes using the steps below.

  1. Run the following command it cloudshell to create the port-forward

gcloud container clusters get-credentials prod --zone us-central1-c && kubectl port-forward --namespace default $(kubectl get pod --namespace default --selector="app=cloud-deploy-tutorial" --output jsonpath='{.items[0].metadata.name}') 8080:8080

  1. Click on the web preview icon in the upper right of the screen.
  2. Select Preview on port 8080

This will take you to a new page which shows the message "Hello World!"

  1. Use ctrl+c in the terminal to end the port-forward.