Scale Your App on Autopilot: Terraform for EC2 Auto Scaling

In today’s fast-paced development environment, deploying applications quickly and efficiently is crucial. Manual deployments are error-prone and time-consuming. This is where Terraform for EC2 Auto Scaling comes in. By leveraging Terraform’s infrastructure as code (IaC) capabilities and the power of EC2 Auto Scaling, you can automate your deployments and achieve seamless scaling to meet your application’s demands. This tutorial will guide you through setting up an automated deployment pipeline using Terraform for EC2 Auto Scaling, empowering you to “deploy and scale like a pro.

Why Automate Deployments?

Manual deployments are prone to errors and inconsistencies. Automating them with tools like Terraform offers several benefits:

  • Reduced Errors: Terraform scripts ensure consistent infrastructure provisioning, minimizing human error.
  • Improved Efficiency: Automation frees up valuable developer time for other tasks.
  • Faster Releases: Deployments become quicker and more predictable.
  • Scalability: Auto Scaling Groups automatically adjust EC2 instances based on demand.

Use-Case Scenario

Imagine a growing e-commerce platform that needs to handle traffic spikes during sales events. Manually scaling servers is time-consuming and error-prone. By automating deployments with Terraform and using EC2 Auto Scaling, the platform can automatically adjust its server capacity in real-time, ensuring seamless performance during peak times without manual intervention.

Prerequisites

  • An AWS account with administrative privileges.
  • Basic understanding of AWS services like EC2, ASG, and IAM roles.
  • Familiarity with Terraform concepts.

Step-by-Step Guide

Step 1: Install Terraform

  1. Download Terraform:
  • Windows:
    • Download the Terraform executable from the Terraform website.
    • Unzip the downloaded file and place the terraform.exe file in a directory included in your system’s PATH.
  • macOS: brew tap hashicorp/tap brew install hashicorp/tap/terraform
  • Linux:
    bash sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" sudo apt-get update && sudo apt-get install terraform
  1. Verify Installation:
   terraform -v

Step 2: Define Your Infrastructure in Terraform

  1. Set Up Your Terraform Directory Create a directory for your Terraform project and navigate into it:
   mkdir my-terraform-project
   cd my-terraform-project
  1. Initialize Terraform Initialize your Terraform project to set up the necessary files and download provider plugins:
   terraform init
  1. Create the Main Terraform Configuration File Create a main.tf file where you’ll define your infrastructure resources:
   touch main.tf
  1. Breakdown of main.tf Provider Configuration:
   provider "aws" {
     region = "us-west-2"
   }

This block specifies the AWS region where your resources will be created.

EC2 Instance Resource:

   resource "aws_instance" "app_server" {
     ami           = "ami-0c55b159cbfafe1f0"  # Replace with your preferred AMI
     instance_type = "t2.micro"

     tags = {
       Name = "AppServer"
     }
   }

This block defines an EC2 instance with a specified AMI and instance type.

Security Group Configuration:

   resource "aws_security_group" "app_sg" {
     name_prefix = "app-sg"

     ingress {
       from_port   = 22
       to_port     = 22
       protocol    = "tcp"
       cidr_blocks = ["0.0.0.0/0"]
     }

     ingress {
       from_port   = 80
       to_port     = 80
       protocol    = "tcp"
       cidr_blocks = ["0.0.0.0/0"]
     }

     egress {
       from_port   = 0
       to_port     = 0
       protocol    = "-1"
       cidr_blocks = ["0.0.0.0/0"]
     }
   }

This block defines a security group allowing SSH (port 22) and HTTP (port 80) access.

Auto Scaling Group:

   resource "aws_autoscaling_group" "app_asg" {
     desired_capacity     = 1
     max_size             = 3
     min_size             = 1
     launch_configuration = aws_launch_configuration.app_lc.id

     tag {
       key                 = "Name"
       value               = "AppServer"
       propagate_at_launch = true
     }
   }

This block defines an Auto Scaling group to manage the EC2 instances.

Launch Configuration:

   resource "aws_launch_configuration" "app_lc" {
     name          = "app-launch-configuration"
     image_id      = "ami-0c55b159cbfafe1f0"
     instance_type = "t2.micro"
     security_groups = [aws_security_group.app_sg.id]

     lifecycle {
       create_before_destroy = true
     }
   }

This block defines the launch configuration used by the Auto Scaling group.

  1. Check Terraform Configuration: Once main.tf is configured, verify the setup:
   terraform validate

This command checks the syntax and configuration of your Terraform files.

Step 3: Configure Application Deployment

  1. Develop a Deployment Script Create a deployment script (deploy.sh) to automate your application deployment process. Here’s an example bash script:
   #!/bin/bash
   sudo apt-get update
   sudo apt-get install -y apache2
   sudo systemctl start apache2
   sudo systemctl enable apache2

   echo "<h1>Deployed via Terraform</h1>" | sudo tee /var/www/html/index.html
  1. Store Deployment Script in S3 Upload the deployment script to an S3 bucket for easy access by your EC2 instances. Use the AWS CLI to upload the script:
   aws s3 cp deploy.sh s3://my-bucket/deploy.sh

Security Consideration:

Avoid storing sensitive information like passwords or API keys directly in your Terraform code. Utilize AWS Secrets Manager to securely store and retrieve secrets for your deployment scripts.

Step 4: Grant Permissions with IAM Roles

  1. Create an IAM Role Create an IAM role with permissions to access S3 and other resources needed during deployment:
   resource "aws_iam_role" "ec2_role" {
     name = "ec2_role"

     assume_role_policy = jsonencode({
       Version = "2012-10-17",
       Statement = [
         {
           Action = "sts:AssumeRole",
           Effect = "Allow",
           Principal = {
             Service = "ec2.amazonaws.com"
           }
         }
       ]
     })
   }
  1. Attach Policy to IAM Role Attach a policy to the IAM role to grant necessary permissions:
   resource "aws_iam_role_policy" "ec2_policy" {
     name = "ec2_policy"
     role = aws_iam_role.ec2_role.id

     policy = jsonencode({
       Version = "2012-10-17",
       Statement = [
         {
           Action = [
             "s3:GetObject"
           ],
           Effect   = "Allow",
           Resource = "arn:aws:s3:::my-bucket/*"
         }
       ]
     })
   }

Note: The policy version “2012-10-17” is a standard version and is still relevant as it specifies the structure of IAM policies.

  1. Attach IAM Role to EC2 Instance Attach the IAM role to your EC2 instances:
   resource "aws_instance" "app_server" {
     ami                  = "ami-0c55b159cbfafe1f0"
     instance_type        = "t2.micro"
     security_groups      = [aws_security_group.app_sg.name]
     iam_instance_profile = aws_iam_instance_profile.ec2_instance_profile.name

     tags = {
       Name = "AppServer"
     }
   }

   resource "aws_iam_instance_profile" "ec2_instance_profile" {
     name = "ec2_instance_profile"
     role = aws_iam_role.ec2_role.name
   }

Security Consideration:

Emphasize the principle of least privilege for IAM roles. Grant only the permissions necessary for the EC2 instances to function and deploy the application. Avoid using wildcards or overly broad permissions in IAM policies.

Step 5: Automate Deployments with Terraform

  1. Leverage the Null Resource Use the null_resource to trigger the deployment script upon infrastructure creation or updates:
   resource "null_resource" "deployment" {
     provisioner "local-exec" {
       command = "aws s3 cp s3://my-bucket/deploy.sh . && sh deploy.sh"
     }

     triggers = {
       ami_id = aws_instance.app_server.ami
     }
   }

This script downloads the deploy.sh from S3 and executes it on the EC2 instance.

State Management

Terraform uses a state file to keep track of your infrastructure. This state file maps resources defined in your configuration to real-world resources. Storing the state file remotely ensures it is safely backed up and accessible from different machines. Use an S3 bucket for remote state storage:

  1. Configure Remote State Storage Create a backend configuration in your main.tf:
   terraform {
     backend "s3" {
       bucket = "my-terraform-state-bucket"
       key    = "terraform.tfstate"
       region = "us-west-2"
     }
   }
  1. Initialize Terraform with Remote State Reinitialize Terraform to use the remote state backend:
   terraform init

Step 6: Execute Terraform

  1. Plan and Apply Run terraform plan to preview the infrastructure changes:
   terraform plan

If the plan looks good, apply the configuration:

   terraform apply

Common Problems and Solutions

  1. Error: “No valid credential sources found” Ensure that your AWS credentials are properly configured. You can set them up using the AWS CLI:
   aws configure
  1. Error: “Instance type not supported in your region” Make sure you are using an instance type that is available in your specified region. Check the AWS documentation for more details.
  2. Error: “Access Denied” Ensure that your IAM roles and policies are correctly configured and have the necessary permissions.

CI/CD Integration

How CI/CD Tools Work

CI/CD (Continuous Integration/Continuous Delivery) tools automate the process of integrating code changes, testing them, and deploying them to production. This ensures that code changes are continuously tested and deployed without manual intervention, leading to faster and more reliable releases.

Integrating with Terraform

You can integrate Terraform with CI/CD tools like Jenkins, GitLab CI, or GitHub Actions to automate the execution of Terraform scripts whenever changes are pushed to your repository.

Example with GitHub Actions:

Step-by-Step CI/CD Integration

  1. Create a GitHub Repository: If you haven’t already, create a new repository on GitHub to store your Terraform configuration files.
  2. Add Your Terraform Configuration Files: Push your main.tf and other necessary files to the GitHub repository.
  3. Create a GitHub Actions Workflow File: In your repository, create a file named .github/workflows/terraform.yml:
   name: Terraform

   on:
     push:
       branches:
         - main

   jobs:
     terraform:
       runs-on: ubuntu-latest

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

         - name: Set up Terraform
           uses: hashicorp/setup-terraform@v1

         - name: Terraform Init
           run: terraform init

         - name: Terraform Plan
           run: terraform plan

         - name: Terraform Apply
           if: github.ref == 'refs/heads/main'
           run: terraform apply -auto-approve
  1. GitHub Actions Workflow Breakdown:
  • name: The name of the workflow.
  • on: Specifies the trigger for the workflow. In this case, it triggers on a push to the main branch.
  • jobs: Defines the jobs to be run in the workflow.
  • steps: Specifies the steps to be executed within the job:
    • Checkout code: Checks out the repository code.
    • Set up Terraform: Sets up Terraform using the HashiCorp setup Terraform action.
    • Terraform Init: Initializes the Terraform configuration.
    • Terraform Plan: Runs terraform plan to show the changes required by the current configuration.
    • Terraform Apply: Applies the Terraform configuration if the push is to the main branch.
  1. Commit and Push the Workflow File: Commit and push the .github/workflows/terraform.yml file to your repository. This will trigger the workflow whenever changes are pushed to the main branch.

Security Best Practices

  • IAM Roles with Least Privilege: Emphasize the principle of least privilege for IAM roles. Grant only the permissions necessary for the EC2 instances to function and deploy the application. Avoid using wildcards or overly broad permissions in IAM policies.
  • Secret Management: Don’t store sensitive information like passwords or API keys directly in your Terraform code. Utilize AWS Secrets Manager to securely store and retrieve secrets for your deployment scripts.
  • Security Group Restrictions: Refine your security groups to restrict inbound and outbound traffic only to the necessary ports and sources. Avoid opening up SSH access (port 22) to the entire internet (0.0.0.0/0). Consider using SSH key pairs for secure access.
  • Regular Security Audits: Schedule regular security audits of your infrastructure and deployment pipeline to identify and address potential vulnerabilities.
  • Compliance Considerations: If your application adheres to specific compliance regulations (e.g., HIPAA, PCI DSS), ensure your deployment process aligns with those compliance requirements.

Conclusion

By leveraging Terraform with EC2 Auto Scaling, you can achieve automated and scalable application deployments on AWS. This approach improves development efficiency and allows for faster and more reliable deployments. Remember to adapt this tutorial to your specific application and infrastructure needs. Happy automating!

For expert help, visit the relevant category on Consultium.io to hire an expert in Programming Languages, AI & LLM, Frameworks, Databases, Testing Frameworks, Cloud & DevOps, Emerging Technologies, Salesforce, SAP & CRM.


Find AWS, Cloud & Devops Expert

Additional Resources

Sign In

Register

  • At least 8 characters
  • At least 1 special character
  • At least 1 number
  • At least 1 capital letter

Reset Password

Please enter your username or email address, you will receive a link to create a new password via email.

Membership

An active membership is required for this action, please click on the button below to view the available plans.