Skip to content

Image Builders Comparison #5

Image Builders Comparison

Image Builders Comparison #5

name: Image Builders Comparison
on:
workflow_dispatch:
inputs:
run_packer:
description: 'Run Packer build'
type: boolean
default: true
run_ec2_imagebuilder:
description: 'Run EC2 Image Builder'
type: boolean
default: true
env:
AWS_REGION: us-west-2
permissions:
id-token: write
contents: read
jobs:
packer-build:
name: HashiCorp Packer Build
runs-on: ubuntu-latest
if: ${{ github.event.inputs.run_packer == 'true' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup Packer
uses: hashicorp/setup-packer@main
with:
version: "1.9.4"
- name: Get latest Ubuntu AMI
run: |
echo "πŸ” Searching for Ubuntu 22.04 AMI..."
# Try specific search first
UBUNTU_AMI=$(aws ec2 describe-images \
--owners 099720109477 \
--filters \
"Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-22.04-amd64-server-*" \
"Name=state,Values=available" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
--output text 2>/dev/null || echo "")
# If that fails, try broader search
if [ "$UBUNTU_AMI" = "" ] || [ "$UBUNTU_AMI" = "None" ]; then
echo "⚠️ First search failed, trying broader search..."
UBUNTU_AMI=$(aws ec2 describe-images \
--owners 099720109477 \
--filters \
"Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-*-amd64-server-*" \
"Name=state,Values=available" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
--output text)
fi
# Fallback to known AMI
if [ "$UBUNTU_AMI" = "" ] || [ "$UBUNTU_AMI" = "None" ]; then
echo "⚠️ Using hardcoded Ubuntu 22.04 AMI for us-west-2"
UBUNTU_AMI="ami-0c2d3e23eb7b0270d"
fi
echo "βœ… Using Ubuntu AMI: $UBUNTU_AMI"
echo "UBUNTU_AMI=$UBUNTU_AMI" >> $GITHUB_ENV
- name: Create Packer template
run: |
cat > packer-template.pkr.hcl << EOF
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1"
}
}
}
source "amazon-ebs" "ubuntu" {
ami_name = "packer-demo-\${timestamp()}"
instance_type = "t3.micro"
region = "${{ env.AWS_REGION }}"
source_ami = "${{ env.UBUNTU_AMI }}"
ssh_username = "ubuntu"
tags = {
Name = "packer-demo-\${timestamp()}"
Tool = "HashiCorp-Packer"
}
}
build {
sources = ["source.amazon-ebs.ubuntu"]
provisioner "shell" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
"sudo systemctl enable nginx",
"echo '<h1>Built with HashiCorp Packer</h1>' | sudo tee /var/www/html/index.html"
]
}
}
EOF
- name: Initialize and build with Packer
run: |
echo "πŸš€ Starting Packer build with AMI: $UBUNTU_AMI"
packer init packer-template.pkr.hcl
packer validate packer-template.pkr.hcl
packer build packer-template.pkr.hcl | tee packer-build.log
echo "βœ… Packer build completed!"
- name: Upload Packer logs
uses: actions/upload-artifact@v4
with:
name: packer-build-logs
path: packer-build.log
ec2-imagebuilder-build:
name: AWS EC2 Image Builder Build
runs-on: ubuntu-latest
if: ${{ github.event.inputs.run_ec2_imagebuilder == 'true' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get latest Ubuntu AMI
run: |
echo "πŸ” Searching for Ubuntu 22.04 AMI..."
# Try multiple search patterns
UBUNTU_AMI=$(aws ec2 describe-images \
--owners 099720109477 \
--filters \
"Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-22.04-amd64-server-*" \
"Name=state,Values=available" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
--output text 2>/dev/null || echo "")
# If that fails, try a broader search
if [ "$UBUNTU_AMI" = "" ] || [ "$UBUNTU_AMI" = "None" ]; then
echo "⚠️ First search failed, trying broader search..."
UBUNTU_AMI=$(aws ec2 describe-images \
--owners 099720109477 \
--filters \
"Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-*-amd64-server-*" \
"Name=state,Values=available" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
--output text)
fi
# If still fails, use a known working AMI
if [ "$UBUNTU_AMI" = "" ] || [ "$UBUNTU_AMI" = "None" ]; then
echo "⚠️ AMI search failed, using hardcoded Ubuntu 22.04 AMI for us-west-2"
UBUNTU_AMI="ami-0c2d3e23eb7b0270d" # Ubuntu 22.04 LTS in us-west-2
fi
echo "βœ… Using Ubuntu AMI: $UBUNTU_AMI"
# Verify the AMI exists
aws ec2 describe-images --image-ids $UBUNTU_AMI --query 'Images[0].Name' --output text
echo "UBUNTU_AMI=$UBUNTU_AMI" >> $GITHUB_ENV
- name: Run EC2 Image Builder pipeline
run: |
echo "πŸš€ Starting EC2 Image Builder with AMI: $UBUNTU_AMI"
# Verify we have a valid AMI
if [ "$UBUNTU_AMI" = "" ] || [ "$UBUNTU_AMI" = "None" ]; then
echo "❌ No valid AMI found. Exiting."
exit 1
fi
# Create component with proper YAML formatting
cat > component.yml << 'EOF'
name: InstallNginx
description: Install Nginx web server
schemaVersion: 1.0
phases:
- name: build
steps:
- name: UpdateOS
action: UpdateOS
- name: InstallNginx
action: ExecuteBash
inputs:
commands:
- apt-get update
- apt-get install -y nginx
- systemctl enable nginx
- echo '<h1>Built with EC2 Image Builder</h1>' > /var/www/html/index.html
EOF
echo "πŸ“‹ Component YAML:"
cat component.yml
# Create component
COMPONENT_ARN=$(aws imagebuilder create-component \
--name "nginx-component-$(date +%s)" \
--semantic-version "1.0.0" \
--description "Install Nginx" \
--platform Linux \
--data file://component.yml \
--query 'componentBuildVersionArn' \
--output text)
echo "βœ… Component created: $COMPONENT_ARN"
# Create image recipe
RECIPE_ARN=$(aws imagebuilder create-image-recipe \
--name "nginx-recipe-$(date +%s)" \
--semantic-version "1.0.0" \
--description "Ubuntu with Nginx" \
--parent-image "$UBUNTU_AMI" \
--components componentArn=$COMPONENT_ARN \
--query 'imageRecipeArn' \
--output text)
echo "βœ… Recipe created: $RECIPE_ARN"
# Get default VPC info for infrastructure config
DEFAULT_VPC=$(aws ec2 describe-vpcs \
--filters "Name=is-default,Values=true" \
--query 'Vpcs[0].VpcId' \
--output text)
DEFAULT_SUBNET=$(aws ec2 describe-subnets \
--filters "Name=vpc-id,Values=$DEFAULT_VPC" \
--query 'Subnets[0].SubnetId' \
--output text)
echo "🌐 Using VPC: $DEFAULT_VPC, Subnet: $DEFAULT_SUBNET"
# Create infrastructure configuration
INFRA_ARN=$(aws imagebuilder create-infrastructure-configuration \
--name "basic-infra-$(date +%s)" \
--instance-types t3.micro \
--subnet-id "$DEFAULT_SUBNET" \
--query 'infrastructureConfigurationArn' \
--output text)
echo "βœ… Infrastructure config created: $INFRA_ARN"
# Start image build
IMAGE_ARN=$(aws imagebuilder create-image \
--image-recipe-arn "$RECIPE_ARN" \
--infrastructure-configuration-arn "$INFRA_ARN" \
--query 'imageBuildVersionArn' \
--output text)
echo "βœ… Image build started: $IMAGE_ARN"
# Create build log
echo "Build Summary:" > ec2-imagebuilder-build.log
echo "Base AMI: $UBUNTU_AMI" >> ec2-imagebuilder-build.log
echo "Image ARN: $IMAGE_ARN" >> ec2-imagebuilder-build.log
echo "Recipe ARN: $RECIPE_ARN" >> ec2-imagebuilder-build.log
echo "Component ARN: $COMPONENT_ARN" >> ec2-imagebuilder-build.log
echo "Infrastructure ARN: $INFRA_ARN" >> ec2-imagebuilder-build.log
- name: Upload EC2 Image Builder logs
uses: actions/upload-artifact@v4
with:
name: ec2-imagebuilder-logs
path: ec2-imagebuilder-build.log
comparison-summary:
name: Build Comparison Summary
runs-on: ubuntu-latest
needs: [packer-build, ec2-imagebuilder-build]
if: always()
steps:
- name: Generate comparison report
run: |
echo "# Image Builder Comparison Report" > comparison-report.md
echo "" >> comparison-report.md
echo "## Build Results" >> comparison-report.md
echo "" >> comparison-report.md
if [ "${{ needs.packer-build.result }}" = "success" ]; then
echo "βœ… **HashiCorp Packer**: Build completed successfully" >> comparison-report.md
else
echo "❌ **HashiCorp Packer**: Build failed or skipped" >> comparison-report.md
fi
if [ "${{ needs.ec2-imagebuilder-build.result }}" = "success" ]; then
echo "βœ… **AWS EC2 Image Builder**: Build completed successfully" >> comparison-report.md
else
echo "❌ **AWS EC2 Image Builder**: Build failed or skipped" >> comparison-report.md
fi
echo "" >> comparison-report.md
echo "## Key Differences Observed" >> comparison-report.md
echo "- **Packer**: Uses direct AMI ID, faster execution" >> comparison-report.md
echo "- **EC2 Image Builder**: More verbose setup, better AWS integration" >> comparison-report.md
echo "" >> comparison-report.md
echo "Build completed at: $(date)" >> comparison-report.md
cat comparison-report.md
- name: Upload comparison report
uses: actions/upload-artifact@v4
with:
name: comparison-report
path: comparison-report.md