NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

改めてCI/CDパイプラインを使ったECS自動デプロイの流れを整理する

本記事は  【コンテナウィーク】  1日目の記事です。
💻  告知記事  ▶▶ 本記事 ▶▶  2日目  📱

こんにちは。梅原です。

皆さんはCI/CDパイプラインやってますか。昨今はパイプラインファーストという考え方もあり、ソースコードの変更反映をトリガーにテストやビルド、デプロイまで自動でやることは多いのではないでしょうか。

今回はAWSでCI/CDパイプラインを実現するためのサービスであるCodeシリーズ(CodeCommit、CodeBuild、CodeDeploy、CodePipeline)を使ってECSへ自動デプロイする流れを見ていきます。

AWSでCI/CDパイプラインを実現するために

そもそもCI/CDパイプラインは、継続的インテグレーション/継続的デリバリーの略で、これまで手動でしていたテストやビルド、デプロイ作業を自動化・高速化するために使われるものです。 CI/CDパイプラインを使うことで、開発効率やリリース効率を向上できるようになります。

AWSでCI/CDパイプラインを実現するためには、以下4つのサービスを使います。

  • AWS CodeCommit (ソースコード管理)

  • AWS CodeBuild (ソースコードのテストやビルド)

  • AWS CodeDeploy (ビルドされたものからデプロイを行う)

  • AWS CodePipeline (上記3サービスを統括)

CodePipelineでCodeCommit、CodeBuild、CodeDeployを繋げることで、ソースコードの変更反映をトリガーにデプロイまで自動で実施することができます。
リポジトリの反映からCodePipelineでECSへデプロイするまでの流れとして、

  1. リポジトリへの反映
  2. ソースステージ
  3. ビルドステージ
  4. デプロイステージ

の4ステージあります。

リポジトリへの反映は文字通り、ソースリポジトリへソースコードのpushやマージリクエストの取り込みといったCodeCommitへの変更反映を実施します。

ソースステージでは、リポジトリの反映をトリガーに、後続のビルドステージに必要なソースコードをリポジトリから取得します。 トリガー元のソースリポジトリはGitHubやBitBucket、S3、ECRなどがあり、最近ではSaaS版のGitLabも対応しました。

ビルドステージでは、buildspec.yamlに記述された命令を元にソースコードのテストやビルド、dockerイメージのビルド、dockerイメージをレジストリにpushします。 JenkinsといったOSSを使用する場合は別途サーバーが必要となりますが、Codebuildではサーバーを意識する必要がありません。
また、ビルド上で出力される成果物のことをビルドアーティファクトと呼び、後続のデプロイステージで利用されます。 ソースコードはソースアーティファクトと呼ばれ、CodeBuildの処理される前にも使用されています。

最後のデプロイステージでは、ソースアーティファクトやビルドアーティファクトを元に、ECSなどにデプロイを実施します。 デプロイ対象はECSだけでなく、EC2はもちろんS3やCloudFormationなどへも可能です。
ECSにデプロイする方法として、ローリングアップデートとBlue/Greenデプロイがあります。 2つのデプロイ方法の比較は以下ブログを参照ください。 tech.nri-net.com

ローリングアップデートとBlue/Greenデプロイで必要なファイルが異なります。今回はBlue/Greenデプロイを説明します。
Blue/GreenデプロイはCodeDeployと統合されており、CodeDeployのデプロイ情報を記載したappspec.yamlとイメージの場所を示すimageDetail.json、タスク定義書の元が必要になります。
必要なファイルの違いは以下を参照ください。

docs.aws.amazon.com

ECSサービスにデプロイするときは、新しいコンテナイメージを向いたタスク定義書を作成し、そのタスク定義書を元にECSサービスを更新する必要があります。 新しいタスク定義書の作成やECSサービスのアップデートといった部分は、CodePipelineないしCodeDeployでよしなにやってくれます。 ビルドステージで新しいコンテナイメージのURIの情報をビルドアーティファクトとしてimageDetail.jsonで出力します。 CodeDeployでソースコードに含めておいたappspec.yamlとtaskdef.jsonのプレースホルダーをビルドアーティファクトから設定し、CodeBuildでpushした新しいコンテナイメージをデプロイしてくれます。

これらを図にまとめると以下になります。 CodeCommitに変更を反映した後、CodePipelineが実行され、CodeBuild上でソースコードのテストやdockerイメージのビルドされ、CodeDeployソースアーティファクトとビルドアーティファクトを元にデプロイされます。

詳細の流れを見ていく

ただ、この図だけでは各サービスが単独で動作しており、まだ処理のつなぎの流れは見えないと思います。 ソースコードへのpushからデプロイまで各ステージの詳細の流れを初めから見ていこうと思います。

1. ソースコードの変更反映

開発者はデプロイを開始したいときは、CodeCommitへソースコードの変更をpushします。 CodeCommitの変更がイベントとしてEventBridgeへ渡されて、EventBridgeがパイプラインを実行し後続のステージへ繋がります。(CodePipelineの検出方法としてCloudWatch Eventsを設定した場合)
図ではmainブランチに直でpushしていますが、通常はマージリクエストを出して特定のブランチに取り込むと思います。そのようなマージリクエストの変更をトリガーに設定できます。

2. ソースステージ

実行されたCodePipelineはソースステージへと入り、CodeCommitからソースコードの取得がなされます。 CodePipelineに指定したサービスロールでCodeCommitのリポジトリを取得し、ソースアーティファクトとしてS3に保存します。

3. ビルドステージ

S3内のソースアーティファクトのbuildspec.yamlに記述した命令を元にテストやビルド、ECRへのpush、imageDetail.jsonの作成を実施します。 imageDetail.jsonはビルドアーティファクトとしてS3に保存されます。

4. デプロイステージ

ソースアーティファクトのappspec.yamlとtaskdef.json、ビルドアーティファクトのimageDetail.jsonを元にCodeDeployがデプロイをしてくれます。その後はCodeDeploy内でBlue/Greenデプロイを開始してくれます。 先述の通り、タスク定義書の作成やECSサービスの更新等のコマンドは不要でサービス側でよしなにやってくれます。

最後に

この通り、CI/CDパイプラインはただ各サービスが単独で動作しているわけではなく、ファイルの受け渡しとしてS3や変更反映イベント発行でEventBridgeといったサービスが使用されています。
このブログで記載したCI/CDパイプラインが基本の形だと思います。要件によっては承認フローを挟んだり、Lambdaで処理を挟んだりといろいろなことが必要になると思います。CodePipelineではそのようなことも可能です。

また、最近のアップデートでCodePipeline v2が出て動的なパラメーターを設定できたり、CodeBuildはコンピュートタイプとしてLambdaを選択できるようになっています。より便利により柔軟なパイプラインが組めるようになっています。

執筆者: 梅原 航 インフラエンジニア。 主にAWSを使ってます。