How teams use GitLab and Terraform for infrastructure as code: A demo
This demo demonstrates how to follow good GitOps procedure to deploy infrastructure as code using Terraform for automation and GitLab as the single source of truth.
When multiple teams use a Git repository as the single source of truth for all infrastructure and application deployment code, they’re performing a good GitOps procedure. Infrastructure teams can collaborate and deploy code to multiple cloud services using Terraform for automation. This article demonstrates how teams can create a Kubernetes cluster by collaborating with teammates within GitLab.
Getting started
This gitops-demo group illustrates the steps infra teams can follow.
Begin by logging into the group where the project lives within GitLab. The next step is to open the README.md file, which shows the underlying structure of the gitops-demo group. There are a few individual projects and two subgroups: infrastructure and applications.
There is a separate repository for each cloud: Azure, GCP, and AWS, and a repository for templates.
Similar files can be found in all three cloud repositories. All of the files are written in Terraform to automate the deployment process, while a gitlab-ci.yml
file is also stored in the repository to provide instructions for automation.
The backend file
Using HashiCorp's Terraform Cloud Service as a remote location for the state file keeps the state file safe and in a central location so it can be accessed by any process. One advantage of using Terraform Cloud is it has the ability to lock the state to ensure only one job can run at a time, preventing multiple jobs from making conflicting changes. The code stores the state files in the Terraform Cloud in an organization called gitops-demo
in a workspace called aws
. This keeps the running state in the cloud provider, so any team member has access at any time.
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "gitops-demo"
workspaces {
name = "aws"
}
}
}
EKS.tf file
The EKS is another Terraform file that leverages the EKS module for the Terraform cluster. Teams can define parameters such as the type of subnets and the number of nodes in the EKS terraform file.
module "eks" {
source = "terraform-aws-modules/eks/aws"
cluster_name = "gitops-demo-eks"
subnets = "${module.vpc.public_subnets}"
write_kubeconfig = "false"
tags = {
Terraform = "true"
Environment = "dev"
}
vpc_id = "${module.vpc.vpc_id}"
worker_groups = [
{
instance_type = "m4.large"
asg_max_size = 5
tags = [{
key = "Terraform"
value = "true"
propagate_at_launch = true
}]
}
]
}
Define the GitLab admin
The Kubernetes provider can be used to create a GitLab admin user and set up automatically as code and managed by Terraform.
Register the cluster with GitLab
Now that a Kubernetes cluster has been created, it's time to register it with GitLab in order to deploy more code to the cluster in the future. The first step is to use the GitLab provider to create a group cluster named AWS cluster.
data "gitlab_group" "gitops-demo-apps" {
full_path = "gitops-demo/apps"
}
provider "gitlab" {
alias = "use-pre-release-plugin"
version = "v2.99.0"
}
resource "gitlab_group_cluster" "aws_cluster" {
provider = "gitlab.use-pre-release-plugin"
group = "${data.gitlab_group.gitops-demo-apps.id}"
name = "${module.eks.cluster_id}"
domain = "eks.gitops-demo.com"
environment_scope = "eks/*"
kubernetes_api_url = "${module.eks.cluster_endpoint}"
kubernetes_token = "${data.kubernetes_secret.gitlab-admin-token.data.token}"
kubernetes_ca_cert = "${trimspace(base64decode(module.eks.cluster_certificate_authority_data))}"
}
The code contains the domain name, environment scope, and Kubernetes credentials.
After this runs, the cluster will be created in AWS and automatically registered to the gitops-demo/apps group.
Terraform template
Return to the infrastructure group and open the Templates folder. When looking at the terraform.gitlab-ci.yml file, it's possible to see how the CI works to deploy infrastructure code to the cloud using Terraform.
Inside the CI file, teams can see a few different stages: validate, plan, apply, and destroy. Using Hashicorp's Terraform base image, users can run different tasks.
The first step is to initialize Terraform.
before_script:
- terraform --version
- terraform init
- apk add --update curl
- curl -o kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.13.7/2019-06-11/bin/linux/amd64/kubectl
- install kubectl /usr/local/bin/ && rm kubectl
- curl -o aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/1.13.7/2019-06-11/bin/linux/amd64/aws-iam-authenticator
- install aws-iam-authenticator /usr/local/bin/ && rm aws-iam-authenticator
The next step is to validate that everything is correct.
validate:
stage: validate
script:
- terraform validate
- terraform fmt -check=true
only:
- branches
It's important to remember that good GitOps workflows incorporate creating a merge request for the changes.
merge review:
stage: plan
script:
- terraform plan -out=$PLAN
- echo \`\`\`diff > plan.txt
- terraform show -no-color ${PLAN} | tee -a plan.txt
- echo \`\`\` >> plan.txt
- sed -i -e 's/ +/+/g' plan.txt
- sed -i -e 's/ ~/~/g' plan.txt
- sed -i -e 's/ -/-/g' plan.txt
- MESSAGE=$(cat plan.txt)
- >-
curl -X POST -g -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}"
--data-urlencode "body=${MESSAGE}"
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/discussions"
artifacts:
name: plan
paths:
- $PLAN
only:
- merge_requests
The merge request
The merge request (MR) is the most important step in GitOps. This is the process to review all changes and see the impact of those changes. The MR is also a collaboration tool where team members can discuss changes and stakeholders can approve changes before the final merge into the main branch.
The merge request defines what will happen when running the infrastructure as code. After the MR is created, the Terraform plan is uploaded to the MR. After all changes have been reviewed and approved, the code can be merged to the main branch. Once the code changes are merged, all the changes will be deployed into production.
Have a question? We're here to help.
Talk to an Expert