ECSのBlue/Green(カナリアリリース)がCloudFormationでサポートされました!

2020.05.20

こんにちは、コンサル部のもこ@札幌オフィスです。

本日、ECSのBlue/Greenデプロイ(カナリアリリース)がCloudFormationでサポートされたので、早速CloudFormationでECSのBlue/Green、カナリアリリースをやってみました!

ECS環境のBlue/Green(カナリアリリース)の仕組み

そもそもECS環境に対してどのようにBlue/Green(カナリアリリース)を行われるのかをおさらいしておきましょう。

時は遡って昨年、ALBでターゲットグループがサポートされました。

[激アツアップデート]ALBだけでカナリアリリース(重み付け)ができるようになりました!

上記の機能を利用したデプロイを自動化した物がCodeDeployで今年2月にリリースされていて、CodePipelineやコマンドなどから実行することで利用することが出来ていました。

ECSでCodeDeployを使った線形デプロイとCanaryデプロイを試してみた

今回のアップデートはCloudFormationで実行出来ることになり、ECSサービスのアップデートをCloudFormationを利用して実行している場合に利用することが出来ます。

やってみる

早速どんな感じに動くのかを検証していきます。

公式ドキュメントのCloudFormation(YAML)テンプレートを実行してみます。

Perform ECS blue/green deployments through CodeDeploy using AWS CloudFormation

スタックのパラメータはデフォルトのVPCとサブネットを指定しました。

作成されたALBのエンドポイントにアクセスすると、このような画面が出てきます。

Blue/Green(カナリアリリース)をしてみる

それでは早速Blue/Green(カナリアリリース)でコンテナをアップデートしてみます。

AWS::ECS::TaskDefinition または AWS::ECS::TaskSet の更新があった場合にCodeDeployが走るそうなので、適当にイメージを更新してみます。

BlueTaskDefinition:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      ExecutionRoleArn: !Ref ECSTaskExecutionRole
      ContainerDefinitions:
        - Name: DemoApp
          Image: 'nginx:mainline-alpine' # 'nginxdemos/hello:latest' から書き換え
          Essential: true
          PortMappings:
            - HostPort: 80
              Protocol: tcp
              ContainerPort: 80
      RequiresCompatibilities:
        - FARGATE
      NetworkMode: awsvpc
      Cpu: '256'
      Memory: '512'
      Family: ecs-demo

CodeDeployの設定は Transformで AWS::CodeDeploy::BlueGreen を呼び出した上で、Hookブロックに設定を書いていく形になります。

TrafficRoutingConfig でデプロイの種類を指定することができ、AllAtOnce、TimeBasedCanary、TimeBasedLinearが対応していて、それぞれの特徴は下記の通りです。

  • AllAtOnce: 名前の通り一気にアップデート
  • TimeBasedCanary: 2段階に分けてアップデート、 最初に30%のトラフィックを新しい環境に流して、5分後に残りの70%を新しい環境に流してデプロイを終了するようなイメージ
  • TimeBasedLinear: 指定したパーセントと時間ごとにアップデート、20%を5分ごとに新しい環境にアップデートするイメージ

※ 詳細なパラメーターについては公式ドキュメントを参照してください。

今回はTimeBasedLinearを利用して、1分おきに20%ずつ新しい環境にトラフィックを流してみます。

Transform:
  - 'AWS::CodeDeployBlueGreen'
Hooks:
  CodeDeployBlueGreenHook:
    Properties:
      TrafficRoutingConfig:
        Type: TimeBasedLinear
        TimeBasedLinear: 
          StepPercentage: 20 # 20%ずつ
          BakeTimeMins: 1 # 1分おきに
      Applications:
        - Target:
            Type: 'AWS::ECS::Service'
            LogicalID: ECSDemoService
          ECSAttributes:
            TaskDefinitions:
              - BlueTaskDefinition
              - GreenTaskDefinition
            TaskSets:
              - BlueTaskSet
              - GreenTaskSet
            TrafficRouting:
              ProdTrafficRoute:
                Type: 'AWS::ElasticLoadBalancingV2::Listener'
                LogicalID: ALBListenerProdTraffic
              TargetGroups:
                - ALBTargetGroupBlue
                - ALBTargetGroupGreen
    Type: 'AWS::CodeDeploy::BlueGreen'

この状態でCloudFormationをアップデートすると、CodeDeployが実行され、コンテナの実行、Hooksで設定した項目に沿ってリリースが始まります。

デプロイ中のALBのルール設定画面はこんな感じで、20%ずつ変更されている事を確認でき、ブラウザでF5連打してもだいたい2割くらいの確率で新しいコンテナにルーティングされている事を確認出来ます。

2分後には追加で20%新しい環境に流れていることを確認出来ます!

まとめ

CloudFormationを利用したECSのBlue/Greenが対応したことにより、CloudFormationでECSのサービスに対してBlue/Green、カナリアリリースを出来るようになりました。

なお、2020/05/20時点ではまだAWS CDKで対応していませんが、GitHubのIssueでは活発に議論されていて、CloudFormationでのBlue/Green対応待ちの状態が続いていましたが、今回のアップデートでCDKは近いうちに実装され、リリースされると見て良いでしょう。

https://github.com/aws/aws-cdk/issues/1559

参考