Atlantis: Terraform Pull Request Automation
What is Terraform ?
Terraform is an open source “Infrastructure as Code” tool, created by HashiCorp.A declarative coding tool, Terraform enables DevOps engineers to use a high-level configuration language called HCL (HashiCorp Configuration Language) to describe the desired “end-state” of infrastructure for running an application.
Terraform Plan-
Terraform generates an execution plan describing what it will do to reach the desired state, and then executes it to build the described infrastructure. As the configuration changes, Terraform is able to determine what changed and create incremental execution plan which can be applied.
Terraform Apply-
The terraform apply command is used to apply the changes required to reach the desired state of the configuration, or the pre-determined set of actions generated by a terraform plan execution plan.
Let’s see how you can enable anyone in your team run Terraform automations safely !
Here comes Atlantis !
Atlantis is an application for automating Terraform via pull requests. It is deployed as a standalone application into your infrastructure. No third-party has access to your credentials.
Atlantis listens for GitHub, GitLab or Bitbucket webhooks about Terraform pull requests. It then runs terraform plan
and comments with the output back on the pull request.
When you want to apply, comment atlantis apply
on the pull request and Atlantis will run terraform apply
and comment back with the output.
Why would you run Atlantis?
- Increased visibility-
When everyone is executing Terraform on their own computers, it’s hard to know the current state of your infrastructure:
- Is what’s in
master
deployed? - Did someone forget to create a pull request for that latest change?
- What was the output from that last
terraform apply
?
With Atlantis, everything is visible on the pull request. You can view the history of everything that was done to your infrastructure.
2. Enable collaboration with everyone-
You probably don’t want to distribute Terraform credentials to everyone in your engineering organization, but now anyone can open up a Terraform pull request.
You can require approval before the pull request is applied so nothing happens accidentally.
3. Review Terraform pull requests better -
You can’t fully review a Terraform change without seeing the output of terraform plan
. Now that output is added to the pull request automatically.
4. Standardize your workflows-
Atlantis locks a directory/workspace until the pull request is merged or the lock is manually deleted. This ensures that changes are applied in the order expected.
How it worked?
- Open a pull request.
- Atlantis automatically runs Terraform plan and comments back on the pull request.
- Someone from your team will review the plan and approve the pull request.
- You comment “atlantis apply”.
- Atlantis automatically runs Terraform applyand comments back on the pull request.
6. Merge the Pull request.
How to install Atlantis on K8s cluster?
- We recommend creating a new user named @atlantis (or something close) or using a dedicated CI user.
- Once you’ve created a new user (or decided to use an existing one), you need to generate an access token for a Github. Create the token with repo scope
- Atlantis uses Webhook secrets to validate that the webhooks it receives from your Git host are legitimate.Webhook secrets are actually optional. However they’re highly recommended for security.You can use any random string generator to create your Webhook secret. It should be > 24 characters.You must use the same webhook secret for each repo.
- first create a Secret with the webhook secret and access token:
echo -n "yourtoken" > token
echo -n "yoursecret" > webhook-secret
kubectl create secret generic atlantis-vcs --from-file=token --from-file=webhook-secret
5.Modify K8s manifest file-
If you’d like to use a raw Kubernetes manifest, StatefulSet is recommended because Atlantis stores its data on disk and so if your Pod dies or you upgrade Atlantis, you won’t lose plans that haven’t been applied. If you do lose that data, you just need to run atlantis plan
again so it's not the end of the world.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: atlantis
spec:
serviceName: atlantis
replicas: 1
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
selector:
matchLabels:
app: atlantis
template:
metadata:
labels:
app: atlantis
spec:
securityContext:
fsGroup: 1000 # Atlantis group (1000) read/write access to volumes.
containers:
- name: atlantis
image: runatlantis/atlantis:v<VERSION> # 1. Replace <VERSION> with the most recent release.
env:
- name: ATLANTIS_REPO_ALLOWLIST
value: github.com/yourorg/* # 2. Replace this with your own repo allowlist.### GitHub Config ###
- name: ATLANTIS_GH_USER
value: <YOUR_GITHUB_USER> # 3i. If you're using GitHub replace <YOUR_GITHUB_USER> with the username of your Atlantis GitHub user without the `@`.
- name: ATLANTIS_GH_TOKEN
valueFrom:
secretKeyRef:
name: atlantis-vcs
key: token
- name: ATLANTIS_GH_WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: atlantis-vcs
key: webhook-secret
### End GitHub Config ###
- name: ATLANTIS_DATA_DIR
value: /atlantis
- name: ATLANTIS_PORT
value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override.
volumeMounts:
- name: atlantis-data
mountPath: /atlantis
ports:
- name: atlantis
containerPort: 4141
resources:
requests:
memory: 256Mi
cpu: 100m
limits:
memory: 256Mi
cpu: 100m
livenessProbe:
# We only need to check every 60s since Atlantis is not a
# high-throughput service.
periodSeconds: 60
httpGet:
path: /healthz
port: 4141
# If using https, change this to HTTPS
scheme: HTTP
readinessProbe:
periodSeconds: 60
httpGet:
path: /healthz
port: 4141
# If using https, change this to HTTPS
scheme: HTTP
volumeClaimTemplates:
- metadata:
name: atlantis-data
spec:
accessModes: ["ReadWriteOnce"] # Volume should not be shared by multiple nodes.
resources:
requests:
# The biggest thing Atlantis stores is the Git repo when it checks it out.
# It deletes the repo after the pull request is merged.
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: atlantis
spec:
type: ClusterIP
ports:
- name: atlantis
port: 80
targetPort: 4141
selector:
app: atlantis
6. Apply k8s manifest file and check if Antlantis pod is Up and running.
7. Push all your terraform code to the github repo.
8. Create a repo level atlantis.yaml file.
An atlantis.yaml
file specified at the root of a Terraform repo allows you to instruct Atlantis on the structure of your repo and set custom workflows.
Notes:
atlantis.yaml
files must be placed at the root of the repo.- The only supported name is
atlantis.yaml
. Notatlantis.yml
or.atlantis.yaml
.
version: 3
projects:
- dir: <path of directory where you have terraform code>
autoplan:
when_modified: ["../modules/**/*.tf", "*.tf*"]
Once above done you can go ahead and start using the atlantis!