IaC deployment using Terraform and GitHub actions

Prerequisite

Before we deploy any resources using terraform and GitHub Actions we need to complete few items.

  1. A place to Store Terraform state file
  2. Create Azure Service Principal from Azure
  3. Sample Terraform code
  4. Complete the workflow (the yaml code which does the actions)

Store Terraform state file

When deploying  using Terraform it will create a state file locally where the terraform is run. The state file is used by Terraform to map Azure Resources to your configuration that you want to deploy, keeps track of meta data and assist further when scaling.

So, it is recommended to store the state file in a repository and use it whenever you work with the Infrastructure thus improving security. Here we will not target security but storing terraform state file remotely. In this deployment, we will the state file remotely in an Azure storage account.

Lets deploy the required storage container called tfstatedevops in Storage Account gitactsaj922 inside Resource Group gitactrg

Commands

New-AzureRmResourceGroup -Name "gitactrg" -Location "eastus2"
New-AzureRmStorageAccount -ResourceGroupName "gitactrg" -AccountName "gitactsaj922" -Location eastus2 -SkuName Standard_LRS
New-AzureRmStorageContainer -ResourceGroupName "gitactrg" -AccountName "gitactsaj922" -ContainerName "tfstatedevops"

Now we have created the repo to save our state file.

Create Azure Service Principal

A Service Principal (SPN) is considered a best practice for DevOps within your CI/CD pipeline. It is used as an identity to authenticate you within your Azure Subscription to allow you to deploy the relevant Terraform code.

We will create a SPN from Azure. This is a simple task. You can follow any article available in the internet to create one.

Give SPN, the contributor access to subscription.

Go to subscription – > IAM -> Role assignments- Select contributor -> select SPN

Setup Deployment Actions in GitHub

Lets go to GitHub

To get started, we will created a new repo, named ‘gitacttfdeployment’

Once repository is created, go to ‘Actions’

Be default, we have many deployment templates available, one for Terraform as well.

However lets create workflow for ourselves by clicking ‘set up a workflow yourself’. Its a temporary code to commit changes.

This action will result in creating a yaml file under ‘repository/.github/workflows/main.yml’

We need to complete the below items

Adding secrets to Github

Completing the Terraform code for deployment

Complete the workflow for deployment

Adding secrets to GitHub

In order for GitHub to communicate with azure, we will add the below secrets under:

Github -> Repository -> Settings -> Actions

By default, there wont be any repository secrets, we will add them by clicking ‘New repository secret’. The secrets to be added are:

AZURE_AD_CLIENT_ID

AZURE_AD_CLIENT_SECRET

AZURE_AD_TENANT_ID

AZURE_SUBSCRIPTION_ID

Lets create a simple terraform code to deploy in Azure

Upload this code in the repository

provider "azurerm" {
    version = "~>2.0"
    features {}
}

terraform {
  backend "azurerm" {
  resource_group_name  = "gitactrg"
  storage_account_name = "gitactsaj922"
  container_name       = "tfstatedevops"
  key                  = "dev.terraform.tfstate"
}

}

resource "azurerm_resource_group" "temprg" {
  name     = "tempgitactrg"
  location = "eastus2"
}

resource "azurerm_storage_account" "tempsa" {
  name                     = "gitactsatemj922"
  resource_group_name      = azurerm_resource_group.temprg.name
  location                 = azurerm_resource_group.temprg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

Its time to update the workflow file with Trigger and Job to do. The code is

name: 'Terraform'

on:
  push:
    branches:
    - main
  pull_request:

jobs:
  terraform:
    name: 'Terraform'
    env:
      ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }}
      ARM_CLIENT_SECRET: ${{ secrets.AZURE_AD_CLIENT_SECRET }}
      ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }}
    runs-on: ubuntu-latest
    environment: dev

    defaults:
      run:
        shell: bash

    steps:
    - name: Checkout
      uses: actions/checkout@v2

       
    - name: 'Terraform Init'
      uses: hashicorp/terraform-github-actions@master
      with:
        tf_actions_version: 0.14.8
        tf_actions_subcommand: 'init'
        tf_actions_working_dir: "./terraform"

    - name: 'Terraform Validate'
      uses: hashicorp/terraform-github-actions@master
      with:
        tf_actions_version: 0.14.8
        tf_actions_subcommand: 'validate'
        tf_actions_working_dir: "./terraform"
        
    - name: 'Terraform Plan'
      uses: hashicorp/terraform-github-actions@master
      with:
        tf_actions_version: 0.14.8
        tf_actions_subcommand: 'plan'
        tf_actions_working_dir: "./terraform"

    - name: Terraform Apply
      if: github.ref == 'refs/heads/main'
      uses: hashicorp/terraform-github-actions@master
      with:
        tf_actions_version: 0.14.8
        tf_actions_subcommand: 'apply'
        tf_actions_working_dir: "./terraform"

The code is explained below:

Section 1 (name):

The name of workflow is ‘Terraform’

Section 2 (on):

This actions defines GitHub Actions will be invoked when any commit happened in the main branch.

Section 3 (Jobs)

All the Actions are part of Terraform.

We setup environmental variables for authentication.

We request GitHub Actions to provide Ubuntu for the runtime environment.

All actions are happening in dev environment.

We are going to use shell to execute all the next Steps that follows.

The steps include checkout and Terraform actions.

Checkout uses checkout community and terraform uses/refers to terraform repository to complete the item ‘with’ provided information on the yaml file.

Once the code is committed, the actions will start deploying the azure resources as per tf code in the repository. Our code installs Resource Groups and Storage Account in Azure.

Please ignore the red ones, as those are cosmetic. We can see the final proper commit with the codes completed successfully.

Leave a Comment

Your email address will not be published. Required fields are marked *

fourteen − 14 =