Blue/Greenデプロイとは?
SA岩永です。クラウド時代になり、Blue/Greenデプロイと呼ばれる方式を取るシステムが増えてきました。ただ、日本語で書かれているBlue/Greenデプロイの情報は多少古いものが多いため、特にクラウドで真価を発揮するBlue/Greenデプロイについて2015年の最後に一度まとめてみたいと思います。
以下は私の個人的な考えに基づくものであり、他にも様々な考え方があります。AWSのデプロイに関する発表でも沢山の考え方が提案されていますし、デプロイをサポートするサービスを多種多様に提供しています。1つの考え方として参考にして頂ければ幸いです。
なおこの記事は、2015年のAWS re:Inventのセッション『(DVO401) Deep Dive into Blue/Green Deployments on AWS』を参考にしています。興味のある方はSlideshareやYoutubeをご覧になることをオススメします。
デプロイに関連する用語の整理
デプロイとは、必要なアプリケーションのリビジョンを所望の環境に反映し、特にWEBサービスであればリクエストを受け付けるようにすることを指します。これを実現する方法として、大きく以下の2つの方法があります。
- In place: インスタンスはそのままに、新しいリビジョンのアプリのみをその場で反映させる
- Blue/Green: 新しいリビジョンのアプリ用に、新しいインスタンスを構築して入れ替える
そして、実現方法とは別の軸で、反映のスピードで大まかに以下の3つの分類ができます。
- All at once: 全台を一斉に新しいリビジョンでデプロイする
- One by one: 1台ずつ新しいリビジョンをデプロイする
- Batch: 数台(例えば半数)ずつ新しいリビジョンをデプロイする
よくBlue/Greenデプロイを「新しいリビジョンのインスタンスを、今と同じ台数構築して一気に切り替える」というやり方のみで考えている方がいますが、昨今そういったデプロイ方式はRed/Blackデプロイとも呼ばれています。これは「Blue/GreenでAll at onceにデプロイする」という1つのやり方に過ぎません。
また、その他のトピックとして以下の様なものがあります。
- Rollback: デプロイしたリビジョンに問題があった時に、以前のリビジョンに切り戻すこと
- Canary: 1台だけ新しいリビジョンをデプロイして、問題がないかを先に確認すること
In place
では2つの実現方法のメリット・デメリットを見ていきましょう。
メリット
この方式はデプロイ時に追加のインスタンスが必要ないので、オンプレミス環境などインスタンスの作成が容易ではない環境では非常に効果的です。ハードウェアの購入からOSインストールや各種設定が既に終わっているインスタンスに対して、アプリのみを配布し再起動などの操作を行うだけで済むので、高速で追加のインスタンスコストがかかりません。
この方式の典型的な例が、CapistranoやFabricといったデプロイツールになります。これらのツールはssh等を用いて配布元から各インスタンスに接続して、アプリの配布から各種コマンド発行を行います。おそらく、多くのWEBシステムがこうしたツールや自作のツールを使ってIn placeなデプロイをしていることが多いと思います。sshさえ通っていればすぐにデプロイをすることができ、またsshでできることは基本的になんでもできるので柔軟性も高く、人気の高い方式となっています。
また、インスタンス内部でソケットを共有しながら新旧のアプリを徐々に切り替えていくところまで作り込むと、サービスアウトしてからデプロイするということも必要なくなり、ゼロダウンタイムでのデプロイも実現できます(その分構成は多少複雑にはなってしまいます)。
デメリット
この方式の大きなデメリットは3つ考えられます。
1つはリモート操作が必要である点です。リモート操作とはsshなどの方法で稼働中のインスタンスに対して操作をすることです。sshを使う場合には鍵の管理が必要となり、そのためにインスタンスの構築が多少複雑になってしまいますし、そもそも本番環境で利用しているインスタンスに対してssh等の穴を開けるリスクはなるべく減らした方が安全です。これに対しては、AWS CodeDeployの様なエージェント型の仕組みを利用することで多少軽減はできますが、ファイルの配布や任意のコマンド実行を稼働中に行うリスクは変わりません(サービスアウトしてから行えばリスクは下がりますが、その分デプロイ速度や無駄なコストが発生します)。
それ以上に大きな問題となるのがインスタンス内部の一貫性の崩れです。In placeでは一度作成したインスタンスに対して、変更を積み重ねていくことになりますが、その後新しいインスタンスを追加することになった時に全く同じ状況を再現するのは限りなく難しくなります。特にコードを配布した後にライブラリのインストール(例: bundle install)などを各インスタンスで行っている場合はインストールに伴う成果物が全インスタンスで同じものであることを保証するのは困難です。基本構成完了後に最新リビジョンのみをデプロイしたインスタンスと、何百回もデプロイを受け稼働し続けているインスタンスで全く同じ構成を作りだすのは、現実的には厳しいです。場合によっては緊急作業によって手作業で施された変更が残ってしまっていたりして、思いもよらぬ差分を産んでしまうことがあります。
最後にRollbackが困難であることも挙げられます。一度変更を加えてしまったものを戻す時、一貫性はより崩れやすくなります。Capistranoではデプロイ毎にディレクトリを切って、symlinkを貼り替えることでデプロイとRollbackを簡単にしていますが、アプリ以外の依存関係の更新(例えばCのライブラリ更新)があった時にはそれでは対応できません。また、古いデプロイを掃除しないとディスク容量も圧迫してきます。
つまり、In placeの場合「アプリのデプロイ」と「アプリ以下のデプロイ」という2種類のデプロイをメンテしなければならないという事実があります。
Blue/Green
こうした課題はほとんどのシステムが直面したことがあるものであり、なんとかしてもっと安定・高速・簡素なデプロイを行いという思いから生まれて来たのがBlue/Greenになります。
序盤にも書いた様に、Blue/Greenは必ずしもBlueとGreenで同じ規模を事前に準備してから切り替えるだけのものではありません。ポイントは、稼働中のBlueに対しては何もせず、別のインスタンスで新しいリビジョンのGreenを作って、任意の戦略に沿って全体をGreenに切り替えていく(Blueはいずれ廃棄する)ということです。
メリット
上記のIn placeのデメリットを全て解消できます。まずリモート操作については、デプロイ時に稼働中のインスタンスには一切変更を加えないので、何も必要ありません。デプロイに関する仕組みをインスタンスは何も持たなくて良いのです。このことはアプリケーション開発プロセスも簡素化してくれます。
一貫性については、極端な作り方としてデプロイ毎にインスタンスのイメージ(Amazon EC2ならAmazon Machine Image(AMI))を作成しておけば、同じリビジョンのインスタンスは全く同じ構成であることが保証できます。なおこれはNetflixが取っている方式です。
Rollbackは非常に容易です。なぜならBlueにはデプロイで何の変更も加えられていないので、単純にトラフィックをBlueに戻すだけで良いです。もしBlueを廃棄した後でも、過去のリビジョンのAMIから再度起動させれば復元も簡単です。
この様に、Blue/Greenではデプロイは「アプリのデプロイ」で下回りのデプロイも一緒に行われるため、例えばOSのアップデート等も全く同じ仕組みで実現することができ、デプロイプロセスは1つになりメンテも格段に楽になります。
デメリット
もちろん、いいことだらけではありません。例えば、デプロイ毎にAMIを作るのはコストが高いと言われます。特にちょっとした修正をデプロイする時にAMIから作り直しになり時間がかかります。これは、AMIの作成を自動化してデプロイ時にはすでに準備ができているようなCI/CDパイプラインを構成することである程度回避はできます。デプロイ毎にAMIを作るのではなく、基本構成のAMIは固定にしておいてインスタンス起動時に最新リビジョンを取得する形にしても良いですが、その場合にはIn placeと同様の一貫性の崩れが起こり得るので注意が必要となります。
また典型的に言われるのが、インスタンスを余分に作らなければいけないコストが無駄という点です。ちょっとした修正をしたいのにわざわざインスタンスを立てなければいけない、All at onceをしようとすると2倍のコストが一時的にかかる、などは確かに無駄です。ただし、これらはクラウドを利用することで大きなリスクにはならなくなりました。一時的に必要なリソースに対して、初期費用不要で従量課金であるクラウドを使っていれば、必要最低限のコストで抑えられます。
AWSでの実現方式
さて、ここからはre:Inventのセッションから、実際にAWSでBlue/Greenを実現するいくつかの方式を見てみましょう。より詳細はセッションのSlideshareやYoutubeを見て頂くと良いと思います。
まずはAmazon EC2 (EC2)をインスタンスとしてBlue/Greenする場合の方法を2種類見てみます。EC2以外には、DNSとしてAmazon Route 53 (Route 53)、ロードバランサとしてElastic Load Balancing (ELB)、EC2の自動スケールアウト/インにはAuto Scaling Group (ASG)を利用します。
Weighted DNS
まずは古典的な方式として、DNSのWeighted round robinを利用した方法です。BlueとGreenでELB, EC2, ASGのシステムを作っておき、Route 53のWeightを使って、徐々にBlueからGreenへトラフィックを寄せていけば実現できます。裏側はASGでトラフィックに応じて自動でスケールするようにしておけば、インスタンスの足し引きは自動で行われます。
この構成のメリットはとにかくシンプルであることです。Route 53のWeightの調整も、AWSのAPIやAWS CloudFormationで簡単に制御できます。一方大きなデメリットとして、DNSの仕組みに依存しているためTTLに注意する必要があり、キャッシュサーバによってはTTLを考慮せず一定期間キャッシュするものも存在するため、コントロールがしづらいという点があります。また、ELBもASGもトラフィックに応じて自動でスケールしますが、多少の時間はかかってしまうため、高速なデプロイは厳しいケースがあります。
Swap Auto Scaling Group
ではDNSに依存しない仕組みを作ってみましょう。Route 53は常に同じELBを指す様にしておき、ELBにattachするASGをコントロールすることで、Blue/Greenが実現できます。ちなみに、これは2015年の新しい機能追加によって実現可能となりました。
まず、BlueのASGが現在ELBにattachされています。デプロイ時にはその横でGreenのASGを作成し、このASGも既存のELBにattachすることで、Blue/Green両方にトラフィックが流れてきます。後は徐々にGreenを増やしながらBlueを減らしていって、最終的にBlueをdetachして削除したらデプロイ完了です。
この方式ではDNSのTTLは気にする必要はありませんし、ELBも既存のものを使えるのでスケールも気にしなくて良いです。一方でASGの付け外しやインスタンス数の調整は、API経由とはいえある程度自前で作りこむ必要はあります。
Container with Amazon ECS Service
さて、デプロイ毎にAMIを作成するという方式ですが、実はこれはそのままコンテナ技術に置き換えることができます。DockerコンテナはAMIと同じ様にイメージというものを持っているので、Blue/Greenを簡単に行うことができます。AWSではDockerコンテナをEC2で構成したクラスタ上の任意の場所にTaskという形で起動する管理サービスとしてAmazon EC2 Container Service (ECS)があります。ECSにあるServiceスケジューラというWEBサービス向けのスケジューラ(どこにどのコンテナをいつ起動するかを制御)を使うと、完全マネージドでBlue/Greenできるので、最後にそれを見てみましょう。
ServiceスケジューラのオプションでELB連携を有効にしておき、BlueとしてあるリビジョンのDockerイメージから起動したコンテナ群(正確にはTask群)があります。これらはServiceスケジューラによって自動的に配置され、ELBに登録されています。次に、新しいリビジョンでDockerイメージを作成し、それを使ったTask Definition(Taskの設計書)でServiceをアップデートするリクエストを送ります。後は、Serviceスケジューラ側でGreenを起動しながらBlueを停止していき、ELBとの連携までやってくれるので、しばらくするとGreen系に切り替わっています。
この方式では、Blue/Greenをどのような割合で遷移させるかをいちいち指定する必要はなく、単に新しいイメージを指定するだけであとは完全にAWSが管理しながらデプロイしてくれます。またつい最近のアップデートにより、このデプロイ時のキャパシティのコントロールをより柔軟に行える様になっています。また、実際にコストとしてかかるEC2については、上述の方式とはことなりそのまま使い続けられるので、追加コストを払う必要はなくIn placeと同様のメリットを享受できます。
一方、デメリットとしてはCanaryや、デプロイ速度の調整などはできないです。またDockerへの適応が済んでいないと利用できません。
まとめ
今回はデプロイに関連する用語の整理と、In placeとBlue/Greenの特徴の紹介、そしてAWSにおけるBlue/Greenの実現方式をいくつか見てきました。デプロイ速度については今回はあまり言及していませんが、どちらかというとデプロイ方式の方が難しい話題なのでこちらをきちんと理解できれば速度についてはすぐに分かってくると思います。
In place方式で苦労されている方がいれば、ぜひ一度Blue/Greenを検討して頂けると良いと思います。一度構築できると、デプロイの仕組みとアプリケーションを疎結合にできるので、どのようなアプリケーションでも同じ様にデプロイできるようになり、特にMicroservicesといった沢山のアプリケーションで構成される様な場合には有効なやり方になってきます。
もしこの辺りの話題で、試してみたい、話を聞いてみたいなどありましたら、お気軽にお声がけください。
SA 岩永 @riywo (なおこの投稿には、後ほど画像などを付け足して、より分かりやすくする改善を加えていく予定です!)
コメント