CDKでEC2のBlue/Greenデプロイをするパイプラインを作る

こんばんは@manoです。もう今年も12月ですね。

12月ということで、今年もNewsPicksではアドベントカレンダーをやります!(って、僕は初参加なんだけども。)

実はここで話すのは初めてですが、僕は(株)NewsPicksの社員で、この記事はNewsPicks Advent Calendar 2019の1日目の記事ということになります。

最近CDKばっかり触っているということもあり、当ブログとしてはここまで2記事連続でCDK関連の話をしてきましたが、今日もCDK関連の話をします。

NewsPicksでは現在、デプロイフローの見直しを進めています。
現状はAWSで、auto scaling groupで管理されたEC2インスタンスに、NewsPicksのアプリケーションはJAVAがメインであるため.warファイルを配置し、Nginx & Tomcatといったwebサーバー構成でアプリケーションを動かしています。
今後それをコンテナ化したり、大きなモノリスになってしまっている部分のマイクロサービス化などをどんどんやっていこうと思っているのですが、まず着手しているのがデプロイフローの改善です。

現在のNewsPicksのデプロイは、自分たちで作ったshellスクリプトによってauto scaling groupのBlue/Greenデプロイを実現しています。
これを、CodeDeployを使用してBlue/Greenデプロイを行うようにしようとしていて、そのあたりの仕組みの実装方法にCDK(言語はtypescript)を採用しています。

CDKを採用した(個人的な)理由

1. 書かなければならないコードの量が少ない。

例えばCloudFormationだと、一つ一つのコンポーネントには基本的にroleの明記が必要で、一つのyaml(またはjson)ファイルが巨大になっていくこともしばしばかと思います。
その点、CDKではコード内の依存関係から、ある程度勝手に必要なpolicyが割り当てられたroleが自動的に作成されます。手軽です。

2. IDE等でclassやinterfaceの定義にジャンプすれば、ドキュメントを見ずとも開発が可能

CloudFormationだと、yamljsonに書いていかなければならないため、自身でドキュメントを確認し、適切に書かなければいけません。
でもCDKだと、typescript等の型のある言語を選択すれば(というかtypescript以外で書いたことないから他はよく知らないんだけど)、classやinterfaceの定義にジャンプすれば必要なパラメータがどのようなものかがすぐにわかるため、便利です!
また、テストが書けるというのもとても魅力的です。「デプロイして初めて書いた内容が合っているのかどうかがわかる」という局面も少なからずありますが、テスト実行時点でわかるものも結構あります。

3. CDK自体の開発がものすごく活発

これも大きな理由です。最近だと毎週のようにバージョンが上がっています

新デプロイフローの構成

このような感じで進めています。 f:id:jumpeim37:20191201180819p:plain

NewsPicksではメインのバージョン管理ツールにbitbucketを使用しているのですが、CodePipelineはbitbucketからのトリガーに対応しておらず・・・、 CodeBuildは対応しているので、

  1. release tagがbitbucketにプッシュされたらCodeBuildプロジェクトがビルドを実行する
  2. 1の成果物がS3にアップロードされる
  3. 2のbucketにアップロードされたことをトリガーとして、CodePipelineが走る
  4. 2でアップロードされた成果物を整理してS3に上げ直す
  5. 手動approve
  6. CodeDeployによりBlue/Greenデプロイを実行する

という構成にしています。

上記構成のCDKでの実装

このような感じで実装しています。
なお、auto scaling groupのBlue/Greenデプロイは、2019/12/1現在CloudFormationが対応していないので、Deployment GroupがCDKでは実装できません。
そのため、上のコードではDeployment Groupに割り当てるIAM roleだけを作っています。
Blue/Greenを行うDeployment Groupを作成するには、 aws deploy create-deployment-group等で行う必要があります。

CodePipelineを採用した理由

1. 手動approveステージが作れる

例えば「ビルドまでは完了してあとはデプロイだ」というとき、そのままデプロイが走ってしまうと、万一それがよからぬタイミングだったりすると大変です。
CodePipelineには、manual approveという機能があり、手動でapproveしないと以降のステージには進めないようになっています。

2. CodeDeployが使える

後述しますが、CodeDeployが素晴らしいです。

3. CDKによりコードで管理できる

素敵ですね。

CodeDeployを採用した理由

1. 過去のリビジョンに遡って簡単にデプロイできる

デプロイ後に戻したくなったとき、Blueのauto scaling groupがまだ生きていればすぐにrollbackできるし、terminate済みだとしても簡単に戻したいリビジョンを選択肢リデプロイできます。

2. 細かいイベントフックごとに任意の処理を実行できる

こちらに詳細が書かれていますが、デプロイ中のフックが結構細かく分けられていて、それぞれに任意の処理を挟むことができます。

終わりに

アドベントカレンダーというものに初めて参加したのですが、記事を強制的に書かざるを得ないという意味で貴重な機会だなと感じました。
これを機に、様々なカレンダーにどんどん参加したいなと思いました。

2019-12-02追記

アドベントカレンダー2日目の記事です。

qiita.com