Terraform with GitLab CI
Introduction
Integrating Terraform with GitLab CI provides a powerful way to automate your infrastructure deployments. This combination enables you to apply infrastructure as code (IaC) principles while leveraging GitLab's robust CI/CD capabilities. By the end of this tutorial, you'll understand how to set up a GitLab CI pipeline that automatically plans and applies your Terraform configurations, bringing version control and automation to your infrastructure management.
Terraform allows you to define infrastructure in a declarative way, while GitLab CI provides the automation engine to validate, plan, and apply those changes in a controlled manner. This integration creates a consistent workflow for infrastructure changes that improves collaboration, reduces errors, and increases deployment speed.
Prerequisites
Before getting started, make sure you have:
- A GitLab account
- Basic knowledge of Terraform
- A project with Terraform code
- Access to a cloud provider (AWS, Azure, GCP, etc.)
Setting Up GitLab CI for Terraform
Step 1: Create a .gitlab-ci.yml
File
First, let's create a basic GitLab CI configuration in your repository. Create a file named .gitlab-ci.yml
in the root of your repository:
stages:
- validate
- plan
- apply
image:
name: hashicorp/terraform:latest
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
variables:
TF_ROOT: ${CI_PROJECT_DIR}
# If you're using a custom module, you can specify it here
# TF_ROOT: ${CI_PROJECT_DIR}/environments/production
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .terraform
before_script:
- cd ${TF_ROOT}
- terraform --version
- terraform init
This configuration sets up a pipeline with three stages: validate, plan, and apply. It uses the official Terraform Docker image and initializes Terraform before each job.
Step 2: Add Validation Stage
Now, let's add a job for validating Terraform configurations:
validate:
stage: validate
script:
- terraform validate
only:
- merge_requests
- main
The validation job checks your Terraform code syntax and configuration without accessing any remote services.
Step 3: Add Planning Stage
Next, add a job for creating Terraform plans:
plan:
stage: plan
script:
- terraform plan -out=tfplan
artifacts:
paths:
- tfplan
expire_in: 1 week
only:
- merge_requests
- main
This job creates an execution plan and saves it as an artifact. The plan shows what infrastructure changes Terraform will make based on your configuration.
Step 4: Add Apply Stage
Finally, add a job for applying the Terraform plan:
apply:
stage: apply
script:
- terraform apply -auto-approve tfplan
dependencies:
- plan
only:
- main
when: manual
The apply job executes the plan to create, update, or delete the specified infrastructure. We've added when: manual
to make this a manual step that requires approval before execution.
Complete .gitlab-ci.yml
Example
Here's the complete CI configuration:
stages:
- validate
- plan
- apply
image:
name: hashicorp/terraform:latest
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
variables:
TF_ROOT: ${CI_PROJECT_DIR}
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .terraform
before_script:
- cd ${TF_ROOT}
- terraform --version
- terraform init
validate:
stage: validate
script:
- terraform validate
only:
- merge_requests
- main
plan:
stage: plan
script:
- terraform plan -out=tfplan
artifacts:
paths:
- tfplan
expire_in: 1 week
only:
- merge_requests
- main
apply:
stage: apply
script:
- terraform apply -auto-approve tfplan
dependencies:
- plan
only:
- main
when: manual
Managing Terraform State in GitLab CI
One crucial aspect of using Terraform in CI/CD is state management. Let's explore how to configure remote state storage for GitLab CI pipelines.