Use GitHub Actions and Terraform to provision EC2 instance

Hi, I’m DevOps Engineer at Tikal Knowledge.

In this tutorial, I will create a simple and practical example of how to provision EC2 instance with Github Actions and Terraform. I will use workflow_dispatch type of workflow which is triggered manually by the user, using Terraform Github action from HashiCorp.

This tutorial will be the first in a series of tutorials for Github Actions, in the following tutorials, I will show how to create and use self-hosted GitHub runners with EC2, docker containers running on Kubernetes, and much more.

I will try to be as practical as possible in my tutorials, so there will not be much theory.

Goal

Deploy EC2 instance of t3.small size to your AWS account using Github Actions and Terraform.

I will use ‘workflow_dispatch’ event for this, which is manually triggered.

What is GitHub actions?

GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.

GitHub Actions goes beyond just DevOps and lets you run workflows when other events happen in your repository. For example, you can run a workflow to automatically add the appropriate labels whenever someone creates a new issue in your repository.

GitHub provides Linux, Windows, and macOS virtual machines to run your workflows, or you can host your own self-hosted runners in your own data center or cloud infrastructure.

workflow_dispatch

This event occurs when someone triggers a workflow run on GitHub or sends a POST request to the "Create a workflow dispatch event" endpoint. For more information, see "Events that trigger workflows."

Why use it?

GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.

Let’s do it

Generate AWS Credentials for terraform user

Go to your AWS account -> IAM -> Add a new user

We need only ‘Programmatic access’

To simplify this tutorial, I will use EC2 Full Access permissions.

Download and save the Access key id and Secret access key which will be added as secrets to Github repo.

The next step will be to add credentials to Github as secrets

Go to your Github repository -> settings -> secrets -> actions

My repo is https://github.com/warolv/github-actions-series, with all the code and the github actions workflow.

Add new repository secret

Need to add two secrets: TF_USER_AWS_KEY (Access key id) and TF_USER_AWS_SECRET (Secret access key) which will be used later in workflow I build.

Add TF_USER_AWS_SECRET in the same way.

Overview of the Terraform script to provision EC2 instance

  • The provisioned instance is based on ubuntu AMI.
  • The instance type is t3.micro.
  • The instance will be provisioned to default VPC | subnet | security group.
  • Need to create SSH key pair to connect with the provisioned instance.
  • EC2 will be provisioned to ‘us-east-2’ region.

Generate SSH key pair to connect with EC2 instance

AWS console -> EC2 -> Key Pair -> Create Key Pair

Download .pem file, it will be used later to connect with EC2 instance.

Terraform script to provision EC2 instance (app_server)

https://github.com/warolv/github-actions-series/blob/master/tf-example/main.tf

# main.tf

# use ubuntu 20 AMI for EC2 instance
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/*20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
# provision to us-east-2 region
provider "aws" {
region = "us-east-2"
}
resource "aws_instance" "app_server" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
key_name = "app-ssh-key"
tags = {
Name = var.ec2_name
}
}

# variables.tf

The EC2 name will be set through workflow using the inputs.

variable "ec2_name" {
type = string
}

Create a workflow with Github Actions to provision EC2 instance

  • configure-aws-credentials’ action used to set AWS credentials with docker container to be used by Terraform.
  • You need to define name of EC2 instance using terraform variables: TF_VAR_ec2_name, before TF runs.
  • Used setup-terraform action from HashiCorp.
  • Used GitHub-hosted runner: ubuntu-latest.

https://github.com/warolv/github-actions-series/blob/master/.github/workflows/provision_ec2.yaml

To see your workflow in actions -> workflows, first need to create ‘.github/workflows/provision_ec2.yaml’ and add it to your repository.

# .github/workflows/provision_ec2.yaml

name: Provision t3.micro EC2on:
workflow_dispatch:
inputs:
ec2-name:
description: EC2 name
required: true
default: 'App Server'
type: string
jobs:
provision-ec2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '14'
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: '${{ secrets.TF_USER_AWS_KEY }}'
aws-secret-access-key: '${{ secrets.TF_USER_AWS_SECRET }}'
aws-region: us-east-2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_wrapper: false
- name: Terraform Apply
id: apply
env:
TF_VAR_ec2_name: "${{ github.event.inputs.ec2-name }}"
run: |
cd tf-example/
terraform init
terraform validate
terraform plan
terraform apply -auto-approve

I am using ‘workflow_dispatch’ type of workflow which is triggered manually.

Click ‘Run workflow’

You can see using AWS console that EC2 instance created!

Now try to connect to this instance using ‘app-ssh-key’

I downloaded app-ssh-key.pem file in my mac to ~/Downloads folder

cp ~/Downloads/app-ssh-key.pem ~/.ssh
cd ~/.ssh
chmod 600 app-ssh-key.pem
ssh -i app-ssh-key.pem ubuntu@13.58.251.181

Success!

You can get all tutorials for Github Action from my github repo by cloning it: ‘git clone https://github.com/warolv/github-actions-series.git‘

Conclusion

In this tutorial, I explained how to provision EC2 instances using Terraform and Github Actions workflow, I used GitHub-hosted runner and workflow_dispatch type of workflow which is triggered manually.

Thank you for reading, I hope you enjoyed it, see you in the next post.

If you want to be notified when the next post of this tutorial is published, please follow me here on medium and on Twitter (@warolv).

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author 👇

🚀Developers: Learn and grow by keeping up with what matters, JOIN FAUN.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store