はじめまして。
2019年新卒で入社し、現在AI事業本部のAirTrackでバックエンドエンジニアをしております大川内(@shoichi1023) です。
今回は、ECS FargateのBlueGreenDeployをCDKのみで実装することがあったので知見をまとめておきます。

実現したいアーキテクチャ

 

モチベーション

現在、プロダクトでAWS CDKを利用してインフラ構築を行っています。
CDKを利用して、ECSのBlueGreenDeployを実装する記事があまり上がっておらず、CDKのみでとなると情報がなかったので、実装する上で調べたこと、ハマったことなどを記して行こうと思います。

AWS CDKとは

CDKとはCloudFormationをTypeScriptやPythonから記述することができるものです。
構成管理ツールは基本的にはjsonやyamlで書くのが一般的ですが、プログラミング言語で書くことができるのがCDKの特徴です。

公式ドキュメント

今回参考にする元記事

実装

基本方針

基本的には、aws-samples/aws-reinvent-2019-trivia-game (GitHub) のサンプルをベースに実装していきます。
変更した点や、なぜcfnオブジェクトを利用するのか、実装の際の注意点などを追記していこうと思います。

Cfnオブジェクトを使う理由

まず、Cfnオブジェクトとは、CDKによる抽象化があまりされていない、低レイヤのオブジェクトになります。
これ以外にも、ecs-patternなどの高レイヤのオブジェクトもあり、CDKの恩恵を最大限うけることを考えると、こういった高レイヤのオブジェクトを利用することが推奨されます。

ではなぜ、このサンプルでcfnオブジェクトを利用しているかというと、 AWS公式ドキュメントの記述にあるように、BlueGreenDeployHookという機能を利用して実装をしていきます。
ただ、この機能はまだCDKでは抽象化されておらず、利用するには低いレイヤのオブジェクトを利用する以外に実装方法がないため、現状ではcfnオブジェクトを利用しています。

issueでもかなり盛り上がってるみたいなので、近いうちに実装されるといいですね。

外部のリソースを使いたい

CDKで構築するとはいえ、毎回新しいリソースを使うわけにもいきません。
例えば、VPCやサブネット、セキュリティグループなどは既存のものを使い回したいですよね。

通常通りに、fromAttribute 等のメソッドを利用して外部のリソースを利用すると、環境のアップデート時にエラーになってしまいます。
そのため、CfnParameter を利用して実行時にidを渡してあげることで回避できます。

具体的には、下記のようにコードを記述し、

import * as core from "@aws-cdk/core";
import * as ec2 from "@aws-cdk/aws-ec2";

const GetCfnParameter = (
  key: string,
  props?: core.CfnParameterProps
): GetCfnParamFn => (scope: core.Construct): core.CfnParameter =>
  new core.CfnParameter(scope, key, props);

const externalVpcId = GetCfnParameter("externalVpcId", { type: "String" });

export class EcsBulueGreenStack extends core.Stack {
  constructor(
    scope: core.Construct,
    id: string,
    props?: core.StackProps
  ) {
    super(scope, id, props);
    const vpc = ec2.Vpc.fromVpcAttributes(
        this,
        "external-vpc",
        {
          vpcId: externalVpcId(this).valueAsString,
          availabilityZones: [
            "ap-northeast-1a",
            "ap-northeast-1c",
            "ap-northeast-1d",
          ],
        }
      );
  }
}

実行時に下記のように値を渡します。


cdk deploy ecs-blue-green-deploy-stack --no-color --parameters externalVpcId=vpc-xxxxxxxx

注意点

ドキュメントにも書いてありますが、TaskSetやTaskDefinitionといったリソースと、それ以外のリソースの更新は同時にできません。
公式ドキュメントを読むと、別々のdeployで適用すればいいように読み取れますが、 Hookをコメントアウトしないと動作しません でした。

また、動作が不安定なところがあり、stackを削除しないとデプロイが適用できないといった事象も確認しました。
AWSに共有して、現在調査をしてもらっているので、何かわかったら追記します。

最後に

CDKのおかげでインフラ構築にあまり触れたことのないメンバーもかなりインフラ構築に馴染めているので、オブジェクトベースで管理できるのはとてもありがたいです。
自分たちのユースケースに合わせて抽象化できるので実装も早くて助かります。
まだまだ発展途上の技術かと思いますが、用途に合えば、ぜひ皆さんも使ってみてください!