皆さま、こんにちは。 キャスレーコンサルティングのSI(システム・インテグレーション)部所属の青木(和)と申します。
今回、「ブルーグリーンデプロイメント」(Blue Green Deployment)というデプロイ手法を紹介させていただきます。

開発工程に占めるリリース作業の負荷は、思いの外大きいものです。
リリース準備のために手順を整備したり、事前にリハーサルを行ったり。
また、本番環境のサーバーを停止させる必要が有るなどの制約がある場合、休日や深夜にリリースする必要があります。
ブルーグリーンデプロイメントは、こうしたリリースの作業負荷を低減させることができるデプロイ手法です。

ブルーグリーンデプロイメントとは

コード変更を行うとテスト、ビルド、デプロイなど、リリース準備までの工程を自動化してくれる「継続的デリバリー」(Continuous Delivery)という考え方があります。
ブルーグリーンデプロイメントは継続的デリバリーから派生したデプロイの方法の事で、次のことを目標にします。

  • デプロイの自動化
  • サーバーのダウンタイムゼロ

クラシックなデプロイメントは既存のサーバーに対して新しい資源を配置したり設定を更新することで行われていました。
ブルーグリーンデプロイでは環境を2つ用意し、リクエストの向き先を切り替えることでデプロイを行います。
大まかな手順は以下の通りです。

①本番環境(以下、ブルー環境と呼ぶ)に対し、アップデート環境(以下、グリーン環境と呼ぶ)を新規作成する。
②グリーン環境をルータにアタッチする。
③ルータの向き先を切り替え、アプリケーションへのリクエストの向き先をブルー→グリーンに変更する。
④グリーンの動作が安定したら完了。問題が発生した場合、向き先をグリーン→ブルーに変更し、ロールバックする。
⑤次回のリリースではグリーンを本番、ブルーをテスト環境とし、①〜④の手順でリリースを実施する。

bg_xxx

検証概要

AWSを利用して検証を行いました。
検証環境の構成は以下の図に示す通りです。

BGDeploy-Architecture

図にあるenv1(ブルー環境)が既存環境で、ユーザがURLでアクセスするとAmazon Route53(DNSサーバーの役割をするAWSサービス)によってブルー環境にリクエストが振られるようにルーティングされています。
これからenv2(グリーン環境)を追加し、設定を変更することでグリーン環境に移行を行うというのが本検証の目的です。

ブルー、グリーン各環境の構成、管理には「AWS Elastic Beanstalk」というサービスを使用します。
各環境の内部は、「ロードバランサー > ターゲットグループ > EC2インスタンス」という若干複雑な構成になっています。
Elastic Beanstalkを使用することで内部の構成をあまり意識せず、環境単位で構成管理を行うことができます。
Elastic BeanstalkにはコンソールとCLI(Command Line Interface)2つの操作方法がありますが、
検証ではCLI(ver3.7.8)を使用しています。

Elastic Beanstalk(CLI)の導入方法、使用方法については公式ドキュメントをご参照ください。
AWS Elastic Beanstalk (CLI)公式ドキュメント

リクエストの向き先を切り替える方法はいくつか考えられますが、今回は次の2つを実践しました。

  • 検証① ⇒ 2つの環境に割り振られたドメインを入れ替える方法(CNAME_SWAPによるデプロイ)
  • 検証② ⇒ DNS(Route53)のルーティング設定を変更する方法(DNSカットオーバーによるデプロイ)

検証環境作成

検証を行うのに使用した環境構築方法を以下に示します。
手順①~④はElastic Beanstalkで、手順⑤はAmazon Route53コンソールから操作しています。

①アプリケーション作成
以下のコマンドでアプリケーションを作成します。

$eb init

対話式の質問が途中で表示されるので、以下のように設定します。

  • アプリケーション名 = BGDeploy
  • アプリケーション種類 = PHP

②ブルー環境作成
①で作成したアプリケーションに環境を作成します。この環境が今動いている既存の環境と考えてください。
今回の検証では、トップページが1枚のシンプルな構成となっています。

$eb create env1

ブルー環境には以下のhtmlをデプロイします。

<html>
<head>
<title>ver1.0</title>
</head>
<body bgcolor="blue">
<font color="white">this is ver1.0</font>
</body>
</html>

デプロイ。

$eb use env1
$eb deploy

③グリーン環境作成
①で作成したアプリケーションにもう一つ環境を追加します。この環境が移行後の環境であると考えてください。

$eb create env2

グリーン環境には以下のhtmlをデプロイします。

<html>
<head>
<title>ver1.1</title>
</head>
<body bgcolor="green">
<font color="white">this is ver1.1</font>
</body>
</html>

デプロイ。

$eb use env2
$eb deploy

④確認
手順②③で作成した環境にwebブラウザからアクセスすると以下のようになります。

  • ブルー環境
$eb use env1
$eb open

bgdeploy_blue

  • グリーン環境
$eb use env2
$eb open

bgdeploy_green

⑤Route53にアプリケーションを関連づけ
手順①〜③で作成したアプリケーションを「AWS Route53」に関連づけることでDNSによるルーティングを可能とします。
Route53とはAWSのサービスの一つで、DNSサーバーの役割をします。
事前に取得した以下のドメインが、②で作成したブルー環境のエイリアスとなるように関連付けをします。
ユーザーはこのURLを叩いてアプリケーションにアクセスすると考えてください。

  • ドメイン名 : aokixyz.top

bgdeploy_route53

webブラウザからアクセスすると、ドメインがブルー環境に紐付いていることが確認できます。
bgdeploy_domain1

検証①CNAME_SWAPによるブルーグリーンデプロイメント

では、ブルー環境からグリーン環境へと移行を行います。
現在、アプリケーションへのリクエストは以下のように処理されます。

①ユーザがURLを叩く。
②Route53が名前解決を行い、ブルー環境にリクエストを振る。
③ロードバランサーがポリシーに則り、アプリケーションサーバー(EC2)へリクエストを振り、処理が行われる。

検証環境構築の中でブルー、グリーン各環境(正確には各環境のロードバランサー)に自動的にドメインが振られています。
2つのドメイン(CNAME)を交換することで、DNSで名前解決するサーバーをグリーン環境に変更し、向き先を変更します。
Elastic Beanstalkはドメイン交換の機能を持っており、以下のコマンドで簡単に行うことが可能です。

$eb use env2
$eb swap env1

以下のコマンドを実行すると、ドメインが入れ替わっていることを確認できます。
(CNAMEの項目がドメインに該当します。env1で使用していたドメインがenv2に割り振られています。)

$eb status
Environment details for: env2
  Application name: BGDeploy
  Region: ap-northeast-1
  Deployed Version: app-170104_132005
  Environment ID: e-xpjfywsf6r
  Platform: 64bit Amazon Linux 2016.09 v2.3.0 running PHP 5.4
  Tier: WebServer-Standard
  CNAME: env1.3kjeufmpnp.ap-northeast-1.elasticbeanstalk.com
  Updated: 2017-01-04 04:29:02.981000+00:00
  Status: Ready
  Health: Green

これで移行完了です。
サーバーを停止させることなく移行するという目標が達成されました。
アプリケーションのURLを叩くと新環境に移行できていることが確認できます。

bgdeploy_cswap_newapp

移行後の環境で問題が発生した場合、以下のコマンドで元のブルー環境に向き先を変更してロールバックします。

$eb use env1
$eb swap env2

ブラウザからURLを叩くと元の環境に戻っていることが確認できます。
bgdeploy_domain1

検証②DNSカットオーバーによるブルーグリーンデプロイメント

検証①ではドメイン交換することで移行を行いましたが、DNSの設定を変更することでも同じことが可能です。
Route53では「トラフィックポリシー」というものを作成することができ、これによってルーティングの向き先や重みづけなどの制御をすることができます。

今回作成するトラフィックポリシーは「加重ルーティングポリシー」と呼ばれるポリシーです。
1つのDNS名(aokixyz.top)に対して複数のリソースを関連づけ、指定した比率でルーティングすることが可能です。
例えば「ブルー100, グリーン0」であればアプリケーションへのリクエストは全てブルーにルーティングされます。
「ブルー1, グリーン1」であればブルーとグリーンに均一に分散されることとなります。

下の表のように優先度を設定し、移行前はブルー環境に、移行後はグリーン環境に向くようにします。

環境 優先度(移行前) 優先度(移行後)
ブルー 100 0
グリーン 0 100

以下の手順でトラフィックポリシーを作成します。

①Route53マネージメントコンソールから「Create policy records」を押下。
bgdeploy_route53_2

②ポリシーに名前をつけ、「Next」を押下。
bgdeploy_route53_3

③endpointに「Elastic Beanstalk environment」を選択し、ブルー環境とグリーン環境を指定する。
ルールに「Weighted Rule」を選択し、ブルー環境 = 「100」, グリーン環境 = 「0」の優先度を指定する。
その後、「Create Traffic Policy」を押下。
bgdeploy_x1

④トラフィックポリシーを作成した後、ポリシーレコードを作成する。
bgdeploy_route53_6

⑤StatusがAppliedになれば、ポリシーの作成は完了です。
bgdeploy_route53_7

ブラウザからURLを叩くとブルー環境にルーティングされていることを確認できます。
bgdeploy_route53_8

続いてトラフィックポリシーを編集して、優先度を変更します。(移行後の状態となります。)

トラフィックポリシーを編集して新しいバージョンとして保存。
bgdeploy_x2

ポリシーレコードのバージョンを新しいものに変更。
bgdeploy_x3

ブラウザからURLを叩くとグリーン環境に切り替わっていることを確認できます。
bgdeploy_route53_13

移行後の環境で問題が発生した場合、移行前のトラフィックポリシーにバージョンを戻すことでロールバックすることができます。

まとめ

長くなりましたが、いかがでしたでしょうか。

リリース時に新しい環境を作成して古い環境は使い捨てていくというのは、クラウド時代らしいデプロイ方法だと思います。
この発想は「Immutable Infrastracture」(一度サーバーを構成したら変更しないという考え方)とリンクしています。

リリースがより効率的に行われたらいいな、と思います。
ここまでお読みいただき、ありがとうございました。

参考

今回の記事の執筆にあたり、以下のサイトを参考にさせていただきました。
Martin Fowler氏のblog