CM re:Growth 2014 SapporoでCloud FormationとBlue-Green Deploymentの話をしてきた #cmdevio

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWSスノーボーダー渡辺です。 自転車シーズンも終わり、週末は山に籠もっています。 札幌にI/Uターンすればそんな生活ができるかもしれません(:p

さて、先週の金曜日に札幌でCM re:Growth 2014 SAPPOROが行われました。 今日は、そこで発表した「Cloud FormationによるBlue-Green Deployment」からポイントを絞って紹介します。

スライド資料はこちらです。

背景

自分はAWSコンサルティング部所属であり、現在は開発を基本的行っておりません。 ですが、これまでは開発現場でバリバリに設計・実装を行っていたこともあり、主に開発寄りの案件がアサインされることが多くなります。 例えば、AWSを利用したシステムの開発を行う企業と相談しながらインフラの設計をしつつアプリケーション部分の開発サポートをしたり、社内でも開発部署(AWSソリューション部)と連携してサポートを行ったりしています。 そうなってくると、必然的に「デプロイ(配備)」についてよく考えます。

そんな中で幾つかの開発系構築案件で、CloudFormationを使うことになり、Blue-Green Deploymentもやってみたので、そのノウハウの公開となりました。

Blue-Green Deploymentとは?

Blue-Green Deploymentとは、ダウンタイムをゼロにすることを目的としたデプロイメント手法のひとつです。 大雑把に言えば、ふたつの環境(Blue / Green)を用意し、片方の環境のみをアクティブにしておき、デプロイが必要な場合にはもう一方の環境に行い、完了したならばアクティブ環境を切り替えるという仕組みです。

AWSを使うことでデメリットが減る

Blue-Green Deployment自体は2010年にマーチンファウラ−のBlogで解説された手法です。 ですが、2系統を用意しなければならないなど、実際に行うには敷居の高いものでした。 しかし、AWSを使うと簡単に環境を作ることも破棄することも出来るため、コストやハード的なデメリットは少なくなりました。 これは、特にCloudFormationを活用することで大きくなります。

RDSは妥協する

スライドでも何度かでてきていますが、RDBを完璧にBlue Green Deploymentすることは非常に難しいといえます。 なぜならばダウンタイムゼロを実現するためには、切り替わる直前までデータ更新の可能性があり、更新内容が新しい環境に引き継がなければならないからです。 さらにRDBのスキーマ変更などがアップデート時に行われるならば、アプリケーション側で2バージョンのスキーマに対応する必要もあります。 こうなってくるとダウンタイムをゼロにすることに非常に大きなコストがかかってしまうため、資金の豊潤なプロジェクトでもなければ採用できないでしょう。

なので、RDB部分は妥協し、RDSを1系統用意するだけにとどめます。 多くの場合で、この妥協は問題ないでしょう。

CloudFormationを活用するポイント

Blue-Green DeploymentでCloudFormationを活用する一番のポイントは、Stackを環境毎に分割して構築することです。 先日サポートした案件では、スライドで説明しているようにVPCなどベース部分用にテンプレートとStackをひとつ作り、Blue環境とGreen環境は別々のStackとして構築しました。 Blue環境とGreen環境のテンプレートは共通です。

ベース部分のCFnテンプレート

ベース部分のテンプレートには、Blue-Green環境以外のリソースを定義します。 VPC, Subnet, Security Groupなどに加え、RDSなどのBlue-Green対象外のインスタンスを定義してください。 状況によってはRDSなどの永続化レイヤーはそれだけで独立したテンプレートとしておくのも有効です。 このベース部分のテンプレートを使って構築したStackは基本的にずっと使用し続けるものです。 変更があった場合は、テンプレートを更新した上でStackをUpdateするようにしてください。

Blue/Green環境用のCFnテンプレート

Blue/Green環境の違いはEC2インスタンスが配置されるサブネットの違いなどになると思います。 それ以外の部分についてテンプレートは同じですから、ここで2つのテンプレートを作ってメンテナンスを大変にするとか、元プログラマとしてはありえません。 うまく、切り替えられる仕組みはないでしょうか?

勿論、あります。 CloudFormationのパラメータ機能とMapping機能を利用して、環境(Green/Blue)を指定する事でサブネットなどを切り替えられるようにしましょう。 一部を抜粋するとこんな感じです。

    "Parameters": {
        "Env": {
            "Type": "String",
            "Default": "Blue",
            "AllowedValues": [
                "Blue",
                "Green"
            ]
       }
    },
    "Mappings": {
        "Subnet": {
            "Blue": {
                "AppA": "subnet-xxxxxxxxx",
                "AppC": "subnet-xxxxxxxxx"
            },
            "Green": {
                "AppA": "subnet-xxxxxxxx",
                "AppC": "subnet-xxxxxxxx"
            }
        }
    },
    "Resources": {
        "FrontWeb1": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
               "SubnetId": {
                    "Fn::FindInMap": [
                     "Subnet", { "Ref": "Env" }, "AppA"
                    ]
                }

            }

        }
     }

Stackを構築するとき、Parametersで定義したEnvを入力することになります。 ここにはBlueかGreenしか入力できません。

EC2のSubnetIdには、FindInMapファンクションを使いMappingsからIDを参照します。 この時、Subnet:Blue/Green:AppAが参照されるため、EC2インスタンスが複数あっても一括で差異を吸収できることになります。 テンプレートのメンテナンスは大変ですから、ここは大切なポイントです。

アプリケーションのデプロイ

AWS環境は何時でも構築して壊すことができるようになりました。 後はデプロイ用のツールを活用し、アプリケーションをデプロイしてください。 Route53でBlueからGreenに切り替えが出来たならば、Stackは破棄しちゃいましょう。 コストが最小限でBlue-Green Deploymentを実現できます。

まとめ

AWSでCloudFormationを活用すると、低コストで簡単にBlue-Green Deploymentが実現出来ます。 ダウンタイムをゼロにするという効果も高いですが、それ以上に何時でも作り直せるという安心感があるのは運用していて大きいでしょう。 うちでも試したいという所があれば是非ご連絡ください!