AWS
ElasticBeanstalk
シェルスクリプト

Elastic Beanstalkを自分の思うように拡張していく上では、.ebextensionsを調整することが欠かせませんが、書き方を間違えれば正常に動作しない、あるいは反映効率が低下する、というような問題を生じることがあります。

.ebextensionsという黒魔術

Elastic BeanstalkはAWSのEC2で動いていますが、.ebextensionsというかたちで設定ファイルを書けば、EC2で可能なことをなんでもできるようになります。逆を返せば、不適切な設定をしてしまうと環境がめちゃくちゃになる、ということです。

重要になる「冪等性」

こういった環境構築系のツールに共通する話ですが、Elastic Beanstalkは2回目以降の反映の際にもEC2はそのまま流用します。そのため、

  • 最初の環境構築…ベースになるEC2の上にアプリケーションごとの設定を実行して反映させていく
  • 2回目以降…すでにある環境に対して、設定をさらに反映していく

という違いがあります。.ebextensionsを書く場合には、どちらで実行しても問題なく実行されるような、冪等性が要求されます。

特に気にしなくていい例

02-yum.config
packages:
  yum:
    git: []

パッケージマネージャでインストールを行う場合、パッケージマネージャそのものが冪等性を保ってくれる(2回インストールしても2回目は何もしないだけになる)ので、特に考慮の必要はありません。データベースのシードなども、メカニズムの時点で冪等なものを使えばいいでしょう。

01-time.config
commands:
  01-cp-zoneinfo:
    command: cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

上記はタイムゾーン設定のために入れてありますが、ファイルコピーでの上書きを複数回行っても、(少々無駄ではありますが)実行される内容に問題はないので、そのまま毎回実行させています。

要注意な場合

設定ファイルを書き換えるような場合、複数回実行するとうまく動かなくなります。「すでに書き換わっているかどうかチェックする」「実行済みのフラグをどこかに記録しておく」などの方法で、複数回の実行を回避するようにしましょう。

97-redis.config
commands:
  create_post_dir:
    command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
    ignoreErrors: true
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/97_conf_redis.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      if grep -E '^unix' /etc/redis.conf >/dev/null; then
        exit
      fi
      sudo sed -i -e 's/^save /#save /g' /etc/redis.conf
      sudo sed -i -e 's/^# unix.*$ //g' /etc/redis.conf
      echo 'unixsocket /tmp/redis.sock' | sudo tee -a /etc/redis.conf >/dev/null
      echo 'unixsocketperm 777' | sudo tee -a /etc/redis.conf >/dev/null
      sudo chkconfig redis on
      sudo service redis restart

ここでは、RedisのUnixソケットを入れて、保存を無効化するように/etc/redis.confを書き換えていますが1ifですでに書き換わっている場合には脱出しています。

気にしなくても動くけど

「リモートからファイルをダウンロードして配置する」ようなものを動かす場合、そのまま何回やっても冪等性という観点では問題ありません。ただ、巨大なファイルで毎回ダウンロードを行えば、回線や時間といったリソースの無駄ですので、「すでにダウンロード済みの場合は処理を飛ばす」ような措置をしておくと、効率化できます。

アップデート時の注意

.ebextensionsを書き換えてアップデートしていくと、古いサーバには前の設定が残ったままとなります。そのため、あるだけで設定すると必要なものが抜けていてうまく動かない、という危険もありますので、ときどきは環境全体を再構築して問題がないか確認しておいたほうがいいかもしれません。


  1. なお、この環境は1インスタンスで動かしているので、EB管理のEC2の内部にRedisを立てています。