September 22, 2024
CloudDevops

Automating AMI Backups with AWS Lambda and Boto3

In the era of cloud computing, ensuring the security and recoverability of your infrastructure is a paramount concern. One way to achieve this is through the use of Amazon Machine Images (AMI) for backup on Amazon Web Services (AWS).

AMIs provide a way to create a snapshot of an instance’s configuration and data, allowing you to quickly launch new instances with the same setup, or restore an instance in the event of failure. However, managing AMI creation can be time-consuming if done manually.

In this blog post, we will discuss a method to automate this process using AWS Lambda and Boto3, AWS SDK for Python.

Why Automate AMI Backups?

Automating AMI backups not only saves time and effort, but also ensures that backups are taken at regular intervals, improving your Disaster Recovery (DR) strategy. It also provides a safety net, allowing you to recover instances quickly and efficiently.

Backup Automation with AWS Lambda and Boto3

The script we’ll use is an AWS Lambda function that uses Boto3, AWS SDK for Python, to interact with the EC2 service.

We start by creating a Boto3 client for EC2, and define filters to select which instances to backup based on specific tags. In this case, we’re looking for instances with a tag ‘Backup’ and value ‘true’.

filters = [
    {
        'Name': 'tag:Backup',
        'Values': ['true']
    }
]
instances = ec2.describe_instances(Filters=filters)

The script then iterates through the filtered instances, retrieving the instance ID and Name. For each instance, it creates a timestamp, appends it to the instance name and updates the instance ‘Name’ tag.

# Create timestamp
timestamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')

# Update instance name with timestamp
instance_resource = ec2_resource.Instance(instance_id)
instance_resource.create_tags(Tags=[{'Key': 'Name', 'Value': instance_name + '-' + timestamp}])

Next, the script creates an AMI from the instance, providing a name and description that include the instance ID and timestamp.

# Create image (AMI)
response = ec2.create_image(
    InstanceId=instance_id,
    Name=image_name,
    Description=image_description,
    NoReboot=True
)

Finally, the script adds tags to the new AMI and its snapshots, including a ‘Backup’ tag with a value of ‘true’ and an ‘AutoDelete’ tag with a value indicating the number of days to keep the backup.

snapshots = ec2.describe_snapshots(Filters=[{'Name': 'description', 'Values': ['*' + image_id + '*']}])
for snapshot in snapshots['Snapshots']:
    ec2.create_tags(
        Resources=[image_id, snapshot['SnapshotId']],
        Tags=[
            {'Key': 'Backup', 'Value': 'true'},
            {'Key': 'AutoDelete', 'Value': '7'},
            {'Key': 'Name', 'Value': image_name}
        ]
    )


The Full Script

Here’s the complete AWS Lambda function to automate AMI backups:

import boto3
import datetime

def lambda_handler(event, context):
ec2 = boto3.client('ec2')
ec2_resource = boto3.resource('ec2')

filters = [
    {
        'Name': 'tag:Backup',
        'Values': ['true']
    }
]

instances = ec2.describe_instances(Filters=filters)

for reservation in instances['Reservations']:
    for instance in reservation['Instances']:
        instance_id = instance['InstanceId']
        instance_name = ''
        for tag in instance['Tags']:
            if tag['Key'] == 'Name':
                instance_name = tag['Value']

        # Create timestamp
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')

        # Update instance name with timestamp
        instance_resource = ec2_resource.Instance(instance_id)
        instance_resource.create_tags(Tags=[{'Key': 'Name', 'Value': instance_name + '-' + timestamp}])

        # Create image name based on instance name and current date
        image_name = instance_name + '-' + timestamp
        image_description = 'AMI of ' + instance_id + ' from ' + timestamp

        # Create image (AMI)
        response = ec2.create_image(
            InstanceId=instance_id,
            Name=image_name,
            Description=image_description,
            NoReboot=True
        )

        # Retrieve image (AMI) id from response
        image_id = response['ImageId']

        # Add 'Backup=true', 'AutoDelete=7' tag and name to the new AMI and its snapshots
        snapshots = ec2.describe_snapshots(Filters=[{'Name': 'description', 'Values': ['*' + image_id + '*']}])
        for snapshot in snapshots['Snapshots']:
            ec2.create_tags(
                Resources=[image_id, snapshot['SnapshotId']],
                Tags=[
                    {'Key': 'Backup', 'Value': 'true'},
                    {'Key': 'AutoDelete', 'Value': '7'},
                    {'Key': 'Name', 'Value': image_name}
                ]
            )

return {
    'statusCode': 200,
    'body': 'AMIs and corresponding EBS snapshots created and tagged successfully'
}

Leave a Reply

Your email address will not be published. Required fields are marked *