Creating a CI/CD pipeline to deploy Terraform on Azure in GitLab

My previous posts have covered how to setup GitLab runners, which are the are processes that pick up and execute jobs for GitLab.

You’ll need to register one with your project to use CI/CD in GitLab. If you don’t have that setup already, check the links below and then come back here!

GitLab runner setup in a docker container on windows

GitLab runner setup on Azure Kubernetes Service

If you do have a runner already setup, you can progress to the actually setting up the pipeline.

Enable CI/CD for your project

In Gitlab, first enable CI/CD for the project under settings -> general -> pipelines (You have probably already done this if you have setup the runner).

Add environment variables for Azure authentication

In GitLab, settings -> CICD-> variables add the variables needed to authenticate with Azure as shown below. You’ll need to create an app registration in Azure AD if you have not already done so.

Creating the pipeline config

To create a CI/CD pipeline in GitLab, first create a file named .gitlab-ci.yml in the root of your project repository.

My simple pipeline config is shown below:

To summarise this config, a container is pulled from my container registry hosted in GitLab which takes the Alpine Linux image, downloads Terraform and moves the executable to the /usr/bin/local/ path.

I plan to develop this later hence creating a new container and hosting it in the local registry. Its also useful if access to the public registry is blocked on your corporate network.

An easier approach would be to pull the official Terraform image from the public repository (if access is allowed, and you don't want to add anything else to the container) using the following line:

name: hashicorp/terraform:latest

Creating the Dockerfile and uploading the container to the project registry in GitLab

If you do want to create your own container rather than use the public one for whatever reason, follow the steps below to create and upload the necessary container to the registry:

  1. Create a file called ‘Dockerfile’ in the root of the repository.

My Dockerfile looks like this:

2. Browse to the project repository container registry section, it will give you the 3 explict commands needed to login, build and upload your container, example as follows…

3. Login to the container registry

docker login <REGISTRY URL>

4. Build the container, in my case again pointing to the internal container registry:

docker build -t <REGISTRY URL> .

5. Push the container to the registry

docker push <REGISTRY URL>

6. In GitLab confirm the container shows:

7. Update the .gitlab-ci.yml file to include the URL to your container pointing to your internal repository.

Now the container is available, Terraform can be run by the pipeline.

Explaining the pipeline config

before_script:
- rm -rf .terraform
- terraform --version
- terraform init

The first line removes any old .terraform config.

The second line outputs the Terraform version.

Lastly Terraform is initialised.

stages:
- validate
- plan
- apply

The pipeline then has 3 stages of the common Terraform workflow.

validate:
stage: validate
script:
- terraform validate
  • The validate stage validates the terraform syntax and config.
plan:
stage: plan
script:
- terraform plan -out "planfile"
dependencies:
- validate
artifacts:
paths:
- ./planfile
  • The plan stage outputs the plan file ready to be used in the apply stage as an artifact. It is dependent on the validate stage completing.
apply:
stage: apply
script:
- terraform apply -input=false "planfile"
only:
- master
dependencies:
- plan
  • The config is applied using the planfile and is dependent on the plan stage completing. The applies only when jobs are created for the master branch of the project.

Appreciate any feedback and thanks for reading!

An experienced IT professional, focused on Cloud and DevOps. Specialising in Azure & Terraform.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store