LoginSignup
10
14

More than 3 years have passed since last update.

AWS CodePipeline で ECS(Fargate) へ Blue/Green デプロイする

Last updated at Posted at 2019-08-15

[追記:この構成だとひとつ古いDockerイメージしか使われないな:thinking:]

AWS CodePipeline を使って Rails アプリケーションを Fargate を利用した ECS に Blue/Green デプロイします。

デプロイの流れ

  1. Rails アプリのソースコードを変更
  2. GitHub に Push または Pull Request をマージ
  3. CodePipeline のパイプラインが起動
  4. CodeBuild でアプリケーションをビルド
  5. CodeBuild で Docker イメージをビルド
  6. CodeBuild から ECR に Docker イメージを latest タグを付けて登録
  7. CodeDeploy で ECR から Docker イメージを取得して ECS にデプロイ

Rails アプリの Docker イメージは appweb の2つ使用します。

CodePipeline 構成

利用するサービスは以下の通りです。

  • AWS Elastic Container Service (ECS)
    • Fargate
  • AWS CodeBuild
  • AWS CodeDeploy
    • ECS(Fargate) Blue/Green Deploy
  • AWS Elastic Container Registry (ECR)
  • GitHub

CodeBuild と CodeDeploy は事前に作成しておいてください。

全体像

パイプラインの完成形は下図のようになります。
Source ステージでは GitHub と ECR を並列で指定します。Docker イメージ複数使うときは全て追加しておきます。
codepipeline_outline.png

次は GitHub Source です。
GitHub と連携してリポジトリとブランチを指定します。図のブランチは動作確認用に ecs としていますが本番利用時は master にしています。
GitHub Source の 出力アーティファクト はこの先のステージで使用しないのでデフォルト値にしています。
codepipeline_github.png

次は ECR Source です。利用する ECR のリポジトリとタグを指定してください。今回は常に latest をデプロイします。
アクション名出力アーティファクトはこの先のステージと設定ファイルで使用するので web を指定します。
codepipeline_ecr.png

次は Build ステージです。
入力アーティファクト には GitHub Source の出力である SourceArtifact を選択します。
プロジェクト名には事前に作成した CodeBuild のプロジェクトを選択してください。
ビルド結果は BuildArtifact として S3 にアップロードします。アップロードされるファイルは taskdef.json appspec.yaml になります。
codepipeline_build.png

最後は Deploy ステージです。
アクションプロバイダーに ECS のBlue/Green を選択してください。専用の設定項目が表示されます。
入力アーティファクトには ECR アクションと Build ステージのアーティファクトを選択しています。今回は SourceArtifact は使用しません。
CodeDeploy に関する設定は事前に作成したものを選択してください。
codepipeline_deploy.png

Amazon ECS タスク定義BuildArtifacttaskdef.json を指定します。AppSpec ファイルも同様に BuildArtifact のファイルを指定してください。
この2つのファイルは buildspec.yamlfiles セクションで指定されているので、ビルド後に S3 にアップロードされて CodePipeline が利用できるようになります。

AWS の公式ドキュメントでは SourceArtifact を指定していますが、以下のエントリにあるように SourceArtifact が 3MB 以上あるとエラーになるので BuildArtifact を参照しています。

CodeDeployでtask definitionが読み込めない時の対処法 - Qiita

最後に taskdef.json で Docker イメージが参照できるように入力アーティファクトを持つイメージの詳細に ECR Source のイメージを設定します。

設定ファイル

CodePipelie/CodeBuild/CodeDeploy には以下の3ファイルが必要です。すべて GitHub のリポジトリに追加しています。

  • taskdef.json
  • appspec.yaml
  • buildspec.yaml

Blue/Green デプロイを利用するので imagedefinitions.json は不要です。ECR Source を利用するので imageDetail.json も不要です。

各種設定値は環境に合わせて読み替えてください

taskdef.json

.family の値は ECS のタスク定義で設定した名前にします。
.containerDefinitions[0].name は Build ステージで入力した「入力アーティファクトを持つイメージの詳細」に合わせます。
.containerDefinitions[0].image が「タスク定義のプレースホルダー文字」になります。<> も含めて設定します。

{
      "family": {{ ここは ECS task  family に合わせる }},
      "taskRoleArn": "arn:aws:iam::000000000000:role/ecsTaskRole",
      "executionRoleArn": "arn:aws:iam::000000000000:role/ecsTaskExecutionRole",
      "networkMode": "awsvpc",
      "containerDefinitions": [
          {
              "name": "app",
              "image": "<app>",
              "essential": true,
          },
          {
              "name": "web",
              "image": "<web>",
              "portMappings": [
                  {
                      "containerPort": 80,
                      "hostPort": 80,
                      "protocol": "tcp"
                  }
              ],
              "essential": false,
          }
      ],
      "requiresCompatibilities": [
          "FARGATE"
      ],
      "cpu": "256",
      "memory": "512"
}

appspec.yaml

Resources[0].TargetServices.Properties.TaskDefinition<> も含めて以下の通り設定します。
SubnetsSecurityGroups は環境に合わせて変更してください。

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
            ContainerName: web
            ContainerPort: 80
        NetworkConfiguration:
          AwsvpcConfiguration:
            Subnets:
              - subnet-00000000
            SecurityGroups:
              - sg-00000000
            AssignPublicIp: ENABLED

buildspec.yaml

files セクションに appspec.yamltaskdef.json が必要です。

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 ap-northeast-1)
  build:
    commands:
      - echo Build started on `date`
      - echo Compiling assets...
      - echo Building the Docker image...
      - docker-compose -f docker-compose.production.yml build --parallel
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker-compose -f docker-compose.yml push

artifacts:
  files:
    - appspec.yaml
    - taskdef.json
10
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
14