Automating AMI Creation with Packer and CI/CD
Custom Amazon Machine Images (AMIs) are essential for maintaining consistency across your EC2 infrastructure. Packer, combined with a CI/CD pipeline, enables automated, repeatable AMI creation.
Why Use Packer?
Manual AMI creation is error-prone and time-consuming. Packer provides:
- Infrastructure as Code: AMI configuration in version control
- Reproducibility: Same configuration always produces the same result
- Multi-cloud support: Build images for AWS, Azure, GCP, and more
- Integration: Works seamlessly with CI/CD pipelines
Basic Packer Template Structure
Here’s a simple Packer template for an Amazon Linux 2023 AMI:
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1.0"
}
}
}
source "amazon-ebs" "al2023" {
ami_name = "custom-al2023-{{timestamp}}"
instance_type = "t3.micro"
region = var.region
source_ami_filter {
filters = {
name = "al2023-ami-*-x86_64"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["amazon"]
}
ssh_username = "ec2-user"
}
build {
sources = ["source.amazon-ebs.al2023"]
provisioner "shell" {
scripts = [
"scripts/update-system.sh",
"scripts/install-tools.sh",
"scripts/configure-services.sh"
]
}
}
CI/CD Integration
Azure DevOps Pipeline Example
trigger:
branches:
include:
- main
paths:
include:
- src/al-2023/*
stages:
- stage: Build
jobs:
- job: PackerBuild
steps:
- task: PackerTool@0
inputs:
version: '1.12.0'
- script: |
packer validate -var-file=env/lab.pkrvars.hcl src/al-2023
displayName: 'Validate Packer Template'
- script: |
packer build -var-file=env/lab.pkrvars.hcl src/al-2023
displayName: 'Build AMI'
env:
AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
Managing AMI Versions
Use SSM Parameter Store to track the latest AMI:
# Extract AMI ID from Packer manifest
ami_id=$(jq -r '.builds[-1].artifact_id|split(":")[1]' manifest.json)
# Update SSM parameter
aws ssm put-parameter \
--name "/ami/al-2023/latest" \
--value $ami_id \
--type String \
--overwrite
Best Practices
1. Use Session Manager Instead of SSH
Configure Packer to use SSM Session Manager for provisioning:
source "amazon-ebs" "al2023" {
# ... other settings
communicator = "ssh"
ssh_interface = "session_manager"
iam_instance_profile = "packer-builder-profile"
}
2. Encrypt AMIs
Always encrypt your AMIs:
source "amazon-ebs" "al2023" {
# ... other settings
encrypt_boot = true
kms_key_id = var.kms_key_id
}
3. Tag Your AMIs
Apply consistent tags for tracking:
source "amazon-ebs" "al2023" {
# ... other settings
tags = {
Name = "Custom AL2023"
Environment = var.environment
BuildDate = "{{timestamp}}"
Version = var.version
}
}
4. Implement Automated Testing
Test your AMI after creation:
# Launch test instance
instance_id=$(aws ec2 run-instances \
--image-id $ami_id \
--instance-type t3.micro \
--query 'Instances[0].InstanceId' \
--output text)
# Run tests
# ...
# Terminate test instance
aws ec2 terminate-instances --instance-ids $instance_id
Conclusion
Automating AMI creation with Packer and CI/CD ensures consistent, secure, and versioned machine images. This approach reduces human error, speeds up deployments, and provides a clear audit trail of infrastructure changes.
Start small with a basic template and gradually add more sophistication as your needs grow.