top of page

Deploying AWS infrastructure using Terraform and GitHub Actions




USE CASE

We need to create an EC2 instance in AWS using Terraform and automate it using GitHub Actions, so that every time code is pushed to the 'main' branch in GitHub a new workflow is automatically activated to create/update the infrastructure.

Additionally, we will see how we can collaborate between a team when multiple team members are working on the same code of terraform.


PREREQUISITES

  • An S3 bucket was created beforehand with the following details.

    s3 bucket name: aws-terraform-github-s3-state

  • A DynamoDB table was created beforehand with the following details.

    dynamodb table name: aws-terraform-github-ddb-lock-table

    partition key: LockID


HOW COLLABORATION CAN BE ACHIEVED BETWEEN TEAM MEMBERS

Storing Terraform state in AWS S3 bucket centralizes and secures state management, enables collaboration across teams, and ensures consistency and durability.

How Locking Works in Terraform

  • When Terraform runs, it will attempt to acquire a lock by writing a record into the DynamoDB table using the LockID as the key.

  • If another process currently holds the lock (e.g., another Terraform apply or plan is running), Terraform will wait until the lock is released.

  • The lock entry in DynamoDB will be automatically removed once the Terraform operation is complete.

This locking mechanism ensures no conflicts when multiple team members or CI/CD pipelines work with the same Terraform state.


Using S3 with DynamoDB for locking prevents concurrent modifications and provides high availability.


STEPS OVERVIEW

  • Create an IAM Role in AWS using OpenID Connect (OIDC)

  • Create Terraform modules for reusable code.

  • Store the Terraform state in an S3 bucket.

  • Write the GitHub Actions workflow to automate infrastructure provisioning.


CREATE AN IAM ROLE IN AWS USING OpenID Connect (OIDC)

Create a new Identity Provider in AWS IAM with the following details:

Provider Type: OpenID Connect

Provider URL: https://token.actions.githubusercontent.com


Now let's create a new IAM Role using this identity provider created:

Trusted entity type: Web Identity

Identity provider: token.actions.githubusercontent.com (created above)

Audience: sts.amazonaws.com

GitHub organization: <your GitHub account>

GitHub repository: <your GitHub repo>

Assign required permissions and done.



TERRAFORM CODE SETUP

Directory Structure: Let's use modules to make the code reusable and more manageable. The directory structure looks like this in this case.


Inside the folder /modules/ec2, there are terraform files for the creation of EC2 instances in AWS.


The main terraform configuration file is main.tf in the root folder in which we import ec2 module to provision the instance. In the same file, a backend configuration is present that helps to save the terraform state file remotely in a s3 bucket.

terraform {
  backend "s3" {
	bucket         = "aws-terraform-github-s3-state"
	key            = "terraform/state/terraform.tfstate"
	region         = "us-east-1"
	encrypt        = true
	dynamodb_table = "aws-terraform-github-ddb-lock-table"
  }
} 

Files terraform.yml and terraform-destroy.yml inside the folder /.github/workflows/ are the files to create GitHub workflows using GitHub actions.

Inside terraform workflow files we need to notice several things:

  • workflow is only activated when some code is pushed to the 'main' branch of GitHub repo.

on:
  push:
	branches:
	  - main
  • Permission that we grant to workflow

    ID Token Write Permission: Required for GitHub Actions to generate and provide the OIDC token needed for assuming the IAM role.

    Contents Read Permission: Required for accessing repository contents and executing Terraform commands.

permissions:
  id-token: write
  contents: read

Configuring AWS credentials using AWS OpenID Connect. Here we have used an IAM role that we created initially in AWS. Using ARN of this role GitHub integrates with AWS. (Now there are many other ways of authentication like using AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, but OIDC method is the most secure)

- name: Configure AWS credentials using OIDC
  uses: aws-actions/configure-aws-credentials@v2
  with:
	role-to-assume: arn:aws:iam::<AWS_ACCOUNT_NUMBER>:role/aws-terraform-github-oidc-role
	aws-region: us-east-1

EXECUTE THE SETUP

Now when all the configuration is done, let's test the setup.

Let us push the code in the 'main' branch of the GitHub repository 'aws-terraform-github'.

As soon as the code is pushed, a new workflow is activated in the GitHub Actions of this repository.



When the workflow finishes its execution, let's now go to AWS and check if EC2 is created.


On checking the s3 bucket that we created for storing the state file, we can find that a new state file exists there.


Sameway, checking the DynamoDb table we can find an entry of hash (lockID).


DELETING THE INFRA CREATED ABOVE

As we have created two workflows inside /.github/workflows, terraform.yml, and terraform-destroy.yml.

We have provisioned the infrastructure using the terraform.yml workflow. Now to delete the provisiond infrastructure, we can use terraform-destroy.yml. heading to GitHub Actions we can find this Terraform Destroy workflow in the left pane. Let's execute that workflow.



EC2 instance created, now is deleted.



Comments


ABOUT ME:

Rahul Gupta
Cloud | DevOps | SRE
rahul42.g@gmail.com

mypic2.jpg

Social Networks:

  • LinkedIn

©2023 by DevOpsAddict. Proudly created with Wix.com

bottom of page