Immutable Infrastructure Deployment with Ansible, Packer, and Terraform

Task Overview

This task focuses on building immutable infrastructure using Ansible, Packer, and Terraform. The goal is to create immutable server images with Packer, automate the provisioning of infrastructure using Terraform, and manage configurations using Ansible.

Technology Stack

Task Architecture

  1. Packer creates a golden AMI with pre-installed configurations using Ansible.
  2. Terraform provisions infrastructure using the pre-built AMI.
  3. Ansible (optional) performs post-deployment tasks if needed.
  4. Auto Scaling and Load Balancing ensure high availability.
  5. Immutable Deployment Strategy ensures new changes are deployed by creating new instances instead of modifying existing ones.

Step-by-Step Implementation

Step 1: Set Up Your Development Environment

Step 2: Create an Ansible Playbook to Configure the Server

Create an Ansible playbook (playbook.yml) to install required packages.

    ---
    - name: Configure Web Server
      hosts: all
      become: yes
      tasks:
        - name: Install Apache
          apt:
            name: apache2
            state: present
        - name: Start Apache
          service:
            name: apache2
            state: started
            enabled: yes
        - name: Copy website content
          copy:
            src: index.html
            dest: /var/www/html/index.html
    

Step 3: Create a Packer Template to Build AMI

Create a file named packer-template.json.

    {
      "variables": {
        "aws_region": "us-east-1",
        "ami_name": "immutable-webserver"
      },
      "builders": [{
        "type": "amazon-ebs",
        "region": "{{user `aws_region`}}",
        "source_ami_filter": {
          "filters": {
            "virtualization-type": "hvm",
            "name": "ubuntu/images/hvm-ssd/ubuntu-22.04-amd64-server-*",
            "root-device-type": "ebs"
          },
          "owners": ["099720109477"],
          "most_recent": true
        },
        "instance_type": "t2.micro",
        "ssh_username": "ubuntu",
        "ami_name": "{{user `ami_name`}}-{{timestamp}}"
      }],
      "provisioners": [{
        "type": "ansible",
        "playbook_file": "playbook.yml"
      }]
    }
    

Build the AMI

Run the following command:

    packer init .
    packer build packer-template.json
    

This will create an AMI ID, which will be used in Terraform.

Step 4: Define Infrastructure with Terraform

Create a Terraform configuration file (main.tf).

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

    variable "ami_id" {}

    resource "aws_instance" "webserver" {
      ami           = var.ami_id
      instance_type = "t2.micro"

      tags = {
        Name = "Immutable-Web-Server"
      }
    }

    output "instance_ip" {
      value = aws_instance.webserver.public_ip
    }
    

Terraform Commands

    terraform init
    terraform apply -var="ami_id=ami-xxxxxx"
    

(Replace ami-xxxxxx with your Packer-generated AMI ID)

Step 5: Automate Deployment Using CI/CD

(Optional) Use Jenkins to trigger Packer and Terraform workflows.

pipeline {
    agent any
    stages {
        stage('Build AMI') {
            steps {
                sh 'packer build packer-template.json'
            }
        }
        stage('Deploy Infra') {
            steps {
                sh 'terraform apply -var="ami_id=ami-xxxxxx" -auto-approve'
            }
        }
    }
}

Step 6: Testing & Verification

Step 7: Scaling & Auto Scaling

Modify Terraform to use an Auto Scaling Group (ASG) and Load Balancer (ALB) for high availability.

resource "aws_launch_template" "webserver" {
  name_prefix   = "webserver-template"
  image_id      = var.ami_id
  instance_type = "t2.micro"
}

resource "aws_autoscaling_group" "webserver_asg" {
  desired_capacity     = 2
  max_size            = 3
  min_size            = 1
  vpc_zone_identifier = ["subnet-xxxxxx"]

  launch_template {
    id      = aws_launch_template.webserver.id
    version = "$Latest"
  }
}

Deploy with:

terraform apply -var="ami_id=ami-xxxxxx"

Final Outcome

Next Steps & Enhancements

Conclusion

This end-to-end implementation follows a truly immutable infrastructure approach, ensuring reliable, scalable, and automated deployments using Ansible, Packer, and Terraform.