Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@neruneruo

CloudFormationテンプレートを1からしっかり理解しながらECS on Fargateなアプリを自動構築する(中編)

前提条件

前編で作ったECSのサービスに対してCodePipelineを使ってCI/CDパイプラインを作るので、前編を理解しておく。

記事中には、備忘のためにリファレンスに書かれていないデフォルト値を整理しておくが、2020年3月時点の情報であり、後でAWSが仕様を変えたとしても追従する予定はないので、挙動が違ったらリファレンスを見直してほしい。あと、今回の構成(ECS on FargateのBlue/Greenデプロイメント)以外の構成以外のデフォルト値まで調査はしていないのであしからず。

CodeDeployでBlue/Greenデプロイメントのアプリケーションを作る

アプリケーションの設定

ここはそんなに悩むことはない。以下のような感じで設定しておけばOK。

  APPLICATION: 
    Type: AWS::CodeDeploy::Application
    Properties:
      ApplicationName: CFn-test-Application
      ComputePlatform: ECS

各プロパティのデフォルト値は以下。

プロパティ デフォルト値
ApplicationName AWS払い出しの名前 ※リファレンス記載
ComputePlatform EC2/オンプレミス

デプロイメントグループの準備

ちなみに、デフォルト値の確認をしていたところ、DeploymentStyle のプロパティを設定しないと、なぜか

For ECS deployment group, ec2TagFilters can not be specified (Service: AmazonCodeDeploy; Status Code: 400; Error Code: InvalidEC2TagException; Request ID: ...)

なエラーが出た。謎。BLUE_GREEN を設定すれば解消するので深く追跡はしない。

例によって各プロパティのデフォルト値は以下。

プロパティ デフォルト値
AlarmConfiguration 無し
AutoRollbackConfiguration よく分からない…
AutoScalingGroups 無し
Deployment よく分からない…
DeploymentConfigName なし?
DeploymentGroupName AWS払い出しの名前 ※リファレンス記載
Ec2TagFilters Fargateでは対象外
Ec2TagSet Fargateでは対象外
LoadBalancerInfo ECSのBlue/Greenデプロイメントでは必須
OnPremisesInstanceTagFilters Fargateでは対象外
OnPremisesTagSet Fargateでは対象外
TriggerConfigurations なし

ここで問題が……

ここから先、どう頑張ってもエラーが出てしまう。
なんと、ユーザーガイドを見ると

Blue/Green デプロイタイプでは、AWS CloudFormation は、Lambda コンピューティングプラットフォームでのデプロイのみをサポートします。

とか書いてある。ガーン……このままではCloudFormationによる全自動化ができないのか……。

ここまでやって諦めてしまうのは勿体ないので、一部だけ半自動にする。
作りたかったアプリケーションとデプロイメントグループの定義をCLIをラップしたシェルにして…

#!/bin/sh

APPLICATION_NAME=CFn-test-Application
DEPLOYMENT_GROUP_NAME=CFn-test-DeploymentGroup
DEPLOYMENT_GROUP_JSON=./CLI_createDeploymentGroup.json

aws deploy create-application --application-name ${APPLICATION_NAME} --compute-platform ECS

aws deploy create-deployment-group --application-name ${APPLICATION_NAME} --deployment-group-name ${DEPLOYMENT_GROUP_NAME} --cli-input-json file://${DEPLOYMENT_GROUP_JSON}

{
  "applicationName": "CFn-test-Application",
  "deploymentGroupName": "CFn-test-DeploymentGroup",
  "serviceRoleArn": "arn:aws:iam::[アカウントID]:role/ecsCodeDeployRole",
  "deploymentStyle": {
    "deploymentType": "BLUE_GREEN",
    "deploymentOption": "WITH_TRAFFIC_CONTROL"
  },
  "blueGreenDeploymentConfiguration": {
    "terminateBlueInstancesOnDeploymentSuccess": {
      "action": "TERMINATE",
      "terminationWaitTimeInMinutes": 30
    },
    "deploymentReadyOption": {
      "actionOnTimeout": "CONTINUE_DEPLOYMENT",
      "waitTimeInMinutes": 0
    }
  },
  "loadBalancerInfo": {
    "targetGroupPairInfoList": [
      {
        "targetGroups": [
          {
            "name": "CFn-test-ALB-TG1"
          },
          {
            "name": "CFn-test-ALB-TG2"
          }
        ],
        "prodTrafficRoute": {
          "listenerArns": [
            "[CFn-test-ALBの本番用リスナーのArn]"
          ]
        },
        "testTrafficRoute": {
          "listenerArns": [
            "[CFn-test-ALBテスト用リスナーのArn]"
          ]
        }
      }
    ]
  },
  "ecsServices": [
    {
      "serviceName": "CFn-test-ECSService",
      "clusterName": "CFn-test-ECSCluster"
    }
  ]
}

こうだ!このシェルを実行して、アプリケーションを作成してからCodeDeployでデプロイを作成してみると、ちゃんとテストポートを使ったBlue/Greenデプロイメントが発動する!

あとは、これをCodePipelineに組み込むのみ!
ということで、後編に続く。

追記

↑のままだと、「半自動」で、何が面倒臭いって、前段でCloudFormationテンプレートで作ったALBのリスナーのARNを、スタックを作り直す都度いちいち書き換えないといけなくいところ。
手動によるミスのリスクは極力減らすべきなのである!

というわけで、前段で作ったALBの属性情報からARNを自動で取得することを考える。

シェルを実行するサーバで、

$ sudo yum jq install

して、JSONを編集できるようにしておこう。

また、前回作ったCloudFormationテンプレートの Outputs に、

  Listener1:
    Description: ALB Listener Arn 1
    Value: !Ref ALBLISTENER1
    Export:
      Name: !Sub ${AWS::StackName}-ListenerArn1
  Listener2:
    Description: ALB Listener Arn 2
    Value: !Ref ALBLISTENER2
    Export:
      Name: !Sub ${AWS::StackName}-ListenerArn2

を追加しておく。こうしておくことで、

$ aws cloudformation describe-stacks --stack-name [スタック名] | jq -r '.Stacks[].Outputs | map(select(.ExportName=="[スタック名]-ListenerArn1"))[] | .OutputValue'

すればリスナー名が取れるのだ。
※jqコマンドの使い方はここの本筋ではないので、このあたりの記事を読んでおいてもらえれば。

そんな感じで

#!/bin/sh

############
# Settings #
############
STACK_NAME=CFn-test
ALBLISTENER_NAME1=${STACK_NAME}-ListenerArn1
ALBLISTENER_NAME2=${STACK_NAME}-ListenerArn2
APPLICATION_NAME=${STACK_NAME}-Application
DEPLOYMENT_GROUP_NAME=${STACK_NAME}-DeploymentGroup
DEPLOYMENT_GROUP_JSON=./CLI_createDeploymentGroup.json

###################
# Replace ALB ARN #
###################
aws configure set output json
ALBLISTENER_ARN1=`aws cloudformation describe-stacks --stack-name ${STACK_NAME} | jq -r '.Stacks[].Outputs | map(select(.ExportName=="'${ALBLISTENER_NAME1}'"))[] | .OutputValue'`
ALBLISTENER_ARN2=`aws cloudformation describe-stacks --stack-name ${STACK_NAME} | jq -r '.Stacks[].Outputs | map(select(.ExportName=="'${ALBLISTENER_NAME2}'"))[] | .OutputValue'`
echo '{
  "applicationName": "CFn-test-Application",
  "deploymentGroupName": "CFn-test-DeploymentGroup",
  "serviceRoleArn": "arn:aws:iam::[アカウントID]:role/ecsCodeDeployRole",
  "deploymentStyle": {
    "deploymentType": "BLUE_GREEN",
    "deploymentOption": "WITH_TRAFFIC_CONTROL"
  },
  "blueGreenDeploymentConfiguration": {
    "terminateBlueInstancesOnDeploymentSuccess": {
      "action": "TERMINATE",
      "terminationWaitTimeInMinutes": 30
    },
    "deploymentReadyOption": {
      "actionOnTimeout": "CONTINUE_DEPLOYMENT",
      "waitTimeInMinutes": 0
    }
  },
  "loadBalancerInfo": {
    "targetGroupPairInfoList": [
      {
        "targetGroups": [
          {
            "name": "CFn-test-ALB-TG1"
          },
          {
            "name": "CFn-test-ALB-TG2"
          }
        ],
        "prodTrafficRoute": {
          "listenerArns": [
            "'${ALBLISTENER_ARN1}'"
          ]
        },
        "testTrafficRoute": {
          "listenerArns": [
            "'${ALBLISTENER_ARN2}'"
          ]
        }
      }
    ]
  },
  "ecsServices": [
    {
      "serviceName": "CFn-test-ECSService",
      "clusterName": "CFn-test-ECSCluster"
    }
  ]
}' > ${DEPLOYMENT_GROUP_JSON}

###################
# execute AWS CLI # 
###################
aws deploy create-application --application-name ${APPLICATION_NAME} --compute-platform ECS
aws deploy create-deployment-group --application-name ${APPLICATION_NAME} --deployment-group-name ${DEPLOYMENT_GROUP_NAME} --cli-input-json file://${DEPLOYMENT_GROUP_JSON}

これにより、パラメータ以外の部分は触らずほぼ自動で動作するようになった。

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What is going on with this article?