ソースコード管理をAWS上のSubversionでおこなってます(詳しくはこちらの記事)。今まで、リポジトリのバックアップはS3と自宅ローカルストレージへ取っているのですが、EC2インスタンスのバックアップは取っていませんでした。時間ができたので、EC2インスタンスのスナップショットを自動的に取る方法を実現してみました。
なお、次のサイトを参考にさせていただきました。
やってることは、これらのサイトで紹介していただいているものとほとんど変わりません。自分のメモ用にまとめました。
インスタンスは、Ubuntu12.04.1 (BitNami Redmine) です。
自動スナップショットを取る方法
EC2のAPIツールを使って実現します。私が書いたシェルスクリプトは次のようなものです。
/etc/ec2/ec2-snapshot.sh
#!/bin/bash # # auto snapshot of EC2 instance # # written by Junichi MORI, 2013/4/11 # variables # this script doesn't use --region option, # because uses default region defined by EC2_URL variable in EC2_ENV file EC2_ENV=/etc/ec2/bash_ec2env EBS_VOL=xxxxxxxxxxxx # functions function message() { echo `date +"%F %T %Z"` : $* } function usage() { echo "Usage: ec2-snapshot.sh generation description" echo " generation : number of old backup, positive number(grater than 0)" echo " description: description of snapshot" } # argement if [ $# != 2 ] then usage exit -1 fi # argument #1 should be natural number ISNUM=`expr "$1" : '^[1-9][0-9]*$'` if [ ${ISNUM} -eq 0 ] then usage exit -1 fi SS_GENERATION=$1 SS_DESC=$2 # environment setting if [ ! -f $EC2_ENV ] then message "error: ec2 environment difinition file is missing" exit -1 fi . $EC2_ENV # auto snapshot LOGMSG=`ec2-create-snapshot --private-key ${EC2_PRIVATE_KEY} --cert ${EC2_CERT} --description "${SS_DESC}" ${EBS_VOL}` message "create: "${LOGMSG} # list of snapshots # first, get snapshots list filtered by description and volume-id. # next, sort snapshots by issued timestamp (field #5) descending order. # last, get snapshot-ids list, i.e. get only field #2. SNAPSHOTS=`ec2-describe-snapshots --private-key ${EC2_PRIVATE_KEY} --cert ${EC2_CERT} --owner self --filter description="${SS_DESC}" --filter volume-id=${EBS_VOL} | sort -k5 -r | cut -f 2` #echo ${SNAPSHOTS} # snapshot rotation COUNT=1 for SS_ID in ${SNAPSHOTS} do if [ ${COUNT} -gt ${SS_GENERATION} ] then LOGMSG=`ec2-delete-snapshot --private-key ${EC2_PRIVATE_KEY} --cert ${EC2_CERT} ${SS_ID}` message "delete: "${LOGMSG} fi COUNT=$((COUNT + 1)) done message "auto snapshot done."
EC2のコマンドラインツールのセットアップについては、こちらの記事をご参考にしてください。コマンドラインツールに必要な環境のセットアップについてもこの記事に書いています。
やってる処理内容は参考サイトとほとんど同じ処理です。異なるのは、世代管理の世代数とdescriptionを引数で渡せるようにしたところです。
一応、処理の流れを書いておくと次のようになります。
- 引数で指定されたdescriptionを与えてスナップショットを作成します。
- 次に、世代管理をおこなうためスナップショット一覧を取得し、作成時刻の降順でソートして、スナップショットidをのリストを取ります。
- これを時刻の新しいほうから数えて、世代数より多い分(古いスナップショット)は削除するというものです。
実際のバックアップでは、このスクリプト呼び出す形で、daily用とweekly用のスクリプトを作ります。
/etc/ec2/ec2-snapshot-daily.sh
#!/bin/bash # # auto snapshot of EC2 instance daily # # written by Junichi MORI, 2013/4/11 # variables SS_GENERATION=6 SS_DESC="Daily Backup" LOG=/var/log/ec2snapshot.log /etc/ec2/ec2-snapshot.sh ${SS_GENERATION} "${SS_DESC}" >> ${LOG} 2>&1
/etc/ec2/ec2-snapshot-weekly.sh
#!/bin/bash # # auto snapshot of EC2 instance weekly # # written by Junichi MORI, 2013/4/11 # variables SS_GENERATION=4 SS_DESC="Weekly Backup" LOG=/var/log/ec2snapshot.log /etc/ec2/ec2-snapshot.sh ${SS_GENERATION} "${SS_DESC}" >> ${LOG} 2>&1
それぞれのスクリプトへのシンボリックリンクを、/etc/cron.daily, /etc/cron.weekly から張ればあとは自動的に実行してくれます。
これで、スナップショットも自動で取れるようになりました。
スナップショットを別リージョンにコピーすることもできます(次の記事などが参考になります)が、それはまた必要性を考えてから試したいと思います。
2013/4/15追記
実際に、/etc/cron.daily、/etc/cron.weekly の各ディレクトリに上記スクリプトへのシンボリックリンクを張ってみたら、なぜかうまく動きません。不審に思って調べてみると、シンボリックリンクのファイル名が問題でした。
定期実行は /etc/crontab に書かれている下記コマンドで呼び出されています。
# m h dom mon dow user command 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) #
このとき、run-parts は指定されたディレクトリ内のコマンドを実行するのですが、コマンド名に使える文字が制限されています。要は ec2-snapshot-daily.sh のようにピリオドは使えませんでした。そこで、
cd /etc/cron.daily ln -s ../ec2/ec2-snapshot-daily.sh ec2-snapshot-daily
のようにしてシンボリックリンクを張れば問題なく動きました。