Step-by-Step Guide on Creating an Amazon Machine Image (AMI) for an EC2 Instance using Bash and PowerShell Scripts

The provided Bash and PowerShell script helps automate the creation of Amazon Machine Images (AMIs) from existing AWS Elastic Compute Cloud (EC2) instances. This is particularly useful for creating point-in-time backups or disaster recovery. I mostly use the script to quickly clone an EC2 instance for testing or troubleshooting.

Create an AMI in the AWS Console

To create an AMI from an EC2 instance via the AWS web interface, first log into the AWS Management Console and navigate to the EC2 Dashboard, selecting Instances from the left sidebar. Choose the EC2 instance you want to create an AMI from, then click on Actions, navigate to Image and templates, and select Create image. Provide the necessary details for your AMI, such as name and description, then click Create Image to initiate the process.

Creating AMI of an EC2 instance in the AWS Console

This process is easy, but if you need to repeat it often, it can be time-consuming. Both the Bash and PowerShell scripts achieve the same result much more quickly.

Prerequisites

To use the script, you have to install the AWS CLI. The script assumes the executing entity has the necessary permissions. Ensure your IAM roles are correctly configured for EC2 and AMI management.

Overview of the script

The effectiveness of this program relies heavily on the naming of your EC2 instances, something we highly recommend. It requires the user to provide two pieces of information: the name designated to your EC2 instance and the name you’d prefer for the AMI. Usually, we recommend using a date for the name of the AMI, since it simplifies the identification of obsolete AMIs.

Here is an elaborate breakdown of the entire script:

Collecting User Input: The program commences by prompting the user to input the name of the EC2 instance and the AMI name they prefer.

Obtaining Instance ID: Following this, the script uses AWS CLI commands to convert the instance name provided by the user into its corresponding instance ID. This particular ID plays a significant role in ensuring image creation targets the appropriate instance.

AMI Creation Initiation: Upon successful identification of the instance, the script initiates the AMI creation process. It employs the create-image command, specifying the instance ID and the desired AMI name. The –no-reboot flag can be toggled to avoid instance disruption during the image capture process. It typically takes just a few seconds for a Linux instance to come back online. You should avoid using –no-reboot when creating an AMI from an EC2 instance if you want to ensure file system integrity, as this option does not safely shut down the instance before creating the image, potentially leading to corrupted files or incomplete data.

AMI availability monitoring: After triggering the AMI creation, the script waits for AWS to confirm the image is fully available. This step ensures that the subsequent operations don’t proceed until the AMI is ready.

Snapshot handling: AMIs are backed by snapshots of the instance’s EBS volumes. The script fetches these snapshot IDs and renames each to match the AMI name. If your EC2 instance uses multiple EBS volumes, you can easily identify the corresponding snapshots in the AWS Console.

The Bash script

I’ve been using this script on macOS for a while, but I suppose it will also work on Linux.

#!/bin/bash

# Prompt for the EC2 Instance Name and AMI Name

read -p "Enter the EC2 Instance Name: " instance_name

read -p "Enter the AMI Name: " ami_name

# Find the instance ID based on the given instance name

instance_id=$(aws ec2 describe-instances --filters "Name=tag:Name,Values=$instance_name" --query 'Reservations[*].Instances[*].InstanceId' --output text)

# Check if the instance ID was found

if [ -z "$instance_id" ]; then

echo "No instance found with name: $instance_name"

exit 1

fi

echo "Creating AMI from instance: $instance_id"

# Create an image (AMI) from the instance and capture the AMI ID

#ami_id=$(aws ec2 create-image --instance-id $instance_id --name "$ami_name" --no-reboot --query 'ImageId' --output text)

ami_id=$(aws ec2 create-image --instance-id $instance_id --name "$ami_name" --query 'ImageId' --output text)

echo "AMI creation initiated for instance $instance_id with AMI ID $ami_id"

# Wait for the AMI to be available

echo "Waiting for AMI to become available..."

aws ec2 wait image-available --image-ids $ami_id

# Additional delay to ensure snapshots are registered

echo "Waiting for snapshots to be registered..."

sleep 60

# Retrieve the snapshot IDs from the block device mappings of the AMI

snapshot_ids=$(aws ec2 describe-images --image-ids $ami_id --query 'Images[*].BlockDeviceMappings[*].Ebs.SnapshotId' --output text)

# Check if there are snapshots to rename

if [ -z "$snapshot_ids" ]; then

echo "No snapshots found for AMI: $ami_id"

exit 1

fi

# Rename each snapshot to use the AMI name

for snapshot_id in $snapshot_ids; do

echo "Renaming snapshot: $snapshot_id to $ami_name"

aws ec2 create-tags --resources $snapshot_id --tags Key=Name,Value="$ami_name"

done

echo "Snapshots associated with AMI $ami_id have been renamed to $ami_name"

The PowerShell script

The PowerShell script is a me translation of the Bash script. I don’t utilize it regularly. If you encounter any problems, please notify me in the comments section below.

Subscribe to 4sysops newsletter!

# Prompt for the EC2 Instance Name and AMI Name

$instance_name = Read-Host -Prompt “Enter the EC2 Instance Name”

$ami_name = Read-Host -Prompt “Enter the AMI Name”

# Determine the instance ID based on the provided instance name

$instance_id = aws ec2 describe-instances –filters “Name=tag:Name,Values=$instance_name” –query ‘Reservations[*].Instances[*].InstanceId’ –output text

# Check if the instance ID was discovered

if ($null -eq $instance_id -or $instance_id -eq “”) {

Write-Host “No instance found with name: $instance_name”

exit 1

}

Write-Host “Creating AMI from instance: $instance_id”

# Create an image (AMI) from the instance and capture the AMI ID

$ami_id = aws ec2 create-image –instance-id $instance_id –name “$ami_name” –query ‘ImageId’ –output text

Write-Host “AMI creation initiated for instance $instance_id with AMI ID $ami_id”

# Wait for the AMI to be available

Write-Host “Waiting for AMI to become available…”

aws ec2 wait image-available –image-ids $ami_id

# Additional delay to ensure snapshots are registered

Write-Host “Waiting for snapshots to be registered…”

Start-Sleep -Seconds 60

# Retrieve the snapshot IDs from the block device mappings of the AMI

$snapshot_ids = aws ec2 describe-images –image-ids $ami_id –query ‘Images[*].BlockDeviceMappings[*].Ebs.SnapshotId’ –output text

# Check if there are snapshots to rename

if ($null -eq $snapshot_ids -or $snapshot_ids -eq “”) {

Write-Host “No snapshots found for AMI: $ami_id”

exit 1

}

# Rename each snapshot to use the AMI name

foreach ($snapshot_id in $snapshot_ids) {

Write-Host “Renaming snapshot: $snapshot_id to $ami_name”

aws ec2 create-tags –resources $snapshot_id –tags Key=Name,Value=”$ami_name”

}

Write-Host “Snapshots associated with AMI $ami_id have been renamed to $ami_name”


Posted

in

, , , ,

by

Tags: