Continuous Delivery on Google Cloud with Gitlab CI/CD and Cloud Deploy
Giovanni Galloro
Customer Engineer
Continuous Delivery (CD) is a set of practices and principles that enables teams to deliver software quickly and reliably by automating the entire software release process using a pipeline. In this article, we explain how to create a Continuous Delivery pipeline to automate software delivery from code commit to production release on Cloud Run using Gitlab CI/CD and Cloud Deploy, leveraging the recently released Gitlab Google Cloud integration.
Elements of the solution
Gitlab CI/CD
GitLab CI/CD is an integrated continuous integration and delivery platform within GitLab. It automates the build, test, and deployment of your code changes, streamlining your development workflow. For more information check the Gitlab CI/CD documentation.
Cloud Deploy
Cloud Deploy is a Google managed service that you can use to automate how your application is deployed across different stages to a series of runtime environments. With Cloud Deploy, you can define delivery pipelines to deploy container images to GKE and Cloud Run targets in a predetermined sequence. Cloud Deploy supports advanced deployment strategies as progressive releases, approvals, deployment verifications, parallel deployments.
Google Cloud Gitlab integration
Gitlab and Google Cloud recently released integrations to make it easier and more secure to deploy code from Gitlab to Google Cloud. The areas of integration described in this article are:
-
Authentication: The GitLab and Google Cloud integration leverages workload identity federation, enabling secure authorization and authentication for GitLab workloads, as CI/CD jobs, with Google Cloud. This eliminates the need for managing service accounts or service account keys, streamlining the process and reducing security risks. All the other integration areas described below leverage this authentication mechanism.
-
Artifact Registry: The integration lets you upload GitLab artifacts to Artifact Registry and access them from Gitlab UI.
-
Cloud Deploy: This Gitlab component facilitates the creation of Cloud Deploy releases from Gitlab CI/CD pipelines.
-
Gcloud: This component facilitates running gcloud commands in Gitlab CI/CD pipelines.
-
Gitlab runners on Google Cloud: The integration lets you configure runner settings from Gitlab UI and have them deployed on your Google Cloud project with Terraform.
You can access the updated list of Google Cloud Gitlab components here.
What you’ll need
To follow the steps in this article you need:
-
A Gitlab account (Free, Premium or Ultimate)
-
A Google Cloud project with project owner access
-
A fork, in your account, of the following Gitlab repository containing the example code: https://gitlab.com/galloro/cd-on-gcp-gl cloned locally to your workstation.
Pipeline flow
You can see the pipeline in the .gitlab-ci.yml file in the root of the repo or using the Gitlab Pipeline editor.
Following the instruction in this article you will create and execute an end to end software delivery pipeline where:
-
A developer creates a feature branch from an application repository
-
The developer makes a change to the code and then opens a merge request to merge the updated code to the main branch
-
The Gitlab pipeline will run the following jobs, all configured to run when a merge request is open through the
- if: $CI_PIPELINE_SOURCE == 'merge_request_event
' rule:
a. The image-build
job, in the build
stage, builds a container image with the updated code.
b. The upload-artifact-registry
component, in the push
stage, pushes the image to Artifact Registry leveraging the Google Cloud IAM integration configured previously as all the other following components. The configuration of this job, as the ones for the other components described below, is split between the component and the explicit job definition in order to set the rules for job execution.
c. The create-cloud-deploy-release
component, in the deploy-to-qa
stage, creates a release on Cloud Deploy and a rollout to the QA stage, mapping to the cdongcp-app-qa
Cloud Run service, where the QA team will run user acceptance tests.
4. After the tests are completed, the QA team merges the MR and this runs the run-gcloud
component, in the promote-to-prod
stage, that promotes the release to the production stage, mapping to the cdongcp-app-prod
Cloud Run service. In this case the job is configured to run on a push to the main branch through the
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
rule:
5. The Cloud Deploy prod target requires approval so an approval request is triggered, the Product Manager for the application checks the rollout and approves it so the app is released in production with a canary release; this creates a new revision of the cdongcp-app-prod
Cloud Run service and direct 50% of the traffic to it. You can see the Cloud Deploy delivery pipeline and targets configuration below (file cr-delivery-pipeline.yaml in the repo) including the canary strategy and approval required for prod deployment. Canary strategy is configured to 50% to make traffic split more visible; in a real production environment this would be a lower number.
6. After checking the canary release, the App Release team advances the rollout to 100%.
You can play all the roles described above (developer, member of the QA team, member of the App release team, Product Manager) using a single Gitlab account and project/repository. In a real world scenario multiple accounts would be used.
The picture below describes the pipeline flow:
In addition to the jobs and stages described above, the .gitlab-ci.yml pipeline contains other instances of similar jobs, in the first-release
stage, that are configured, through rules, to run only if the pipeline is executed manually using the “Run pipeline” button in Gitlab web UI. You will do that to manually create the first release before running the above described flow.
Prepare your environment
To prepare your environment to run the pipeline, complete the following tasks:
-
Create an Artifact Registry standard repository for Docker images in your Google Cloud project and desired region.
-
Run
setup.sh
from the setup folder in your local repo clone and follow the prompt to insert your Google Cloud project, Cloud Run and Cloud Deploy region and Artifact Registry repository. Then commit changes to the.gitlab-ci.yml
andsetup/cr-delivery-pipeline.yaml
files and push them to your fork.
3. Still in the setup folder, create a Cloud Deploy delivery pipeline using the manifest provided (replace yourregion
and yourproject
with your values):
This creates a pipeline that has two stages: qa and prod, each using a profile with the same name and two targets mapping two Cloud Run services to the pipeline stages.
4. Follow the Gitlab documentation to set up Google Cloud workload identity federation and the workload identity pool that will be used to authenticate Gitlab to Google Cloud services.
5. Follow the Gitlab documentation to set up Google Artifact Registry integration. After that you will be able to access the Google AR Repository from Gitlab UI through the Google Artifact Registry entry in the sidebar under Deploy.
6. (Optional) Follow the Gitlab documentation to set up runners in Google Cloud. If you’re using Gitlab.com, you can also keep the default configuration that uses Gitlab hosted runners, but with Google Cloud runners you can customize parameters as the machine type and autoscaling.
7. Set up permissions for Gitlab Google Cloud components as described in the related README for each component. To run the jobs in this pipeline, the Gitlab workload identity pool must have the following minimum roles in Google Cloud IAM:
-
-
roles/artifactregistry.reader
-
roles/artifactregistry.writer
-
roles/clouddeploy.approver
-
roles/clouddeploy.releaser
-
roles/iam.serviceAccountUser
-
roles/run.admin
-
roles/storage.admin
-
8. Manually run the pipeline from Gitlab web UI with Build -> Pipelines -> Run pipeline to create the first release and the two Cloud Run services for QA and production. This runs all the jobs that are part of the first-release
stage, and waits for the pipeline execution to complete before moving to the next steps.
9. From the Google Cloud console, get the URL of the cdongcp-app-qa and cdongcp-app-prod Cloud Run services and open them with a web browser to check that the application has been deployed.
Run your pipeline
Update your code as a developer
-
Be sure to move at the root of the repository clone and create a new branch of the repository with the name “new feature” and check it out:
2. Update your code: open the app.go file in the cdongcp-app folder and change the message in row 25 to “cd-on-gcp app UPDATED in target: …”
3. Commit and push your changes to the “new-feature” branch.
4. Now open a merge request to merge your code: you can copy and paste to your browser the url in the terminal output and in the Gitlab page click the “Create merge request” button, you will see a pipeline starting.
Run automatic build of your artifact
1. In Gitlab look at Build > Pipelines, click on the last pipeline execution id; you should see three stages each one including one job:
2. Wait for the pipeline to complete; you can click on each job to see the execution log. The last job should create the cdongcp-$COMMIT_SHA release (where $COMMIT_SHA is the short SHA of your commit) and roll it out to the QA stage.
3. Open or refresh the cdongcp-app-qa URL with your browser; you should see the updated application deployed in the QA stage.
4. In a real world scenario the QA team performs some usability tests in this environment. Let’s assume that these have been completed successfully and you, as a member of the QA team this time, want to merge the changed code to the main branch: go to the merge request Gitlab page and click “Merge”.
Approve and rollout your release to production
1. A new pipeline will run containing only one job from the run-gcloud
component. You can see the execution in the Gitlab pipeline list.
2. When the pipeline is completed your release will be promoted to prod stage waiting for approval, as you can see in the Cloud Deploy page in the console.
3. Now, acting as the product manager for the application that has to approve the deployment in production, click on Review; you will see a rollout that needs approval. Click on REVIEW again.
4. In the “Approve rollout to prod” page, click on the “APPROVE” button to finally approve the promotion to the prod stage. The rollout to the canary phase of the prod stage will start, and after some time the rollout will stabilize in the canary phase.
5. Let’s try to observe how traffic is managed in this phase: generate some requests to the cdongcp-app-prod URL service with the following command (replace cdongcp-app-prod-url
with your service URL):
6. After some time you should see responses both from your previous release and the new (canary) one.
7. Now let’s pretend that the App Release team gets metrics and other observability data from the canary. When they are sure that the application is performing correctly, they want to deploy the application to all their users. As a member of the App Release team, go to the Cloud Deploy console and click “Advance to stable” and then “ADVANCE” on the confirmation pop up; the rollout should progress to stable. When the progress stabilizes you will see in the curl output that all the requests are served by the updated version of the application.
Summary
You saw an example Gitlab CI/CD pipeline that leverages the recently released Google Cloud - Gitlab integration to:
-
Configure Gitlab authentication to Google Cloud using workload identity federation
-
Integrate Gitlab with Artifact Registry
-
Use Gitlab CI/CD and Cloud Deploy to automatically build your software and deploy it to a QA Cloud Run service when a merge request is created
-
Automatically promote your software to a prod Cloud Run service when the merge request is merged to the main branch
-
Use approvals in Cloud Deploy
-
Leverage canary release in Cloud Deploy to progressively release your application to users
Now you can reference this article and the documentation on Gitlab CI/CD, Google Cloud - Gitlab integration, Cloud Deploy and Cloud Run to configure your end to end pipeline leveraging Gitlab and Google Cloud!