Screaming Loud

日々是精進

EC2の起動時にEBSを紐付ける設定

EC2の起動時にEBSを紐付ける設定をするのに割と手間取ったのでメモ

利用するのは、起動テンプレートのユーザーデータです。

ユーザーデータに関してはこちら。

docs.aws.amazon.com

設定

今回はECSのインスタンスに対してdockerコンテナが立ち上がる前にebsをマウントさせたいため、cloud-boothookにその設定を書きます。

以下はcloud-boothookに関する引用です。

cloud-boothook ユーザーデータ形式は、起動プロセスでユーザーデータシェルスクリプトよりも前に実行されます cloud-boothook ユーザーデータは、インスタンス起動のたびに実行されるため、ブートフックが複数回実行されることを防ぐためのメカニズムを作成する必要があります。

docs.aws.amazon.com

実際に書くユーザーデータは以下

Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0

--==BOUNDARY==
Content-Type: text/cloud-boothook; charset="us-ascii"

# Create /mnt/ebs folder
cloud-init-per once mkdir_ebs mkdir -p /mnt/ebs

#cloud-boothook
#!/bin/sh
# Install awscli
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" \
  && python get-pip.py
pip install awscli

aws configure set region ap-northeast-1

# Install JQ JSON parser
yum install -y jq

# Find Volumes
INSTANCE_AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
VOLUME_ID=`aws ec2 describe-volumes --filters Name=status,Values=available  Name=availability-zone,Values=$INSTANCE_AZ | jq -r '.Volumes[] |.VolumeId' | head -n 1` 2>&1 >> /tmp/cloud-boot.log
echo "volumeID: ${VOLUME_ID}" 2>&1 >> /tmp/cloud-boot.log

## Attach Volumes
if [ "${VOLUME_ID}" != "" ]; then
  aws ec2 attach-volume  --volume-id $VOLUME_ID --instance-id $INSTANCE_ID --device  /dev/xvde 2>&1 >> /tmp/cloud-boot.log
  COUNT=0
  while [ ! -e /dev/xvde ] && [ $COUNT -le 4 ]; do
    echo "Waiting for disk to appear.. /dev/xvde" 2>&1 >> /tmp/cloud-boot.log
    sleep 1
    COUNT=$(($COUNT + 1))
  done
  mkfs -t ext4 /dev/xvde 2>&1 >> /tmp/cloud-boot.log
  echo -e '/dev/xvde /mnt/ebs ext4 defaults,user 0 2' >> /etc/fstab
fi

mount -a

chmod -R 775  /mnt/ebs

--==BOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

# Set any ECS agent configuration options
echo ECS_ENABLE_CONTAINER_METADATA=true >> /etc/ecs/ecs.config
echo ECS_CONTAINER_STOP_TIMEOUT=2m >> /etc/ecs/ecs.config
echo "ECS_CLUSTER=my-ecs-cluster" >> /etc/ecs/ecs.config

--==BOUNDARY==--

軽く解説

BOUNDARYでcloud-boothookとshellscriptを分けています。

#!/bin/sh と書くとそれ以降shellscriptが使えます。

ebsをマウントするにはawsコマンドを入れる必要があるので、pipで入れます。 入れたawsコマンドで必要なregion設定を行い、実際の余っているebsを使います。

ebsの検索時にAZを指定しないとマウントできないのが割とハマりどころでした。 EBSのAZはあまり意識しないので忘れがちです。

余ってるVolumeがありVolumeIDが取得できたらマウントします。

マウント出来たかどうかを見るために、sleepで確認します。

あとはECSで使う設定です。

注意

cloud-boothook内で yum update をしてはいけません。 ecs-agentがyumで管理されているため、boothook内でyumを上げると、ecs-agentも勝手に上がるようになってしまいます。

まとめ

AZ以外に個人的にハマったポイントは cloud-init per once でずっとawsコマンドのインストールをしており、インストール出来ていなかったという点です。 全部 cloud-init per always に全部書いてもいいですが、cloud-boothook上のshellで普通に書いたほうが結果的には楽でした。