Skip to content

Instantly share code, notes, and snippets.

@eekfonky
Created March 9, 2018 11:59
Show Gist options
  • Save eekfonky/cd3acd76d13bca1485e15afa6d59f92a to your computer and use it in GitHub Desktop.
Save eekfonky/cd3acd76d13bca1485e15afa6d59f92a to your computer and use it in GitHub Desktop.
Backup EBS Volume to Another Region
#!/bin/bash
# error handling
error_handler() {
echo "Error occurred in script at line: ${1}"
echo "Line exited with status: ${2}"
}
trap 'error_handler ${LINENO} $?' ERR
set -o errexit
set -o errtrace
set -o nounset
## Variable Declartions ##
# get Instance Details
INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
# how many days do you wish to retain backups for? Default: 7 days
RETENTION_DAYS="7"
RETENTION_DATE_IN_SECONDS=$(date +%s --date=-"$RETENTION_DAYS"+days)
# tags for snapshots
TAG_NAME="CreatedBy"
TAG_VALUE="AutomatedJenkinsBackup"
# get source region
SOURCE_REGION=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/\([1-9]\).$/\1/g')
# get destination region
DESTINATION_REGION="eu-west-1"
# grab ALL volume IDs attached to this instance
# VOLUME_LIST=$(aws ec2 describe-volumes --region "$SOURCE_REGION" --filters Name=attachment.instance-id,Values="$INSTANCE_ID" --query Volumes[].VolumeId --output text)
# grab volumes with termination set to TRUE
# VOLUME_LIST=$(aws ec2 describe-volumes --region "$SOURCE_REGION" --filters Name=attachment.instance-id,Values="$INSTANCE_ID" Name=attachment.delete-on-termination,Values=true --query Volumes[].VolumeId --output text)
# grab volumes with termination set to FALSE
VOLUME_LIST=$(aws ec2 describe-volumes --region "$SOURCE_REGION" --filters Name=attachment.instance-id,Values="$INSTANCE_ID" Name=attachment.delete-on-termination,Values=false --query Volumes[].VolumeId --output text)
# DEST_VOLUME_LIST=$(aws ec2 describe-volumes --region "$DESTINATION_REGION" --filters Name=attachment.instance-id,Values="$INSTANCE_ID" Name=attachment.delete-on-termination,Values=false --query Volumes[].VolumeId --output text)
# Timestamp
TIMESTAMP=$(date +%F-%a) # year-month-date-day format
ORIG_SNAPSHOT="$TIMESTAMP-$VOLUME_LIST.json"
## Function Declarations ##
package_to_install () {
# enter the package you want installed in PKG_NAME below
PKG_NAME="jq"
if ! type $PKG_NAME > /dev/null 2>&1; then
# check Linux package manager (yum or apt)
declare -A osInfo;
osInfo[/etc/redhat-release]=yum
osInfo[/etc/yum.conf]=yum
osInfo[/etc/arch-release]=pacman
osInfo[/etc/gentoo-release]=emerge
osInfo[/etc/SuSE-release]=zypp
osInfo[/etc/debian_version]=apt
osInfo[/etc/lsb-release]=apt
for f in "${!osInfo[@]}"
do
if [[ -f $f ]];then
sudo ${osInfo[$f]} install "$PKG_NAME"
fi
done
fi
}
# Function: create snapshot of attached EBS and get SnapShotId
create_source_snapshot () {
aws ec2 create-snapshot --region "$SOURCE_REGION" --volume-id "$VOLUME_LIST" --description "$TIMESTAMP Jenkins Docker home temporary snapshot" > "$ORIG_SNAPSHOT"
ORIG_ID=$(jq -r '.SnapshotId' "$ORIG_SNAPSHOT")
COPY_SNAPSHOT="$TIMESTAMP-$ORIG_ID.json"
# check snapshot status
ORIG_PROGRESS=$(aws --region "$SOURCE_REGION" ec2 describe-snapshots --snapshot-id "$ORIG_ID" | jq -r '.Snapshots[].Progress')
while [[ "$ORIG_PROGRESS" != "100%" ]]; do
sleep 20
ORIG_PROGRESS=$(aws --region "$SOURCE_REGION" ec2 describe-snapshots --snapshot-id "$ORIG_ID" | jq -r '.Snapshots[].Progress')
done
}
# Function: copy snapshot to another region for fault tolerance
copy_source_snapshot () {
aws --region "$DESTINATION_REGION" ec2 copy-snapshot --source-region "$SOURCE_REGION" --source-snapshot-id "$ORIG_ID" --description "$TIMESTAMP Jenkins Docker home directories" > "$COPY_SNAPSHOT"
COPY_ID=$(jq -r '.SnapshotId' "$COPY_SNAPSHOT")
# check snapshot copy status
COPY_PROGRESS=$(aws --region "$DESTINATION_REGION" ec2 describe-snapshots --snapshot-id "$COPY_ID" | jq -r '.Snapshots[].Progress')
while [[ "$COPY_PROGRESS" != "100%" ]]; do
sleep 60
COPY_PROGRESS=$(aws --region "$DESTINATION_REGION" ec2 describe-snapshots --snapshot-id "$COPY_ID" | jq -r '.Snapshots[].Progress')
done
# add tags to the resulting snapshot
aws ec2 create-tags --region "$DESTINATION_REGION" --resource "$COPY_ID" --tags Key=$TAG_NAME,Value=$TAG_VALUE
}
# Function: cleanup and delete snapshots older than $RETENTION_DAYS
cleanup () {
# remove source snapshot & json files
aws ec2 delete-snapshot --region "$SOURCE_REGION" --snapshot-id "$ORIG_ID"
rm -rf "$ORIG_SNAPSHOT" "$COPY_SNAPSHOT"
# remove snapshots in $DESTINATION_REGION older than $RETENTION_DAYS
SNAPSHOT_LIST=$(aws ec2 describe-snapshots --region "$DESTINATION_REGION" --filters Name=tag-key,Values="$TAG_NAME" Name=tag-value,Values="$TAG_VALUE" --query 'Snapshots[*].{ID:SnapshotId}' --output=text)
for SNAPSHOT in ${SNAPSHOT_LIST[@]}; do
# Check age of snapshot
SNAPSHOT_DATE=$(aws ec2 describe-snapshots --region "$DESTINATION_REGION" --snapshot-ids "$SNAPSHOT" --query 'Snapshots[].StartTime' --output=text | awk -F "T" '{printf "%s\n", $1}')
SNAPSHOT_DATE_IN_SECONDS=$(date "--date=$SNAPSHOT_DATE" +%s)
if (( $SNAPSHOT_DATE_IN_SECONDS <= $RETENTION_DATE_IN_SECONDS )); then
aws ec2 delete-snapshot --region "$DESTINATION_REGION" --snapshot-id "$SNAPSHOT"
fi
done
}
## SCRIPT COMMANDS ##
package_to_install
create_source_snapshot
copy_source_snapshot
cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment