ECS FargateでGitHubのWebHookでBlue/Green自動デプロイする

`AWS Fargate`でBlue/Greenの自動デプロイを設定します。
ソースレポジトリには`GitHub`、ビルドには`CodeBuild`、デプロイパイプラインには`CodePipeline`を用います。
自動ビルドの設定は、`CloudFormation`とマネジメントコンソールを利用します。

※以下の手順を実行すると、`AWS`のサービス利用料が発生します。
※`Fargate`のBlue/Greenデプロイ設定は完了しているものとします。
※`Fargate`のBlue/Greenデプロイ設定は、以下を参照してください。

[ECS FargateでBlue/Greenデプロイ設定](https://qiita.com/takeshi_hirosue/items/0ccacbe8015b3830e1a7 "FargateでBlue/Greenデプロイ設定")

※今回のサンプルは以下を利用しています。
https://github.com/Thirosue/cross-accout-deploy-sample

### 構成イメージ

> 今回の構成のイメージは下図のとおりです。

<img width="820" alt="スクリーンショット 2020-01-18 15.35.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/9ca11ec5-bdf9-5c37-e35e-1fa4a2d1800e.png">

### `GitHub`で認証トークンを作成する

認証トークンの作成の仕方は [こちら](https://help.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line "こちら") を参照

> 認証トークンには`Read`および`Webhook`の権限を付与する

<img width="755" alt="スクリーンショット 2020-01-12 21.08.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/78eab96d-0ea9-435b-fe87-f29340da98d8.png">

### 自動ビルド設定（CodeBuild）

Blue/Greenデプロイには以下の3ファイルを作成する必要があります。

+ imageDetail.json（ビルドイメージ指定ファイル ※ECSビルドで必要）
+ appspec.yaml（CodeDeploy設定ファイル ※ECSの場合、Blue/Greenデプロイでのみ必要）
+ taskdef.json（タスク定義ファイル ※ECSの場合、Blue/Greenデプロイでのみ必要）

```bash
  
version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION) #ECRへログイン
      - REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_NAME}
      - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) #リリースタグを生成
      - echo AWS Account Setiing ...
      - sed -i -e "s/__ACOUNTID__/$AWS_ACCOUNT_ID/" taskdef.json #ビルド実行AWSアカウントで置換
  build:
    commands:
      - echo Build started on `date`
      - echo Vue.js Project Building...
      - docker run --rm -v $(pwd):/work node:lts /bin/bash -c "cd /work && yarn && yarn build" #安定版（LTS）でビルド
      - cp -r dist docker/
      - echo Building the Docker image...
      - docker build -t $REPOSITORY_URI:latest docker/
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Pushing the Docker image...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo Writing image definitions file...
      - printf '{"Version":"1.0","ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json #イメージ指定ファイルを出力
      - cat imageDetail.json
artifacts:
  files:
    - appspec.yaml
    - taskdef.json
    - imageDetail.json
```

※設定ファイルの全量は以下を参照してください。
https://github.com/Thirosue/cross-accout-deploy-sample/blob/master/buildspec.yml

### デプロイパイプライン設定（`CodePipeline`）

`CloudFormation`とマネジメントコンソールで設定します。

##### Buildステージまでの設定

> `CloudFormation`で`Build`ステージまで設定します。
> ->`GitHubOAuthToken`には、上記で取得した認証トークンを設定する
> ->`ProdAccount`は任意の値を設定する（本記事では利用しない）

<img width="1001" alt="スクリーンショット 2020-01-12 21.28.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/48ead5c6-b80c-3669-99f0-97e4b6badbcb.png">

```yaml
  SampleCodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Source:
        BuildSpec: buildspec.yml
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/standard:3.0
        Type: LINUX_CONTAINER
        PrivilegedMode: true
        EnvironmentVariables:
          - Name: AWS_ACCOUNT_ID
            Type: PLAINTEXT
            Value: !Ref AWS::AccountId
          - Name: AWS_DEFAULT_REGION
            Type: PLAINTEXT
            Value: !Ref AWS::Region
          - Name: CONTAINER_NAME
            Type: PLAINTEXT
            Value: front
          - Name: IMAGE_NAME
            Type: PLAINTEXT
            Value: !Sub ${ServiceName}
      LogsConfig:
        CloudWatchLogs:
          Status: ENABLED
      Name: !Sub ${ServiceName}-codebuild
      ServiceRole: !Ref CodeBuildServiceRole

  SampleCodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub ${ServiceName}-codepipeline
      RoleArn: !GetAtt CodePipelineServiceRole.Arn
      ArtifactStore:
        Type: S3
        Location: !Ref ApplicationDeployArtifactBucket
      Stages:
        - Name: Source
          Actions:
            - Name: download-source
              ActionTypeId:
                Category: Source
                Owner: ThirdParty
                Version: 1
                Provider: GitHub
              Configuration:
                Owner: !Ref GitHubOwner
                Repo: !Ref GitHubRepositoryName
                OAuthToken: !Ref GitHubOAuthToken
                Branch: master
              OutputArtifacts:
                - Name: SourceOutput
        - Name: Build
          Actions:
            - Name: BuildAction
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref SampleCodeBuild
              RunOrder: 1
              InputArtifacts:
                - Name: SourceOutput
              OutputArtifacts:
                - Name: BuildOutput
```

※`CloudFormation`の全量は以下を参照してください。
https://github.com/Thirosue/cross-accout-deploy-sample/blob/master/provisioning/pipeline.yaml

##### Deployステージの設定

> 上記で作成したパイプラインに`Deploy`ステージを追加します。

<img width="631" alt="スクリーンショット 2020-01-12 20.45.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/ae57ffff-6a52-7378-b432-fa7ede88d932.png">

> `Deploy`アクションを追加する。
> ->Amazon ECS(ブルー/グリーン)を選択し、ビルドで作成した`BuildOutput`を入力アーティファクトに指定します。

<img width="1271" alt="スクリーンショット 2020-01-12 20.47.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/2af6d371-81a3-d923-602d-eaccb2c1cb4d.png">

<img width="1197" alt="スクリーンショット 2020-01-12 20.48.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/1e32de7b-2aef-c971-2e0e-0790c2d44f70.png">

### 自動デプロイ確認

> 変更を`GitHub`にPushします。
> ->サンプルプロジェクトであれば、[index.html](https://github.com/Thirosue/cross-accout-deploy-sample/blob/master/public/index.html "index.html")のタイトルを修正してみてください。

以下のとおり正常にデプロイされるはずです。

<img width="1368" alt="スクリーンショット 2020-01-12 21.38.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73176/75b69fd5-41bc-4d4b-d2d8-5088440cc053.png">