Automate AWS AMI backups with Retention Period

Automate AWS AMI backups with Retention Period of n Days


Normally, we get requests to enable AMI backups and keep them for last 7 days or 30 days, etc. As it is not feasible to do this manually, it’s best to automate this process.

When we say automation, first thing that comes to mind is DevOps, where we can use different tools such as Ansible or Chef or Puppet. Since, I like to do things in Shell Script, I’ll be sharing the script here (also on Github).

This script make use of an additional CSV file, which has the content as below:

1
2
3
4
5
#InstanceID,RetentionDays
i-b060363e,2
i-f10f5e7f,2
i-07d41dc8,2
i-715b81be,2

The above CSV has 2 columns, viz., InstanceID and RetentionDays. This file is used by the script to automate the AMI backup process.

Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/bin/bash
# Script to create AMI of server on daily basis and deleting AMI older than n no of days

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/snap/bin

alias aws=''$(which aws)' --output text --region ap-southeast-1'
shopt -s expand_aliases

createAMI() {
#To create a unique AMI name for this script
INST_NAME="$(aws ec2 describe-instances --filters Name=instance-id,Values=$1 --query 'Reservations[*].Instances[*].Tags[?Key==`Name`].Value')"
INST_TAG="$INST_NAME"_"$(date +%d%b%y)"
echo -e "Starting the Daily AMI creation: $INST_TAG\n"

#To create AMI of defined instance
AMI_ID=$(aws ec2 create-image --instance-id "$1" --name "$INST_TAG" --description "$1"_"$(date +%d%b%y)" --no-reboot)
echo "New AMI Id is: $AMI_ID"
echo "Waiting for 0.5 minutes"
sleep 30

#Renaming AMI and its Snapshots
aws ec2 create-tags --resources "$AMI_ID" --tags Key=Name,Value="$INST_TAG"
aws ec2 describe-images --image-id "$AMI_ID" --query 'Images[*].BlockDeviceMappings[*].Ebs.SnapshotId' | tr -s '\t' '\n' > /tmp/newsnaplist.txt
while read SNAP_ID; do
aws ec2 create-tags --resources "$SNAP_ID" --tags Key=Name,Value="$INST_TAG"
done < /tmp/newsnaplist.txt

#Finding AMI older than n which needed to be removed
if [[ $(aws ec2 describe-images --filters Name=description,Values="$1"_"$(date +%d%b%y --date ''$2' days ago')" --query 'Images[*].BlockDeviceMappings[*].Ebs.SnapshotId' | tr -s '\t' '\n') ]]
then
AMIDELTAG="$1"_"$(date +%d%b%y --date ''$2' days ago')"

#Finding Image ID of instance which needed to be Deregistered
AMIDELETE=$(aws ec2 describe-images --filters Name=description,Values="$AMIDELTAG" --query 'Images[*].ImageId' | tr -s '\t' '\n')

#Find the snapshots attached to the Image need to be Deregister
aws ec2 describe-images --filters Name=image-id,Values="$AMIDELETE" --query 'Images[*].BlockDeviceMappings[*].Ebs.SnapshotId' | tr -s '\t' '\n' > /tmp/snap.txt

#Deregistering the AMI
aws ec2 deregister-image --image-id "$AMIDELETE"

#Deleting snapshots attached to AMI
while read SNAP_DEL; do
aws ec2 delete-snapshot --snapshot-id "$SNAP_DEL"
done < /tmp/snap.txt
else
echo "No AMI present"
fi
}

###################################################################
########## Call the instance function below as shown ##############
###################################################################

IFS=','
grep -v '^#' /root/cloudcover/ami_automation/instanceList.csv | while read -r INST_ID RETENTION; do
createAMI $INST_ID $RETENTION
done


######### Removing temporary files
rm -f /tmp/snap.txt /tmp/newsnaplist.txt

I’ll explain the above code below:

  1. Export PATH and set alias for aws command.
  2. Declare a function createAMI which encompasses create-image, decribe-images, deregister-image, etc API calls.
  3. With the instanceList.csv file, we call the createAMI function for each line (or Instance ID) with retention period in days.

Notes:

  • The script assumes default AWS CLI profile being used (or role assigned to an instance).
  • You can change your input file (instanceList.csv) in the script.
  • The script has been tested by me and is working on production level.
  • It is highly recommended to test before using this script.
  • I am not responsible for any damage caused by this. (Given that there is no rm -rf * command in it.)

Any optimization in the script is welcome. This script is uploaded on Github.

amazon web services aws awscli linux acm ami