Using Jenkins to create AWS Infrastructure with Terraform.

Using Jenkins to create AWS Infrastructure with Terraform.

The finished product of this project is terraform code that builds an AWS environment with three EC2 instances. The Jenkins CI/CD Pipeline will be triggered when the code is pushed to a GitHub repository via GitHub Webhook.

What is Jenkins?

Jenkins is an open-source automation server that helps facilitate the continuous integration and delivery (CI/CD) of software projects. It allows developers to automate various stages of the software development lifecycle, including building, testing, and deploying applications.

What is Terraform?

Terraform is an open-source infrastructure as code (IaC) tool developed by HashiCorp. It enables you to define and manage your infrastructure resources, such as virtual machines, networks, storage, and services, in a declarative manner. With Terraform, you can provision and manage your infrastructure across various cloud providers and on-premises environments.

Prerequisites

Configure Terraform Cloud

Terraform Cloud is an application that helps teams use Terraform together. It manages Terraform runs in a consistent and reliable environment, and includes easy access to shared state and secret data, access controls for approving changes to infrastructure, a private registry for sharing Terraform modules, detailed policy controls for governing the contents of Terraform configurations, and more.

  1. Sign in to Terraform Cloud

2. Select CLI-driven workflow.

  1. Name your workspace then Create workspace.

  2. Copy the provided example code and add it to backend.tf to replace the current backend.

     terraform {
       cloud {
         organization = "YOUR ORGANIZATION NAME"
    
         workspaces {
           name = "YOUR WORKSPACES NAME"
         }
       }
     }
    

Set the Execution Mode by clicking Remote and selecting Local.

Create Terraform Cloud Token

  1. Run terraform login in CLI and Enter the value yes.

  2. Terraform will open a web browser to the tokens page for app.terraform.io.

  3. Enter a Description and click Generate token.

  4. Copy down the provided token and keep it in a safe place. (You can always generate a new token if you lose the previous one)

  5. Copy and paste the Terraform Cloud token

  6. Run terraform init

This ensures our Terraform code is connected to Terraform cloud, uses Terraform cloud workspaces and stores our state file remotely.

Terraform Code

Create the following terraform files

backend.tf

terraform {
  cloud {
    organization = " YOUR ORGANIZATION NAME "

    workspaces {
      name = " YOUR WORKSPACES NAME "
    }
  }
}

provider.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

variables.tf

variable "instance_type" {
  type    = string
  default = "t2.micro"
}
variable "monitoring" {
  default = true
}

variable "tags" {
  type = map(any)
  default = {
    Terraform   = "true"
    Environment = "dev"
  }
}

data "aws_vpc" "selected" {
  default = true
}

data "aws_security_groups" "default" {

  filter {
    name   = "group-name"
    values = ["default"]
  }
}

ec2.tf

module "ec2_instance" {
  source = "terraform-aws-modules/ec2-instance/aws"

  for_each = toset(["one", "two", "three"])

  name = "instance-${each.key}"

  instance_type          = var.instance_type
  monitoring             = var.monitoring
  vpc_security_group_ids = data.aws_security_groups.default.ids

  tags = var.tags
}

Create Security Group

Create the Jenkins Security Group with the following inbound rules:

  • Type: HTTP
    Port range: 8080
    Source: My IP

Outbound Rules:

  • Type: All traffic
    Port range: All
    Destination: 0.0.0.0/0

Jenkins Configuration

  1. Enter [Public IP]:8080 or [Public DNS]:8080 in your browser to see Jenkins setup.

    1. retrieve your administrative password by running sudo cat /var/lib/jenkins/secrets/initialAdminPassword

    2. Copy and then paste the result into the Unlock Jenkins field and click Continue.

    3. Click Install suggested plugins.

    4. Enter the required information. Save and continue to Jenkins.

    5. Click Manage Plugins > Select Available > Search Pipeline: AWS Steps, Terraform and install without restart.

  2. Click Manage Jenkins > Global Tool Configuration then scroll to Terraform and click Add Terraform

  3. Enter any name of your choice and select Terraform version Terraform 30504 linux (386) and click save

    Terraform Cloud Credentials

    1. To get the Terraform Cloud credentials, in the terminal run cat /home/<YOUR-USERNAME>/.terraform.d/credentials.tfrc.json for Linux or open the the file credentials.tfrc.json with the path C:\Users\<YOUR-USERNAME>\AppData\Roaming\terraform.d\credentials.tfrc.json in windows.

    2. Copy the output. Create a local txt file and paste the output and save.

    3. Go back to Jenkins and add a new credential.

  • Kind = Secret file

  • File = (Choose the file you just saved)

  • ID = tf-creds

  • Description = terraform cloud credentials

  1. Click Create

GitHub Webhooks

  1. Go to the project GitHub repo and click Settings.

  2. Click Webhooks then Add Webhook

  3. Enter the following:

    Payload URL = [jenkins url]/github-webhook/
    Please Note: Ensure the / is at the end.
    Content type = application/json

    Which events would you like to trigger this webhook? = Just the push event

  4. Click Add WebHook

Create Jenkins Pipeline

  1. Go to the Jenkins Dashboard and click New Item.

  2. Name the pipeline terraform-jenkins and select Pipeline. Then click OK.

  3. Configure the pipeline
    1. Build Triggers = GitHub hook trigger for GITScm polling

    2. Pipeline Definition = Pipeline script from SCM

    3. SCM = Git

    4. Repository HTTPS URL = [repo name].git

    5. Branches to build = */main

    6. Script Path = jenkinsfile

JenkinsFile

Jenkins requires a Jenkinsfile in the root of our code directory to create a Jenkins Pipeline.

pipeline {
  agent any
  environment {
    TF_IN_AUTOMATION = 'true'
    TF_CLI_CONFIG_FILE = credentials('tf-creds')
  }
tools {
  terraform 'terraform'
}

stages {
    stage('Init') {
      steps {
        sh 'terraform init -no-color'
      }
    }
    stage('Plan') {
      steps {
        sh 'terraform plan -no-color'
      }
    }
    stage('Apply') {
      steps {
        sh 'terraform apply -auto-approve -no-color'
      }
    }
}
}

Push your code to GitHub and the build process will be triggered because of the GitHub webhook we created earlier.

The image below shows a successful build along with the instances running in AWS.

Destroy the Infrastructure using Jenkins Build Parameters

Our intention with build parameters is to provide an option for the users to select which “Action” they wish to perform. Depending on the selection, the pipeline will either run the “apply” command or “destroy” the infrastructure.

  1. Go to: Dashboard >terraform-jenkins> Configuration. In the general section, click on the checkbox stating, “This project is parameterized.”

  2. Select the Choice Parameter and fill in the form as shown below. The name represents the “variable” name we will use in our pipeline script to replace the variable with the selected value.

    Each choice is listed on the next line; here, we have two choices – apply and destroy. These are potential values.

  3. Edit the jenkinsfile to use the action variable in the “ Apply” stage.

  4. Click on Build with Parameters then Select destroy and click on Build

    The image below shows the resources being destroyed along with confirmation of the instances terminated in AWS.