タイトル

Need for Answer

2014年3月13日木曜日

AWS EC2バックアップを定期的に取得する方法(awscli+jq版)

AWS EC2のストレージ信頼度は高いです。が、人為ミスによるコンテンツ紛失はどうにもなりません。…EC2をバックアップしたいという需要はクラウドでも一緒ですね。

先人の作り上げたShellScriptをawscli+jqで移植しよう!というお話です。STOP!車輪の再発明!

長いので使い方を先に説明しますと、『all_createsnapshot.sh』をどこかのEC2で実行すると、タグ付けられたEC2-Instanceを全部バックアップします!cronに登録しておくと良いと思います!

前置き終了以下解説。

awscli』と『jq』のインストールが必須です。
jqはパスの通った所に置いて下さい。

まずはShellScriptから説明します。

2つのShellScriptは同一ディレクトリに設置して下さい。awscliの設定ファイル設置場所をハードコードしておりますので、各自ご修正ください。

2つのShellScriptの役割はこんな感じです。
  • all_createsnapshot.sh ⇒ バックアップ対象のEC2のInstance-IDをリスト化
  • createsnapshot.sh ⇒ Instanse-IDを渡すとSnapshotを取得。過去分は削除。
ログは『標準出力』『/var/log/message』の2つに出力されます。

ShellScriptはパラメータを渡して実行する事ができます。
通常は自動取得されますので、設定の必要は無いです。

all_createsnapshot.sh
パラメータ 内容 未指定時
-h ヘルプを表示 表示しない
-c AWS_CONFIG_FILEの場所を指定
(外部から引き渡すときに使用)
Shell内設定を使用

createsnapshot.sh
パラメータ 内容 未指定時
-h ヘルプを表示 表示しない
-c AWS_CONFIG_FILEの場所を指定
(外部から引き渡すときに使用)
Shell内設定を使用
-i SnapShotを取得したいInstanceID 実行中のインスタンス
-g SnapShotを保存する世代数 5

#!/bin/bash
#
# All Instances CreateSnapshot script

CONFIG_FILE=/root/aws/account.txt

opterror(){
    echo "Usage: $prog -c [config]" 1>&2
    echo "             -h HELP"
    exit 1
}

while getopts c:h OPT
do
  case $OPT in
    "h" ) HELP=1 ;;
    "c" ) CONFIG="$OPTARG" ;;
      * ) opterror
  esac
done

# TimeWatch Start ----------------------------
START_TIME=`date +%s`
TMPTXT="$0 Start EC2 SnapShot JOB..."
echo "${TMPTXT}" && logger -t $0 -i "${TMPTXT}"

# Exec ---------------------------------------
test ! -z $HELP   && opterror
test ! -z $CONFIG && CONFIG_FILE=${CONFIG}

export AWS_CONFIG_FILE=${CONFIG_FILE}
script_dir=$(cd $(dirname $BASH_SOURCE); pwd)

# Exec Failed Check --------------------------
test -z ${AWS_CONFIG_FILE} && echo "Not Set AWS_CONFIG_FILE ..." && exit 1
test ! -f ${script_dir}/createsnapshot.sh && echo "Not Find createsnapshot.sh ..." && exit 1

# Loop Tagged Instances
aws ec2 describe-instances --filters "Name=tag-key,Values=backup" "Name=tag-value,Values=ON"|jq -r ".Reservations[].Instances[].InstanceId"| while read INSTANCE_ID
do
    GENERATION=`aws ec2 describe-instances --instance-id=${INSTANCE_ID} |jq -r '.Reservations[].Instances[].Tags[]|select(.Key== "generation").Value'`
    test -z ${GENERATION} && GENERATION=5

    TMPTXT="Backup INSTANCE is ${INSTANCE_ID} and Generation is ${GENERATION}"
    echo "${TMPTXT}" && logger -t $0 -i "${TMPTXT}"

    if [ ! -z $CONFIG ];then
        ${script_dir}/createsnapshot.sh -i ${INSTANCE_ID} -g ${GENERATION} -c $CONFIG
    else
        ${script_dir}/createsnapshot.sh -i ${INSTANCE_ID} -g ${GENERATION}
    fi
done

# TimeWatch STOP -----------------------------
END_TIME=`date +%s`

SS=`expr ${END_TIME} - ${START_TIME}`

HH=`expr ${SS} / 3600`
SS=`expr ${SS} % 3600`
MM=`expr ${SS} / 60`
SS=`expr ${SS} % 60`

TMPTXT="$0 exec Total Time => ${HH}:${MM}:${SS}"
echo "${TMPTXT}" && logger -t $0 -i "${TMPTXT}"

#!/bin/bash
#
# CreateSnapshot script
# using awswcli + jq

CONFIG_FILE=/root/aws/account.txt
export LANG=C

#=====================================================
opterror(){
    echo "Usage: $0 -i [instance_id] -g [backup generation] -c [config]" 1>&2
    echo "          -h HELP"
    echo "          if Not Defined instance_id, take Backup Myself."
    exit 1
}

while getopts i:g:c:h OPT
do
  case $OPT in
    "h" ) HELP=1 ;;
    "i" ) EC2_INSTANCE_ID="$OPTARG" ;;
    "g" ) EBS_GENERATION_COUNT="$OPTARG" ;;
    "c" ) CONFIG_FILE="$OPTARG" ;;
      * ) opterror
  esac
done

#------------------------------------------------------
test ! -z $HELP && opterror
test ! -z $CONFIG && CONFIG_FILE=${CONFIG}

export AWS_CONFIG_FILE=${CONFIG_FILE}

test -z $EC2_INSTANCE_ID && EC2_INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
test -z $EBS_GENERATION_COUNT && EBS_GENERATION_COUNT=5
#======================================================

EBS_VOLUME_ID=`aws ec2 describe-volumes|jq --arg hoge ${EC2_INSTANCE_ID} -r '.Volumes[]|select(.Attachments[].InstanceId ==$hoge)|.VolumeId'`

# Create SnapShot --------------------
NOW=`date +"%Y/%m/%d %k:%M:%S"`
DESCRIPT_TXT="AutoBackup ${EC2_INSTANCE_ID} created at ${NOW}"
aws ec2 create-snapshot --volume-id ${EBS_VOLUME_ID} --description "${DESCRIPT_TXT}" >/dev/null 2>&1

# Error Catch ------------------------
RESULT=$?
TMPTXT="${EC2_INSTANCE_ID} create snapshot ${EBS_VOLUME_ID} "

if [ ${RESULT} -ne 0 ];then
  TMPTXT="${TMPTXT} => failed..."
else
  TMPTXT="${TMPTXT} => Success!!"
fi

echo "${TMPTXT}" && logger -t $0 -i "${TMPTXT}"

# List & Sort Delete SnapShots -------
SNAPSHOTS=(`aws ec2 describe-snapshots |jq --arg hoge ${EBS_VOLUME_ID} -c '.Snapshots[] | select(.VolumeId==$hoge) | [ .StartTime, .SnapshotId, .Description ]'| grep "AutoBackup" |sort -t "," -k 1,1| awk -F'[,"]' '{print $5}'`)
SNAPSHOTS_LINE=${#SNAPSHOTS[*]}

CNT=`expr ${SNAPSHOTS_LINE} - ${EBS_GENERATION_COUNT}`

# Exit -------------------------------
if [ ${CNT} -lt 0 ];then
  exit 0
fi

# Delete OLD SnapShot ----------------
for ((i = 0; i < ${CNT}; i++)){
  aws ec2 delete-snapshot --snapshot-id ${SNAPSHOTS[i]} >/dev/null 2>&1

  RESULT=$?
  TMPTXT="${SNAPSHOTS[i]} delete"

  if [ ${RESULT} -ne 0 ];then
    TMPTXT="${TMPTXT} => failed..."
  else
    TMPTXT="${TMPTXT} => Success!!"
  fi

  echo "${TMPTXT}" && logger -t $0 -i "${TMPTXT}"
}

次に、実際の使用方法を説明します。

バックアップ取得対象のEC2にTagを付けます。「Key:backup Value:ON」のものをバックアップ対象とします。「Key:generation Value:[任意の数値]」をつけると、その世代分以降のバックアップは削除されます。未指定時は5世代です。


あとはどこかのEC2で『all_createsnapshot.sh』を実行すれば、タグ付けされたEC2のSnapShotが取得されます。

なおバックアップ削除は『Descriptionに「AutoBackup」という文字列が含まれている物のみ』対象にします。手動取得したSnapshotsが勝手に消去されることは無いのでご安心下さい。

参照元:
【AWS】クラウド時代のバックアップ管理術  ~tagを活用したsnapshotの世代管理~
Amazon EBSのスナップショット(バックアップ)を取得しつつ世代管理も行うスクリプト



0 件のコメント:

コメントを投稿