AWS EBSのリサイズをシェルスクリプトにまとめてみた

はじめに

AWSのストレージサービスならばとりあえずS3を選んでおけば間違いはないのでしょうけど,既存サービスを短期間でAWSに移行する場合にはEBSを使うことがあるかと思います.以前はEBSの容量を変更できませんでしたので,事前に余裕を持って確保するか,都度容量を割り当ててデータを移行するか悩ましいところでした.

2017年2月にAWSよりEBSの新機能について発表があり,EBSの容量やタイプ,IOPSなどがオンザフライで変更できるようになりました.そこで,EBSの空き容量が閾値を下回ったときに拡張するシェルスクリプトを用意し,定期的に実行することでお財布への負担と管理運用作業を軽くしてみました.

https://aws.amazon.com/jp/blogs/news/amazon-ebs-update-new-elastic-volumes-change-everything/

書いてみた

  • スペシャルデバイス名とEBSボリューム名(Nameタグに割り当てた文字列)を指定して実行します.
  • 使用容量が95%に達したら,80%弱になるくらいに拡張します.
  • Amazon Linuxでroot権限で実行することを前提としています.
  • 2017年4月の時点でのAmazon Linuxにプレインストールされているaws-cliではaws ec2 modify-volumeに未対応なため,アップデートが必要でした.
  • JSONのパースにjqが必要なので,事前にインストールしてください.
  • aws ec2 modify-volumeの直後にresize2fsを実行しても反映されないのでスリープを入れています.
#!/bin/sh
#
# $ sudo yum install jq
# $ sudo pip install -U awscli
# # sh ./ebs-resize.sh -d /dev/xvdf -v ebs-volume-name
#

usage() {
  echo "Usage: $0 -d device-name -v ebs-volume-name" 1>&2
  exit 1
}

while getopts d:v:h OPT
do
  case $OPT in
    'd')
      DEVICE_NAME=$OPTARG
      ;;
    'v')
      VOLUME_NAME=$OPTARG
      ;;
    'h')
      usage
      ;;
    \?)
      usage
      ;;
  esac
done

shift $((OPTIND - 1))

if test ${#DEVICE_NAME} -eq 0 -o ${#VOLUME_NAME} -eq 0; then
  usage
fi

df -k $DEVICE_NAME 1> /dev/null
if test "$?" -ne 0; then
  echo "$DEVICE_NAME is not found."
  exit 1
fi

export THRESHOLD_PERCENT=95
export EXPAND_RATE=1.25
export USED_PERCENT=`df -k $DEVICE_NAME | grep -v Filesystem | awk '{print $5}' | awk -F% '{print $1}'`
export CURRENT_SIZE=`df -k $DEVICE_NAME | grep -v Filesystem | awk '{print $2}'`
export NEW_SIZE=`echo "scale=0;$CURRENT_SIZE * $EXPAND_RATE / 1024 / 1024 + 1" | bc -l`
export AWS_DEFAULT_REGION=`curl --silent http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//g'`
export INSTANCE_ID=`curl --silent http://169.254.169.254/latest/meta-data/instance-id`
export VOLUME_ID=`aws ec2 describe-volumes --filter "Name=attachment.instance-id,Values=$INSTANCE_ID" "Name=tag:Name,Values=$VOLUME_NAME" |  jq -r '.Volumes[].VolumeId'`

if test ${#VOLUME_ID} -eq 0; then
  echo "$VOLUME_NAME is not found."
  exit 1
fi

if test $USED_PERCENT -ge $THRESHOLD_PERCENT; then
  aws ec2 modify-volume --volume-id $VOLUME_ID --size $NEW_SIZE
  sleep 30
  /sbin/resize2fs $DEVICE_NAME
fi

exit 0

おわりに

crontabに登録して1日1回程度動かすようにしましょう.なおaws ec2 modify-volumeは1度実行すると6時間は変更できないようです.ご利用は計画的に.

リンク

https://gist.github.com/stoshiya/4cafa50b34223aaa2a70c588abbede89