開発メモ#2 : AWS でのホスト / クラウドネイティブなデプロイ

開発メモ#1 : Cinnamon によるデプロイ - naoyaのはてなダイアリー に引き続き、その2です。

最近は個人で作るような小規模なものでも AWS を利用してホストしています。たとえ個人で作ったものとはいえ、利用するユーザーがいる以上はおいそれと落とすこともできない。かといって運用にあまり手間をかけたくない。その辺り、AWS で解決できる点が多い。

AWS の良いところはインフラが動的なので「後からどうとでもなる」ところ。

インスタンスの性能が足りないのであればスケールアップするでもいいし、冗長性が欲しくなったらそのタイミングで ELB (ロードバランサ) を用意すれば良い。その時、仮想化されていないハードウェアを使っていると移行のためにサーバーを再セットアップしたりアプリケーションをデプロイし直したりと手間がかかるところ、AWS ではその辺りの手間がほとんどかからない・・・というのが気に入っています。

Elastic IP を使ったノンストップなデプロイ

AWS を利用している人にとってはごくごく普通のノウハウですが、個人で作ったものでもこういう使い方があるよというのを紹介しておきます。

例えば自分がホストしているウェブアプリケーションに、少し大きめの変更を加えたいときどうするか。当然 scm でブランチを切って手元で開発してサーバーで動作を確認する。問題はその後で、実際に本番に適用したら思わぬトラブルに見舞われてしまった・・・ということは多い。

以前はわざわざテスト(ステージング環境)のためにVPSをもう一台契約するとかもコストがかかって嫌だし、仮にステージングでうまくいってもそこからさらに結局プロダクションにデプロイするときにオペミスでミスしたら意味がない・・・ということで、ちょっと後ろめたい気持ちもありつつローカルの開発が終わったところで直接プロダクションにデプロイしていました。

これは結構精神衛生上悪くって、ミスったらその瞬間から障害対応モードだし、万が一ロールバックがうまくいかなかったらと考えると嫌〜な気持ちになります。こういうのが積もり積もると、変更に対する恐れがでてきてしまってよくないですね。

で、最近はどうしているかというと、大きめの変更は

  • 既存のEC2インスタンスのコピー (スナップショット) からインスタンスを複製
  • 複製されたインスタンスをステージング環境としてアプリケーションの変更をデプロイ
  • 諸々動作確認等々をして問題なく動くことを確認
  • Elastic IP をプロダクションから、ステージングのインスタンスへと付け替え
  • 終わり

という手順でデプロイしてます。超ハッピー。

AWS には Elastic IP というサービスがあって、グローバルIPアドレスをいつでも好きな EC2 インスタンスなどに割り当てられるIPアドレスが使えます。これを使って、サービスのエンドポイントをできあがった環境に瞬時に切り替えることができる。アクセスしているエンドユーザーはその瞬間から新しい環境に接続することになります。*1

もし、実際にユーザーがアクセスして未知のトラブルに遭遇したら Elastic IP をすぐ元のインスタンスへ付け直せば良い。また、特に問題なかったら利用し終えた古いインスタンスは破棄してしまえば、コストもかかりません。

この辺りはAWSクラウドデザインパターン にある、AMIスナップショットでホストを複製するStampパターン と Elastic IP を使った動的な IP の変更である Floating IPパターンの組み合わせですね。

Floating IP パターンの解説にもある通り、この運用フローは障害対応時にも使えます。仮にインスタンスが壊れてしまった場合、スナップショットから新しいインスタンスを作って IP をそこに割り当てればよい。ELB を使うほどではないけど、コールドスタンバイでいいからある程度の耐障害性が欲しいというニーズを、メンテナンス性と同時に満たしてくれるものです。デプロイのために作っておいたスナップショットが、有事の際のバックアップにもなるというコンボです。

自分はそこまではやっていませんが一連の操作をプログラムから自動化するのももちろん可能です。

前回も紹介しましたが、この一連の作業でスナップショットを上げたり下げたりしていると public DNS が変わりまくるので ssh 先の変更などが手間。そこは ec2ssh が便利ですよ〜。capistrano や Cinnamon のような ssh ベースのデプロイツールの設定ファイルへのホスト名記述をどうするか問題も一緒に解決してくれるので一石二鳥です。

クラウドネイティブなデプロイ

昨年末の AWS re:Invent は大盛況だったようですが話題になったのが Amazonは1時間に最大1000回もデプロイする。クラウドネイティブなデプロイとはどういうものか? AWS re:Invent基調講演(Day2 AM) - Publickey にある "クラウドネイティブなデプロイ" でした。

大規模サービスのデプロイをフェーズデプロイメントなどを行うのではなく、まったく同じサーバー群の複製を作ってしまって、ロードバランサを切り替えることで一瞬で行うのが、クラウドネイティブなデプロイ。

(2012 re:Invent Day 2 Keynote: Werner Vogels - YouTube より)

先に紹介した Elastic IP を使ったデプロイの、大規模版ですね。やっていることはほとんど同じです。インスタンス群の複製はスナップショットと puppet や chef などのサーバー管理ツールを使うことで自動化することができると思います。

過去にサービスのリニューアルなど、既存システムの大規模な開発を行う際にこの辺りの移行をどうするかは常に悩みの種でしたが、インフラが動的になることでこんな富豪な解決策ができるわけですね。大規模システムのコピーを必要になったら作って要らなくなったらすぐ捨てる。全部ソフトウェアだからできる芸当です。

イノベーションってこういうことを言うんだなと思いました。

クラウド (IaaS/PaaS) の価値はコストやスケーラビリティももちろんですが、個人的には、こういうオペレーション周りの革新がより本質的ではないかなと思っています。動的で柔軟なオペレーションが変化への恐れを軽減し、回り回って試行錯誤の回数が増え、結果的にその上で動くビジネスも正解にたどり着きやすくなる。いま流行で言うリーン的ですね。

なお、しつこいようですが、Amazon Web Servicesステマではありません!

*1:細かい話ですが、アプリケーションがステートレスに作られている前提。ステートフルな接続はもちろん切れてしまいます、念のため