- Published on
Step-by-step Guide to Setting up Atlantis with Gitlab
- Authors
- Name
- Ruan Bekker
- @ruanbekker
Introduction
In our previous post, we explored the powerful features of Atlantis and how it automates Terraform. Now, it's time to get hands-on and set up Atlantis with GitLab. This tutorial will walk you through the entire process, from installation to configuration, ensuring you can leverage Atlantis for your Terraform projects seamlessly.
Prerequisites
Before we begin, make sure you have the following prerequisites:
- A GitLab account with access to a repository.
- A Kubernetes cluster to host Atlantis.
- Basic knowledge of Terraform.
If you want to follow along and need a Kubernetes cluster, you can check out this post that shows you how to run a local Kubernetes cluster using KinD.
Step 1: Gitlab Integration for Atlantis
Before we can deploy Atlantis, we first need to configure two things for our Gitlab integration:
- Gitlab Access Credentials: We need to grant Atlantis access to the Gitlab API.
- Webhook Secrets: Atlantis uses webhooks and the secret is being used for validation.
Gitlab Access Credentials
First, we need to create an access token for Atlantis that will be stored in a Kubernetes secret. For more information on this, you can follow Atlantis Documentation on this topic.
From Gitlab, on the left side, select your profile and select "Preferences":
Then select "Access Tokens":
From the "Personal Access Tokens" page, you can select "Add new token" on the right hand side to create a new access token:
Provide a name for your access token. If you want your token to expire after some time, you can provide the date of expiry and select the api scope, which will provide read and write access to the Gitlab API.
Then, select "Create personal access token". The token value will be provided to you on the top of the screen where you can copy the value, as we will need it in the next step.
Create a file named /tmp/gitlab_token
and store the token value in there. We will create a Kubernetes secret from this file later.
echo -n 'glpat-xx-example' > /tmp/gitlab_token
Atlantis Webhook Secret
Webhooks are used by Atlantis to validate that the webhooks being received are actually from the legitimate source.
Generate a random string and output the value to /tmp/gitlab_secret
where we will use it later to create the Kubernetes secret from:
echo -n $(openssl rand -hex 32) > /tmp/gitlab_secret
Kubernetes Secret
In our Atlantis deployment, we will reference a secret called atlantis-vcs
, which will contain the gitlab-token
and gitlab-webhook-secret
.
We will now create this secret from the two files that we have defined earlier. First we need to create the namespace:
kubectl create namespace atlantis
Now that we have our Atlantis namespace, we can create the secret inside the namespace:
kubectl create secret generic atlantis-vcs \
--namespace atlantis \
--from-file=/tmp/gitlab_token \
--from-file=/tmp/gitlab_secret
Now that we have created our Kubernetes secret, we can continue to deploy Atlantis.
Step 2: Install Atlantis
Atlantis supports other methods to deploy Atlantis, which you can find in their documentation. In this tutorial we will be using Helm to deploy our Atlantis release.
I will be deploying version 5.4.2, but in the future you can follow their releases page to get the most up to date version.
First we want to add the Atlantis helm chart repo to helm:
helm repo add atlantis https://runatlantis.github.io/helm-charts
To get the default helm chart values from the latest version, we can run the following to save the values in our current working directory as values.yaml
:
helm inspect values atlantis/atlantis > values.yaml
IMPORTANT: I will be sharing my values that I am using for this demonstration, these values are fitted for my environment and may require some tweaking to fit your environment. I will try to document each configuration option.
---
# https://github.com/runatlantis/helm-charts/blob/atlantis-5.4.2/charts/atlantis/values.yaml
atlantis:
atlantisUrl: https://atlantis.mydomain.tech # this is your ingress url
orgAllowlist: 'gitlab.com/rbekker87/*' # specifies which repositories you want to allow atlantis to work from
gitlab:
user: rbekker87 # the gitlab user of your account
vcsSecretName: 'atlantis-vcs' # the kubernetes secret that we created earlier
repoConfig: |- # atlantis server side repo configuration
repos: # https://www.runatlantis.io/docs/server-side-repo-config
- id: /.*/
apply_requirements: [approved, mergeable]
import_requirements: [approved, mergeable]
workflow: default
allowed_overrides: [workflow, apply_requirements]
allow_custom_workflows: true
workflows:
default:
plan:
steps: [init, plan]
apply:
steps: [apply]
hidePrevPlanComments: true # neatens up your previous comments be collapsing them
enableDiffMarkdownFormat: true # provides a nice markdown preview
service:
type: ClusterIP
ingress:
enabled: true
ingressClassName: nginx # provide your ingress class
path: /events # ensure to have /events here
pathType: ImplementationSpecific
host: atlantis.mydomain.tech # the ingress host
tls: # the ingress tls configuration
- secretName: sektorlab-tech-tls
hosts:
- atlantis.mydomain.tech
environment: # the atlantis server configuration
ATLANTIS_GITLAB_USER: "rbekker87" # https://www.runatlantis.io/docs/server-configuration.html
ATLANTIS_AUTOMERGE: true
ATLANTIS_AUTOPLAN_MODULES: true
ATLANTIS_ALLOW_COMMANDS: "version,plan,apply,unlock,import,state,approve_policies"
environmentSecrets: # here we are referencing the secrets that we created earlier
- name: ATLANTIS_GITLAB_TOKEN
secretKeyRef:
name: atlantis-vcs
key: gitlab-token
- name: ATLANTIS_GITLAB_WEBHOOK_SECRET
secretKeyRef:
name: atlantis-vcs
key: gitlab-webhook-secret
Now that we have our helm release custom values defined, we can install Atlantis to our Kubernetes cluster using:
helm upgrade --install atlantis atlantis/atlantis \
--create-namespace \
--namespace atlantis \
--version 5.4.2 \
--values values.yaml
After we deployed atlantis, we can check if our pods are running:
kubectl get pods -n atlantis
We can verify if our ingress was created:
kubectl get ingress -n atlantis
We are running a statefulset for Atlantis, so we can monitor the logs from our statefulset:
kubectl logs -f sts/atlantis -n atlantis
If everything looks good we can continue to configure our webhook for our Gitlab project.
Step 3: Configure Gitlab Webhooks
I have created a repository atlantis-demo, and inside the project I need to add a webhook to this project so that Merge Request events can be sent from Gitlab to Atlantis.
From the project, select "Settings" on the left and then select "Webhooks":
Then select "Add new webhook" on the right and provide your events ingress url, it should contain the /events
suffix at the end, for example:
https://atlants.mydomain.tech/events
Then provide the following:
- Name: The name will be used as an identifier in your Gitlab webhooks.
- Secret: This is the secret that we created earlier, which you can access with
cat /tmp/gitlab_secret
. - Trigger: Push events, Comments and Merge request events.
If your ingress uses SSL and is verified then you can select Enable SSL verification
and then select "Add webhook.
Step 4: Configure Your Terraform Repository
In our Terraform Repository (atlantis-demo), add an atlantis.yaml
file in the root of our project, where we define our environment name, our workspace and since I am testing this project on my own I will be overriding my apply requirements that I don't require approvals on my merge request:
version: 3
projects:
- dir: environments/dev
workspace: dev
apply_requirements: [undiverged]
autoplan:
when_modified: ["*.tf", "../../modules/**/*", ".terraform.lock.hcl"]
enabled: true
Lets define some Terraform code that will output a random uuid. In environments/dev/main.tf
define:
resource "random_uuid" "uuid" {}
terraform {
required_providers {
random = {
source = "hashicorp/random"
version = "3.5.1"
}
}
}
provider "random" {}
output "uuid" {
value = random_uuid.uuid.result
sensitive = false
}
Now we can commit this to a branch and create a merge request.
Step 6: Test Your Setup
When we review the workflow of how Atlantis works from our previous post, we can summarize it as follows:
- A Merge Request (MR) gets opened and the event gets sent to Atlantis.
- A Terraform plan execution gets triggered by Atlantis and the output gets sent back to the MR.
- The user comments
atlantis apply
which is sent to the webhook andterraform apply
gets executed on the Atlantis pod. - The output gets sent as a comment and Atlantis merges the MR.
First, I Open a Merge Request in my GitLab repository and watch Atlantis in action, our Merge Request diff looks like the following:
You should see Atlantis automatically comment with the output of terraform plan
in the Merge Request overview:
You can also rerun the plan by commenting atlantis plan
. If you are happy with the changes that Terraform will create, you can comment atlantis apply
:
And once Atlantis applied the Terraform changes, Atlantis will then merge the Merge Request.
Atlantis Commands
In our atlantis.yaml
we have defined some defaults like our dir: environments/dev
and workspace: dev
, so everytime we have a commit in that directory, atlantis will automatically do a plan, and resulting in the following command:
atlantis plan -d environments/dev -w dev
I will provide a couple of examples of atlantis commands that we can run.
- Run a plan in all environments:
atlantis plan
- Run a plan in a different workspace:
atlantis plan -d environments/dev -w test
- Run a plan against a target:
atlantis plan -d environments/dev -w dev -- -target=module.vpc
- Plan a delete
atlantis plan -d environments/dev -w dev -- -destroy
- Remove Terraform state:
atlantis state -d environments/dev -w dev rm 'module.acm[0].this'
- Import Terraform state:
atlantis import -d environments/dev -w dev module.this.resource resource.this.something
- Atlantis help
atlantis --help
Conclusion
Setting up Atlantis with GitLab streamlines your Terraform workflow, making infrastructure changes more efficient and secure. By following this guide, you can automate Terraform operations, enforce best practices, and improve collaboration within your team.
Stay tuned for more tutorials and tips on Terraform and infrastructure management. Happy automating!
Thank You
If you found this guide helpful, share it with your colleagues and friends. Don't forget to subscribe to our newsletter for more insights and tutorials on DevOps and infrastructure management. Follow me at @ruanbekker on Twitter.
- Linktree: https://go.ruan.dev/links
- Patreon: https://go.ruan.dev/patreon