Terraform is a great tool for automating infrastructure configuration. As your configuration and environment grow larger, and additional team members come in to help manage infrastructure, a better model needs to be in place to help run your Terraform code in a collaborative manner.

Many solutions exist in both the open source (Atlantis, tf-controller) and commercial (Terraform Cloud, Env0, Spacelift) space. A solution that came to my attention recently is Digger.

Throughout this tutorial, we'll explore Digger, an open-source tool designed to run Terraform processes within your CI pipeline, leveraging your existing CI infrastructure.

What is Digger?

Digger is an open-source tool that allows you to run all Terraform processes using the same CI infrastructure you already use. It reuses your CI infrastructure with jobs, logs, compute, orchestration, etc., so you can benefit from your existing software deployment methodology.

Prerequisites

Before getting started with this tutorial, you will need to have a Civo account. Then, to launch a Civo Kubernetes cluster using Digger.dev, you can follow these steps:

  • In your Civo account, obtain an API token by going to Settings -> Profile and clicking the Security tab.
  • Create a new GitHub Repository.
  • In the new GitHub repository, go to Settings -> Secrets and Variables -> Actions. Create a CIVO_TOKEN secret with the API key above.
  • In the New Repository, ensure you enable GitHub Actions, as well as grant the pipeline read and write permissions.

Automating Infrastructure as Code Prerequisites

Configuring the Civo Provider in Terraform

In the repository, create the following files (links provided with example code):

Step 1: Specify required provider as maintained by Civo

terraform {
  required_providers {
    civo = {
      source = "civo/civo"
    }
  }
}

Step 2: Configure the Civo Provider

Tip: This configuration sets up the Civo provider, allowing Terraform to interact with your Civo account. Ensure that the CIVO_TOKEN secret is set in your GitHub Actions pipeline to authenticate Terraform with Civo.
provider "civo" {
  region = "LON1"
}

Step 3: Query xsmall instance size

data "civo_size" "xsmall" {
  filter {
    key    = "type"
    values = ["kubernetes"]
  }

  sort {
    key       = "ram"
    direction = "asc"
  }
}

data "civo_size" "small" {
  filter {
    key    = "type"
    values = ["kubernetes"]
  }

    filter {
        key = "name"
        values = ["g4s.kube.small"]
        match_by = "re"
    }
}

Step 4: Create a firewall

resource "civo_firewall" "core-firewall" {
  name                 = "core"
  create_default_rules = false
  ingress_rule {
    label      = "k8s"
    protocol   = "tcp"
    port_range = "6443"
    cidr       = ["0.0.0.0/0"]
    action     = "allow"
  }
  ingress_rule {
    label      = "k8s"
    protocol   = "tcp"
    port_range = "80"
    cidr       = ["0.0.0.0/0"]
    action     = "allow"
  }
  ingress_rule {
    label      = "k8s"
    protocol   = "tcp"
    port_range = "443"
    cidr       = ["0.0.0.0/0"]
    action     = "allow"
  }
}

Step 5: Create a cluster without specific cluster type by default is K3s

resource "civo_kubernetes_cluster" "core-cluster" {
  name         = "core"
  firewall_id  = civo_firewall.core-firewall.id
  applications = "cert-manager,traefik2-nodeport"
  pools {
    size       = element(data.civo_size.small.sizes, 0).name
    node_count = 3
  }
}

Setting Up the GitHub Actions Pipeline

The next step is to Sketch out the GitHub Actions pipeline and core Digger configurations. The main branch configuration needed for this is:

name: CI

on:
  pull_request:
    branches: [ "main" ]
    types: [ closed, opened, synchronize, reopened ]
  issue_comment:
    types: [created]
    if: contains(github.event.comment.body, 'digger')
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    # Based on https://github.com/diggerhq/digger/issues/395#issuecomment-1601257947
    permissions: write-all
    steps:
      - name: digger run
        uses: diggerhq/digger@v0.2.0
        with:
          # All current locking mechanisms require large-cloud resources
          disable-locking: true
          # AWS Setup Below
          # setup-aws: true
          # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          # aws-region: us-east-1
        env:
          GITHUB_CONTEXT: ${{ toJson(github) }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CIVO_TOKEN: ${{ secrets.CIVO_TOKEN }}

How to Configure Digger

auto_merge: false
projects:
    - name: "core-cluster"
      dir: core-cluster

Testing the Pipeline

Once everything has been committed to the main branch, you'll need to make a PR to actually test the pipeline. Create a new branch, initial-commit. Make a minor change to any of the Terraform in the core-cluster directory. Push up that branch, then create a new PR.

In that PR, write a new comment to trigger a terraform plan to see the actions the Terraform code will perform.

Testing the Pipeline

Review the output of the terraform plan output. This will let you and any peer reviewers see what infrastructure changes will occur.

Testing the Pipeline Output

Ensure all resources being created or modified are expected, then write a comment of digger apply.

Testing the Pipeline Digger Apply

On the PR, you will see the results of the Terraform apply.

Testing the Pipeline PR

Once the apply is complete, merge your PR into the main branch.

Once the pipeline has been completed successfully, you can log in to your Civo account and verify that the Kubernetes cluster has been created.

Automating Infrastructure as Code: Deploying Kubernetes with Digger and GitHub Actions

Now we have completed our first cluster, provisioned completely from Digger!

While this configuration will get you far, in Part 2, we will explore hardening our pipeline with better state and lock management, all within the Civo architecture!

Summary

Now that we have finished this tutorial, you should be able to use Digger to automate Terraform processes within a Civo Kubernetes cluster using GitHub Actions. You can read part 2, “Hardening our Infrastructure as Code Pipeline with Digger,” here.

If you are interested in learning more about the topics discussed in this tutorial, check out some of these resources: