In the realm of DevOps, GitOps has emerged as a powerful methodology to manage infrastructure and applications. This article will illustrate the implementation of a GitOps flow for Terraform modules (for infrastructure provisioning) and Helm charts (for Kubernetes applications) using the Cluster.dev platform.
Cluster.dev offers an intuitive interface and tools designed to simplify the setup, configuration, and maintenance of Kubernetes infrastructures. Its capabilities align well with implementing a GitOps workflow for Terraform modules and Helm charts.
Understanding GitOps
In GitOps, all configuration and infrastructure code reside within Git repositories. Any adjustments made to the configuration stored in the repository trigger a reconciliation process that enacts these modifications.
Utilizing Cluster.dev ensures that your complete configuration remains consistently managed and stored within Git.
Let’s look at an example infrastructure repository: https://github.com/shalb/cdev-aws-eks
Unit Versioning in StackTemplate
A stack template is a yaml
file that tells Cluster.dev which units to run and how to do it. It’s an important resource of Cluster.dev, responsible for its flexibility. Stack templates use Go template language which allows users to both select and customize units they want to run.
Here, in the /template.yaml you can find links for each module, whether it’s Terraform or a Helm chart.
units: - name: route53 type: tfmodule source: github.com/shalb/cluster.dev-domain?ref=v0.1.0 # refering git repo of the module with the version - name: vpc type: tfmodule providers: *provider_aws source: terraform-aws-modules/vpc/aws # refering module in terraform registry and its version version: "5.1.1"
To update a module in the template, just modify the tag. It’s advisable to test using a development branch.
Versioning the Resulting Infrastructure — The Stack
The next level of versioning is at the Stack level. This object determines which StackTemplate to use and includes all necessary variables for this stack.
Consider the following from https://github.com/shalb/cdev-aws-eks/blob/main/examples/stack-eks.yaml:
name: cluster template: "https://github.com/shalb/cdev-aws-eks?ref=main" # The version of StackTemplate pinned to a specific stack kind: Stack backend: aws-backend cliVersion: ">= 0.7.14" variables: region: {{ .project.variables.region }}
Git tags and branches in the stack can be used to manage and update versions of StackTemplates.
Upgrading Your Infrastructure
Suppose you need to update a Terraform module in your production setup.
1. Update the module version in the StackTemplate:
- name: route53 type: tfmodule source: github.com/shalb/cluster.dev-domain?ref=v0.2.0 # Update the module's version here
2. As long as this change affects your infrastructure module, create a new tag for the StackTemplate in Git, then update the tag within the Stack:
name: cluster template: "https://github.com/shalb/cdev-aws-eks?ref=1.2.3" # Adjust the StackTemplate's version
And that’s it. Your infrastructure code now has a set pinned layout for infrastructure components, all maintained within Git.
GitOps Reconciliation
The Cluster.dev’s ability to start whole infrastructures makes it ideal for GitOps reconciliation. However, modifications to the infrastructure can have a substantial impact, emphasizing the need to preview planned changes. To address this, we recommend implementing a Pull Request (PR) or Merge Request (MR) process for thorough review and authorization of changes.
Outlined below is the typical process:
- An engineer modifies the Stack version, creating a Pull Request for the main branch.
- This automatically activates the
cluster.dev (cdev plan)
command, enabling the user to inspect proposed infrastructure changes. - Once the PR is approved, the merging process triggers a new pipeline, using the
cluster.dev (cdev apply)
command to effectively apply all changes.
This way Cluster.dev reconciles changes in various components, be they Terraform modules or Helm charts.
GitHub Workflow Example
Let’s assume you are storing your Cluster.dev configurations (stack yamls) inside a Git repository under the .cluster.dev/dev-project/
folder.
For each project (e.g., dev or production infrastructure), create a distinct GitHub workflow file: github/workflows/dev-project.yaml
.
name: Cluster.dev for dev-project on: push: branches: - 'cluster.dev-*' - main paths: - '.cluster.dev/dev-project/**' pull_request: branches: - main paths: - '.cluster.dev/dev-project/**' jobs: plan: if: github.event_name == 'pull_request' runs-on: ubuntu-latest container: clusterdev/cluster.dev:v0.7.18 steps: - name: Check out code uses: actions/checkout@v3 - name: Run ClusterDev Plan run: | cd .cluster.dev/10-project aws s3 mb s3://cdev-state || true # create or reuse state bucket cdev plan env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: eu-central-1 apply: if: github.event_name == 'push' && contains(github.ref, 'refs/heads/main') # Runs only on push to main branch runs-on: ubuntu-latest container: clusterdev/cluster.dev:v0.7.18 steps: - name: Check out code uses: actions/checkout@v3 - name: Run ClusterDev Apply run: | cd .cluster.dev/dev-project cdev apply --force env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: eu-central-1
In this example, we employ a Cluster.dev container from DockerHub. The two jobs are:
plan
: Creates a plan for a PR or a specific branch commit.apply
: Actuates the configuration and reconciles changes, with –force enabling non-interactive mode.
This approach is highly adaptable, suitable for various CI/CD systems like GitLab or Jenkins.
Demo
Use this demo link EKS Cluster creation demo to try out the GitOps pipelines that would be generated into your repository.
Best Practices
Using Cluster.dev makes it easier to align with the GitOps best practices for Terraform modules and Helm charts, including:
- Embracing modular design principles to promote reusability.
- Employing Helm chart versioning strategies for efficient management of application releases.
- Regular review and testing changes with automated CI/CD pipelines before applying them.
Summary
Working through this guide we have seen how Cluster.dev can boost the GitOps flow for Terraform modules and Helm charts. This helps organizations optimize their DevOps workflows, including seamless integration of infrastructure components, their versioning, and reconciliation.