雑多なインフラエンジニア日記

技術ブログでっす~

EC2自動バックアップスクリプト

RDSには自動バックアップ機能がありますが、EC2には無いので、
EC2(正確にはEBS)のバックアップスクリプトbashで作ってみ
ました。

コードが少々汚い気がしますが・・・

前提

1. backupタグを作成済みであること。
2. /home/xxxx/.bash_profile に、AWSコマンド実行に必要な環境変数
設定されていること。
http://xoxo-infra.hatenablog.com/entry/2013/02/08/013002


仕様

1. backupタグが、ON になっているインスタンスのみをバックアップ取得対象と
している。
2. スクリプトの第1引数に指定されたインスタンスのEBSバックアップ&AMI作成を
する。
3. 作成したAMI、Snapshotにタグを付与する。
4. スクリプトの第2引数に指定された世代分は残す。
5. 作成されるAMI名は、「インスタンス名_yyyymmdd-HHMMSS」
6. 作成されるスナップショット名は、「インスタンス名_デバイス名_yyyymmdd-HHMMSS」
7. cron実行にて定期的にバックアップを作成することを前提にしている。
一応、手動実行も可能。


スクリプト (make-ami.sh)


・make-ami.sh インスタンス名 保存世代数 で実行する。
(ex.) make-ami.sh web01 3

 
#!/bin/bash

. /home/xxxx/.bash_profile

NODENAME=$1
GENE=$2

DATE=`date +%Y%m%d-%H%M%S`
SHELL_NAME=`basename ${0}`
LOG=/pathto/logs/${SHELL_NAME}_${NODENAME}.log

RETRY_MAXCNT=15
RETRY_WAIT_TIME=60
RETVAL=0
ARRAY_CNT=0

#set -x



#--------------------------
# Output Messages
#--------------------------
Output() {

        if [ ${RETVAL} -eq 0 ] ; then
                printf "[`date '+%Y%m%d %H:%M:%S'`] ${PROC} is Sucusess\n"
        elif [ ${RETVAL} -eq 1 ] ; then
                printf "[`date '+%Y%m%d %H:%M:%S'`] ${PROC} is Abnormal End\n"
                exit ${RETVAL}
        fi

} >> ${LOG}



#--------------------------
# Main
#--------------------------
MakeAMI() {

        PROC=ArgumentCheck
        if [ -n "${NODENAME}" ] && [ -n "${GENE}" ] ; then
                RETVAL=0
        else
                RETVAL=1
        fi
        Output
        
        
        #PROC=ServerHealthCheck
        #if ping -c 5 ${NODENAME} > /dev/null 2>&1 ; then
        #        RETVAL=0
        #else
        #        RETVAL=1
        #fi
        #Output
        
        
        PROC=MakeAMI
        INSTANCE_ID=`ec2-describe-instances -F "tag:backup=ON" -F "tag:Name=${NODENAME}" | awk '$1 == "INSTANCE" {print $2}'`
        if ec2-create-image -n ${NODENAME}_${DATE} -d "${DATE}" --no-reboot ${INSTANCE_ID} ; then
                RETVAL=0
        else
                RETVAL=1
        fi
        Output
        
        
        PROC=CheckAMI
        AMI_ID=`ec2-describe-images | grep ${NODENAME}_${DATE} | awk '{print $2}'`
        for RETRY_CNT in `seq 1 1 ${RETRY_MAXCNT}` ; do
                if ec2-describe-images ${AMI_ID} | grep available ; then
                        RETVAL=0
                        break
                else
                        if [ ${RETRY_CNT} -eq ${RETRY_MAXCNT} ] ; then
                                RETVAL=1
                        else
                                sleep ${RETRY_WAIT_TIME}
                        fi
                fi
        done
        Output
        
        
        PROC=CreateTag-AMI
        if ec2-create-tags ${AMI_ID} -t Name=${NODENAME}_${DATE} ; then
                RETVAL=0
        else
                RETVAL=1
        fi
        Output


        PROC=CreateTag-Snapshot
        SNAP_ARRAY=(`ec2-describe-images -F "tag:Name=${NODENAME}_${DATE}"| grep ^BLOCKDEVICEMAPPING | awk '{print $3"="$4}'`)
        ARRAY_MAXCNT=`expr ${#SNAP_ARRAY[@]} - 1`
        for ARRAY_CNT in `seq 0 1 ${ARRAY_MAXCNT}` ; do
                #DEVICE=`echo ${SNAP_ARRAY[${ARRAY_CNT}]/\/dev\//} | awk -F"=" '{print $1}'`
                #SNAP_ID=`echo ${SNAP_ARRAY[${ARRAY_CNT}]/\/dev\//} | awk -F"=" '{print $2}'`
                eval `echo ${SNAP_ARRAY[${ARRAY_CNT}]/\/dev\//} | awk -F"=" '{print "DEVICE="$1,"SNAP_ID="$2}'`
                
                if ec2-create-tags ${SNAP_ID} -t Name=ami_${NODENAME}_${DEVICE}_${DATE} ; then
                        RETVAL=0
                else
                        RETVAL=1
                
                fi

                if ec2-describe-snapshots ${SNAP_ID} | grep "Created by CreateImage" | grep completed ; then
                        RETVAL=0
                else
                        RETVAL=1
                fi
                Output
        done

} >> ${LOG} 2>&1



#--------------------------
# Purge AMI&Snapshot
#--------------------------
Purge() {

        PROC=PurgeAMIandSnapshot
        AMI_IDs=`ec2-describe-images | grep ^IMAGE | grep ${NODENAME} | sort -k3 | awk '{print $2}'`
        AMI_ID_CNT=`echo ${AMI_IDs} | wc -w`
        DELCNT=`expr ${AMI_ID_CNT} - ${GENE}`

        if [ ${DELCNT} -le 0 ] ; then
                RETVAL=0
        else
                for DELID in ${AMI_IDs} ; do

                        # Snapshot Info
                        DELSNAP_IDs=`ec2-describe-images ${DELID} | grep ^BLOCKDEVICEMAPPING | awk '{print $4}'`

                        # Purge AMI
                        if ec2-deregister ${DELID} ; then

                                # Purge Snapshot
                                for DELSNAP_ID in ${DELSNAP_IDs} ; do
                                        if ec2-delete-snapshot ${DELSNAP_ID} ; then
                                                RETVAL=0
                                        else
                                                RETVAL=1
                                        fi
                                done

                                DELCNT=`expr ${DELCNT} - 1`
                                if [ ${DELCNT} -eq 0 ] ; then
                                        RETVAL=0
                                        break
                                fi
                        else
                                RETVAL=1
                                break
                        fi

                done
        fi
        Output


        PROC=AMIList
        AMI_IDs=`ec2-describe-images | grep ^IMAGE | grep ${NODENAME} | sort -k3 | awk '{print $2}'`
        if ec2-describe-images ${AMI_IDs} ; then
                RETVAL=0
        else
                RETVAL=1
        fi
        Output


} >> ${LOG} 2>&1



#--------------------------
# Call Func
#--------------------------
MakeAMI
Purge
exit 0
 



50GB程度のインスタンス(EBS)なら、数分で終わりますが、500GBとかだと
6時間くらい掛かりました。。。
大きいサイズのEBSバックアップを取る場合の良いソリューションは無いの
かしら。。
初回は仕方ないか。

https://forums.aws.amazon.com/thread.jspa?threadID=123356&tstart=0