mazyu36の日記

某SIer所属のクラウドエンジニアのブログ

AWS CDKでECS Blue Green DeploymentのL2 Constructがキタ

はじめに

以下の記事で ECSのBlue Green Deploymentが正式にはAWS CDKに対応していないという記事を作成した。 mazyu36.hatenablog.com

しかし2022/11にv2.50.0で待望のL2 Constructが実装されたので試してみた。 docs.aws.amazon.com

実装方法

前回の記事の手順ベースで差分を明記する形で記載していく。

1. CodeDeployのロールを作成する→不要

IAMロールは自動で作成してくれるので不要となった。

// CodeDeployのロール作成
const codeDeployRole = new iam.Role(this, 'CodeDeployRole', {
    assumedBy: new iam.ServicePrincipal('codedeploy.amazonaws.com'),
    managedPolicies: [
            iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeDeployRoleForECS')
    ]
})

2. CodeDeployのECSアプリケーションを作成する。 → 必要(変更なし)

以下の通り。ここは特に変更なし。

// CodeDeployのECSアプリケーションを作成
const ecsApplication = new codedeploy.EcsApplication(this, 'EcsApplication', {
        applicationName: 'ECSServiceApp', // 名称は任意
});

3. デプロイメントグループを作成する。 → 必要(変更あり)

一番変更があった箇所。専用のDeployment GroupのL2 Constructが実装されたため、これを使用すれば良い。

以下v2.50.0前後でどれぐらい違うかを示す。

// v2.50.0より前
const deploymentGroup = new codedeploy.CfnDeploymentGroup(this, 'ECSDeploymentGroup', {
  applicationName: ecsApplication.applicationName,
  serviceRoleArn: codeDeployRole.roleArn,
  autoRollbackConfiguration: {
    enabled: true,
    events: ['DEPLOYMENT_FAILURE']
  },
  blueGreenDeploymentConfiguration: {
    deploymentReadyOption: {
      actionOnTimeout: 'CONTINUE_DEPLOYMENT',
      waitTimeInMinutes: 0
    },
    terminateBlueInstancesOnDeploymentSuccess: {
      action: 'TERMINATE',
      terminationWaitTimeInMinutes: 5
    }
  },
  deploymentConfigName: 'CodeDeployDefault.ECSAllAtOnce',
  deploymentGroupName: 'ecsDeployment',
  deploymentStyle: {
    deploymentOption: 'WITH_TRAFFIC_CONTROL',
    deploymentType: 'BLUE_GREEN'

  },
  loadBalancerInfo: {
    targetGroupPairInfoList: [{
      targetGroups: [
        { name: blueTargetGroup.targetGroupName },
        { name: greenTargetGroup.targetGroupName }
      ],
      prodTrafficRoute: {
        listenerArns: [listener.listenerArn]
      },
      testTrafficRoute: {
        listenerArns: [testListener.listenerArn]
      }
    }]
  },
  ecsServices: [{
    clusterName: ecsCluster.clusterName,
    serviceName: ecsService.serviceName,
  }]

})


// v2.50.0より後(L2 Costruct)
const blueGreenDeploymentGroup = new codedeploy.EcsDeploymentGroup(this, 'BlueGreenDeploymentGroup', {
  blueGreenDeploymentConfig: {  // ターゲットグループやリスナーを直接設定
    blueTargetGroup,
    greenTargetGroup,
    listener,
    testListener
  },
  autoRollback: {  // ロールバックの設定
    failedDeployment: true
  },
  service: ecsService,  // ECSサービスを直接指定
  application: ecsApplication,  // 2で作成したECSアプリケーション
  deploymentConfig: codedeploy.EcsDeploymentConfig.ALL_AT_ONCE, // デプロイの方式を指定(一括で置き換えるのか、一定割合ずつ置き換えるのかなど)
  deploymentGroupName: 'ecsDeployment',
})

上記のように設定項目が大幅減、かつリソースも型で紐付けられるため非常にやりやすくなっている。

ロールバックやデプロイの設定については省略可能だが、予期せぬ動作とならないよう、デフォルトの動作はしっかり把握しておいた方が良い。

4. CodePipelineにCodeDeployのステージを追加する → 必要(変更あり)

ここも楽になった。

CodeDeployのActionにおいて、v2.50.0より前では一度DeploymentGroupを作成し紐づけるという力技が必要であったが、v2.50.0では3で作成したECS DeploymentGroupを紐づけるだけで良くなった。

// CodePipelineを定義
const pipeline = new codepipeline.Pipeline(this, 'CodePipeline', {
    pipelineName: 'CodePipeline'
});


// CodePipelineにDeployステージを追加
const deployStage = pipeline.addStage({
  stageName: 'Deploy'
});


// ------v2.50.0より前
// DeploymentGroupを作成する。ここは名称を参照する形で力づくで作成している感ある。
const deploymentGroup: codedeploy.IEcsDeploymentGroup = codedeploy.EcsDeploymentGroup.fromEcsDeploymentGroupAttributes(this,
    'EcsCodeDeploymentGroup', {
    deploymentGroupName: 'ecsDeployment', // 手順3で作成したDeploymentGroupの名前と一致させる
    application: ecsApplication // 手順2で作成したECSアプリケーションを設定
});

// CodeDeploy用のActionを作成する。
const deployAction = new codepipeline_actions.CodeDeployEcsDeployAction({
    actionName: 'EcsCodeDeploymentAction',
    deploymentGroup,
    taskDefinitionTemplateInput: buildOutput,
    appSpecTemplateInput: buildOutput,
    containerImageInputs: [{
        input: buildOutput,
        taskDefinitionPlaceholder: "IMAGE1_NAME" // taskdef.jsonに設定するアレ
    }]
});


// ------v2.50.0
const deployAction = new codepipeline_actions.CodeDeployEcsDeployAction({
    actionName: 'EcsCodeDeploymentAction',
    deploymentGroup: blueGreenDeploymentGroup, // ECS Deployment Groupを指定するのみ
    taskDefinitionTemplateInput: buildOutput,
    appSpecTemplateInput: buildOutput,
    containerImageInputs: [{
        input: buildOutput,
        taskDefinitionPlaceholder: "IMAGE1_NAME"
    }]
});

以上のようにECS Blue Green DeploymentはAWS CDKにおいて非常に実装しやすくなった。

実際に上記をベースに実装したところ問題なく動作した。

ということで

AWS CDKでECS Blue Green Deploymentを構築することは容易となったので、採用するかは運用次第というところか。

2022 AWS DevDayでこの辺りが取り上げられそうなので要注目(以前の記事の再掲)。

  • C-3: Blue/Green デプロイと安全性と複雑性と
  • C-4: AWS CDKでECS on FargateのCI/CDを実現する際の理想と現実

aws.amazon.com