Code三兄弟を使って ECS に継続デプロイ方法



streampack の Tana です。

CodeCommit が Backlog Git に対応していなかったり、CodeXXX が多くて使いにくそうなイメージが
根付いてましたが、AWS Summit Tokyo 2019 にて意外と CodeBuild, CodeDeploy, CodePipeline
などを使ってECS環境にデプロイしているところがあったのでこの機会に試してみました。
`AWS資格試験`のためにも（汗)

## 概要

CodeCommit に登録されたリポジトリにコードを push 後に、
CodeBuild で Docker イメージをビルドし、
ECR にプッシュして、
ECSへ反映させる手順となります。

## 前提条件

- CodeCommit や Github でコード管理している
- 事前にECSで動いている環境がある

## CodeCommit

今回はCodeCommitを使用します。
CodeCommit にてリポジトリを準備し、ビルドしたいアプリケーションのコードを Commit & Push します。

### buildspec.ymlの準備

下記のサンプル buildspec.yml コピーし、お使いのアプリの`runtime-versions`を更新します。
runtime-versions にサポートされている言語・バージョンは下記に記載されています。
https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
また、`<container-definition>` は ECS で使用しているコンテナ名に書き換えます。
コンテナ名は ECS のタスク定義にて確認できます。
編集されたそのファイルは対象のレポジトリ のルートにて commit & push します。

``` buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      # golang: 1.12   # アプリケーションによって書き換え
      # ruby: 2.6

  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region ap-northeast-1)
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $ECR_NAME:$ECR_VERSION .
      - echo docker tag $ECR_NAME:$ECR_VERSION $ECR_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_NAME:$ECR_VERSION
      - docker tag $ECR_NAME:$ECR_VERSION $ECR_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_NAME:$ECR_VERSION
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $ECR_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_NAME:$ECR_VERSION
      - printf '[{"name":"<container-definition>","imageUri":"%s"}]' $ECR_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_NAME:$ECR_VERSION > imagedefinitions.json    # <container-definition> もお使いのコンテナ名に書き換え

artifacts:
  files: imagedefinitions.json
```

ECRのレポジトリやバージョンなどハードコーディングでもいいのですが、
より実戦向きのために、環境変数込みで定義してます。
後ほど説明する `CodeBuild` のプロジェクト作成時に、その環境変数を定義します。

## CodeBuild

注意すべき項目のみ記載してます。

### CodeBuildプロジェクトの作成

Environment設定

<img width="814" alt="codebuild-env2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/f32684b9-d1e7-feb8-4377-0ef1baaf04d3.png">

**要点**

- standard:1.0 でも動く(buildspec.yml に install,runtime-verions の指定が不要)
- docker build を実行を許可するために、 Privileged はチェックする
- Role作成後は `AmazonEC2ContainerRegistryFullAccess` 付与を忘れずに


注意点:
> install 項目などの runtime-versions 設定しなくても大丈夫ですが、 aws/codebuild/standard:2.0 を指定した場合は必須です。


Environment Variables(環境変数)

<img width="811" alt="codebuild-env-vars2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/5638ff3e-95ee-d43b-fa6a-8d0cafd25740.png">

は下記とマッチするように環境変数をセットします。

```
$ECR_ID.dkr.ecr.ap-northeast-1.amazonaws.com/$ECR_NAME:$ECR_VERSION
```

ECR_VERSION (イメージタグ) は`latest` がデフォルトで使われてます。


### IAM Role for CodeBuild and ECR

作成された IAM Role に対して、
`AmazonEC2ContainerRegistryFullAccess`
を付与します。

<img width="969" alt="iam-role-deploy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/049ade35-008b-1bbe-205c-f5cb1780901e.png">

これで ECR にイメージをプッシュできるようになります。

### 単体でビルド実行

手動でビルドして、成功することを確認します。
ここで成功しないと CodePipeline で失敗するでしょう。

## CodePipeline

### ソースプロバイダ選択 ~ CodeCommitとの連携

CodeCommit や Github などのプロバイダを選択します。
今回は CodeCommit を使っているので、CodeCommitのリポジトリとブランチを指定します。

<img width="771" alt="codepipeline-source-provider.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/cb29f8f5-c974-3a91-c017-b43f13c8bff1.png">

### デプロイステージ選択 ~ ECSとの連携

ECS を選択し、
ECSのクラスタ名と
ECSのサービス名を
選択します。

<img width="771" alt="codepipeline-deploy-stage.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/d868321a-fe0b-34c5-71d3-3decc42eb3ae.png">

### 結果の確認

CodeCommit に push 後に実行されるかを確認し、
Deploy まで Succeeded になれば、ECSに最新のコード(ビルドイメージ)
が反映されてます(るはず)。

<img width="808" alt="codepipeline-result.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232803/4f123b71-0d42-9811-9d10-66c856f7423c.png">

### 使ってみての感想

ECSですでに動いていれば、CodeCommit からECSまでのデプロイまでの CI/CD を実現することができました。
ローカルでの build & push は意外に時間がかかり、ローカルPCにも影響するので、意外と使えそうだと実感しました。
Backlog Git サポートされたり、Lambdaなどを使わずにデプロイ結果の slack 連携などができれば移行を検討しそうです。