ちょっと話題の記事

EC2複数台構成時の構築とデプロイ

2015.06.30

高可用性・高負荷対応のWebシステムをAWSで構築する場合、ELB配下に2台以上のEC2インスタンスを配置する構成が鉄板です。こういった構成の場合、各EC2インスタンスは同等の挙動をすることが期待されます。各インスタンスにデプロイされているアプリケーションの挙動に差異があると予期せぬ問題を引き起こすことは想像に難くないでしょう。

AWS_Design_Web_-_Cacoo

今回は、ELB構成のWebシステムを構築する場合の、EC2インスタンスの管理やデプロイなどのポイントを紹介します。

ベースインスタンスの作成

プロダクション環境のインスタンスは複数となるため、1台1台をセットアップしては効率がよくありません。AMIを作成することで、EC2インスタンスは簡単に複製できるため、ベースとなるインスタンスを1つ構築して複製すると、効率良く構築することができます。

それ以外のベースインスタンスに関するトピックを紹介しましょう。

ステージング環境として利用する

ベースインスタンスはステージング環境として利用することもできます。不要な場合は停止しておくことで余分な費用も抑えることができるでしょう。

ミドルウェアアップデートに利用する

ミドルウェアのアップデートなどはベースインスタンスに対して行い、動作検証してからプロダクション用のインスタンスと差し替える運用とすると良いでしょう。

なお、ベースインスタンスは開発用に使うのは避けた方が無難です。開発用のインスタンスは実験的に様々なミドルウェアをインストールすることが多くなります。余分なミドルウェアがインストールされていると管理しにくくなります。開発用のインスタンスでノウハウを蓄積した後にベースインスタンスに適用する方が合理的です。 バックアップや複製が簡単だからこそできる手法です。

ベースインスタンスはReboot時に動作可能な状態とする

Apacheなどのサービスは、ベースインスタンスの起動時に自動起動するように設定しておき、起動するだけでシステムが利用できるように設定します。 システムの起動に全プロダクション用インスタンスにログインしなければならないとしたならば、インスタンス数が増えた場合に大きな手間となるからです。Reboot(Lunch)時にシステムが動作可能な状態となることは、Auto Scalingを利用する場合は、必須要件となります。

Tomcatなどバイナリインストール可能なミドルウェアでも、なるべくパッケージインストール(yum)を利用し、サービスとして登録する方が構築の手間は少なくなるでしょう。

固定Private IPを避ける

特別な理由が無い限りは、固定Private IPは避けるべきです。 もし、ELB配下のインスタンスに固定IPを割り当てた場合、2つ目以降のインスタンスはIPアドレスが重複してしまい起動に失敗します。起動後にIPアドレスを変更して・・・と手間が増えてしまいます。固定IPに依存しないようにシステムを構築してください。

Public IPは動的に割り当てる

各インスタンスにPublic IPがない場合、SSHによるログインは踏み台サーバ経由となります。Public IP必要ならばEIPを割り当てることができますが、各AWSアカウントで保持できるEIPに上限があることも注意してください。 EIP上限は申請により緩和することができますが、Public IPの自動的に割当てに設定しておくのがオススメです。EIPと違い、インスタンスの起動時にPublicIPが変更されてしまいますが、インスタンス停止中に余分な課金が発生することもありません。

ログをCloudWatch logsで回収する

複数台構成とした場合、各インスタンスのログをそれぞれ管理するのは非常に面倒です。ログをどの程度まで保持したいかにもよりますが、AWSのCloudWatch Logsを利用するとほとんどの場合にシアワセになれます。

CloudWatch Logsでは各EC2インスタンスにエージェントをインストールし、定期的にログを送信する仕組みを提供します。CloudWatchに送信されたログは管理コンソールから簡単に検索し、必要に応じてアラートメールを送信する事ができます。ログの反映まで若干の遅延があることや、サーバがダウンした場合などに欠損するログなどが出る可能性がありますが、Fluentdなどの専用サービスを構築するほどではない場合は、簡単に設定できるのが魅力です。

プロダクション環境へのデプロイ

ベースインスタンスを作成すると、そのインスタンスのAMIからインスタンスを複製することでELB配下に複数のインスタンスを配置しやすくなります。ですが、ちょっとした修正を行いたい場合や、リリース直後の頻繁にアップデートが必要な場合には、都度AMIを作成するのは面倒です。

プロダクション環境の各EC2インスタンスにソースコードをデプロイする場合、デプロイ用のサーバを1台用意すると便利です。踏み代用サーバと兼務しても構いませんし、JenkinsなどのCIサーバと同居しても良いでしょう。 デプロイサーバから各EC2インスタンスにソースコードをデプロイする方法として、大きくふたつのやり方があります。

各インスタンスにソースコードをデプロイする

稼働中の全インスタンスにソースコードをデプロイします。 デプロイにはCapstranoといったツールを利用しても構いませんし、シンプルにrsyncを利用するのも良いでしょう。問題となるのは各サーバのPrivate IPをどのように扱うかです。

Untitled_Web_-_Cacoo

台数が少ないのであれば、管理コンソールなどで確認して、設定ファイルを変更しても良いでしょう。動的に取得したい場合は、EC2インスタンスにタグを付与することで、awscliなどを使ってインスタンスのIPアドレスを取得できます。

例えば、次のスクリプトは、タグに「Role=Web」「Environment=Production」が設定されているEC2インスタンスのPrivate IPを取得し処理を実行するシェルスクリプトです。

ipAddresses=$(aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" "Name=tag:Role,Values=web" "Name=tag:Environment,Values=Production" | jq -r '.Reservations[].Instances[].PrivateIpAddress')

for ip in $ipAddresses; do
if [ $ip != "null" ]; then
echo "$ip"
fi
done

ただし、本番環境を稼動したまま、各インスタンスにソースコードをデプロイする場合は、デプロイ途中の中途半端な状態にユーザがアクセスする可能性が残る点は注意してください。ウェブページの見た目に関する修正などの場合は、オススメです。

ベースインスタンスにデプロイし、インスタンスを再構築する

プロダクション用のインスタンスに直接デプロイするのでは無く、ステージング環境用のインスタンスなどにデプロイを行います。 デプロイされたそのインスタンスを使って本番環境のインスタンスを差し替えます。ステージング環境用のベースインスタンスで動作確認を行える事もメリットです。デプロイと動作確認ができたならば、AMIを作成します。

Untitled_Web_-_Cacoo

AMIを作成したならば、新しいインスタンス群を起動してください。最後にELB配下のインスタンスを新しいインスタンスに差し替えます。

この方法のメリットは、リリース後に問題が発生した場合にリリース前のインスタンスに戻すのが簡単である点です。簡易版Blue-Greenデプロイメントと言えるでしょう。

まとめ

AWS環境ではインスタンスの作成や複製が容易である特性を利用し、ベースインスタンスを使った開発やデプロイ手法が有効と言えます。 しかしながら、ELB配下にインスタンスを配置するような場合は、固定IPを避けるなどの点に注意しなければなりません。

また、実際に開発と構築、そして運用をしていくために、はじめにデプロイ手順を整備しておくことが大切です。システムに問題が発覚した場合でも、元の状態に戻せるBlue-Greenデプロイメントを採用したり、軽微な修正は簡単に全インスタンスに適用できるように準備したりすると良いでしょう。 AWS環境であれば簡単ですね。