【GitHub+AWS ECS】CI/CDパイプラインを使ったECSの自動デプロイ(ローリングアップデート)をやってみた -2

はじめに

最初にこの場をお借りして、感謝申し上げます。「AWSのECS環境を構築してみる」「AWS ECSで自動デプロイを組んでみる」の記事を大変参考にさせていただきました。心よりお礼申し上げます。

本記事では、これらの記事をベースにしながら、初心者としてつまずいた点、疑問に思った点などを織り交ぜながら記述します。

長くなりましたので二つに分割しました 1-ECS環境構築、2-自動デプロイ設定(本記事)

CI/CD環境は GitHubリポジトリ → GitHub接続 → AWS CodePipelineで構築しました。

自動デプロイの設定

前提条件

Amazon EC2インスタンスの起動 Amazon Linux 2023
以下、Session Manager を使用して 接続したEC2をローカル環境としています。

EC2にアタッチするIAMロール
・AmazonSSMManagedInstanceCore
・AmazonEC2ContainerServiceforEC2Role
 :ECSタスクの実行やコンテナ操作、CloudWatch Logs へのログ送信のため
・AmazonEC2ContainerRegistryFullAccess:DockerでECRにプッシュするため
 
ECS環境はpart1で構築済み
 

buildspec.ymlファイルを作成する

AWS CodeBuild でビルドプロセスを定義するために使用される YAML フォーマットの構成ファイルのこと。このファイルでは、ビルドの各フェーズ(pre_build、build、post_build)で実行されるコマンドを指定できます。
ファイルは、AWS CodeBuild を使用して Docker イメージをビルドし、Amazon ECR にプッシュするためのプロセスを定義しています。各フェーズで必要なコマンドが実行され、最終的にはイメージ定義ファイルが生成され、ECS などのサービスで使用されることになります。

.
├ src
│ └ index.html
├ Dockerfile
└ buildspec.yml

buildspec.ymlファイルの内容を書き込む

version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com
      - REPOSITORY_URI=<aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/test-repo
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo Writing image definitions file...
      - printf '[{"name":"container01","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json

※自分で変更する部分
<aws_account_id>
リージョン
REPOSITORY_URI:ECR のリポジトリの URI
container01:Docker イメージを参照するサービスのタスク定義のコンテナ名

GitHub リポジトリの作成

  1. GitHub にてリポジトリを作成しておきます。例:リポジトリ名:ecsautodeploytest
  2. Webhookの作成
    a. GitHubリポジトリに移動し、SettingsWebhooksに進みます
    b.Payload URL:

    https://codepipeline.ap-northeast-1.amazonaws.com/webhooks

    c. Content type: application/json を選択してください。
    d. SSL Verification
    :「Enable SSL verification」にチェックを入れてください。

GitHubのWebhook: プログラムのリポジトリをホスティングしているGitHubでは、プルリクエストやコミットが行われた際にWebhooksを利用してCI/CDパイプラインをトリガーし、ビルドやデプロイの自動処理を開始できます。

当初、Webhookの存在をしらなかったので、パイプライン作成画面でエラーが出て詰まりました。

ローカルリポジトリの作成~初回プッシュ

Git をインストール

sudo dnf install git
git --version

Git の初期設定

git config --global user.name "あなたのユーザ名"
git config --global user.email "あなたのメールアドレス"

ローカル環境で Git リポジトリを初期化して Remote に追加しておきます。

Gitを使ってローカルリポジトリを作成し、それをGitHubのリモートリポジトリにプッシュ(アップロード)する

git init
git add .
git commit -m "My first commit"
git branch -M main
git remote add origin https://github.com/[ユーザ名]/ecsautodeploytest.git
git push -u origin main
  1. git init
    現在のディレクトリをGitリポジトリとして初期化します。
  2. git add .
    カレントディレクトリ以下にあるすべてのファイルをGitのインデックス(ステージングエリア)に追加します。
  3. git commit -m "My first commit"
    ステージングエリアにある変更をローカルリポジトリに「コミット」します(=履歴として保存します)。
  4. git branch -M main
    現在のブランチをmainブランチにリネームします。以前のGitではデフォルトブランチの名前はmasterでしたが、現在は多くのリポジトリでmainがデフォルトとして使われています。
  5. git remote add origin https://github.com/[ユーザ名]/ecsautodeploytest.git
    ローカルリポジトリに「リモートリポジトリ」との関連を設定します。
    originという名前で、GitHub上にあるリモートリポジトリを指定します。https://github.com/[ユーザ名]/ecsautodeploytest.gitはリモートリポジトリのURLです。これにより、ローカルリポジトリとGitHub上のリポジトリが紐付けられ、後でプッシュやフェッチができるようになります。
  6. git push -u origin main
    mainブランチをリモートリポジトリ(origin)にプッシュします。
    git pushはローカルリポジトリの変更をリモートリポジトリに送信するコマンドです。ここでは、mainブランチをリモートリポジトリのmainブランチにアップロードしています。uオプションを使うことで、今後このブランチをデフォルトの追跡対象に設定し、次回以降git pushとするだけでリモートブランチと同期が取れるようになります。

余談:
Gitにおけるブランチ名とは、ソースコードの変更履歴を分岐させる際に使用する名前のこと。Gitでは、リポジトリの中で複数のブランチを作成し、それぞれに異なる作業を並行して進めることができます。ブランチは、ある時点のコードのスナップショットを指すポインタのようなものであり、独立して変更を加えられます。

CodePipeline の設定を行う

  1. AWS コンソールからCodePilelineを選択

  2. パイプラインを作成する

  3. 任意のパイプライン名を設定(例:ecsAutoDeployPipeline

  4. サービスロール:新しいサービスロール

  5. 次に

  6. ソースプロバイダーとしてGitHub(バージョン2)を選択

  7. 接続するを押下し、任意の接続名を設定。(例:GitHubConnection

  8. 接続を行い、GitHub 側の画面で認可を行う。

  9. 新しいアプリをインストールするを選択し、連携対象のリポジトリを選択。

  10. 接続ボタンを押下

  11. リポジトリ名から、対象のリポジトリを選択。(既に接続済みのものから選択できます)

  12. ブランチ名から、mainを選択

  13. 出力アーティファクト形式CodePipeline のデフォルトを選択

  14. トリガーはフィルターを指定

    トリガー (Trigger):
    パイプラインを自動で開始するために設定する条件のこと

    1. トリガータイプ (Trigger Type):
      パイプラインがどのようなアクションで自動的に開始するかを決めます。
      トリガータイプの選択肢:
      フィルターなし: アクション設定の一部として指定されたデフォルトのブランチへのプッシュ時にパイプラインを開始します。
      フィルターを指定: コードプッシュのブランチ名など、特定のフィルターでパイプラインを開始し、正確なコミットを取得するフィルターを追加します。これにより、変更時に自動的に開始されないようにパイプラインも設定されます。
      変更を検出しない: パイプラインが自動で起動されません(手動起動のみ)。
    2. イベントタイプ (Event Type):
      パイプラインを自動的に開始するための具体的なイベントを選択します。
      イベントタイプの選択肢:
      プッシュ: リポジトリに新しいコミットがプッシュされたときにトリガーされます。
      プルリクエスト: プルリクエスト(PR)が作成、更新、またはマージされたときにトリガーされます。
    3. フィルタータイプ (Filter Type):
      どのブランチやタグが対象かを設定します。
      フィルタータイプの選択肢:
      ブランチ: 特定のブランチがターゲットになります。例えば、mainブランチなど。
      タグ: 特定のタグがターゲットになります。Gitのタグは特定のリリースやマイルストーンを示すために使われます。
    4. ブランチ (Branch):
      パイプラインを開始するために、どのブランチにプッシュされた場合にトリガーするかを設定します。
      設定例:
      含める: 特定のブランチにプッシュされた場合にパイプラインを開始する。※フィルタータイプでブランチにチェックを入れた場合、こちらにも記入する。今回はmain
      除外: 特定のブランチやファイルを除外したい場合はここで指定します。
    5. ファイルパス – オプション (File Path):
      プッシュされたファイルに基づいて、パイプラインをトリガーする条件を設定できます。
      設定例:
      含める: 特定のファイルパスが含まれる場合にトリガーを発動する。
      除外: 特定のファイルパスが含まれていない場合にのみトリガーを発動する

    参考:Filter triggers on code push or pull requests

  15. ビルドステージを追加するで、AWS CodeBuildを選択し、プロジェクトを作成

    a. プロジェクト名に任意の名前を設定(例:ecsAutoDeployBuild
    b. 環境イメージマネージド型イメージ
    c. オペレーティングシステムAmazon Linux2
    d. ランタイムStandardを選択。
    e. イメージaws/codebuild/amazonlinux2-x86_64-standard:5.0を選択。
    f. イメージのバージョン そのまま。
    g. 追加設定>特権付与にチェック。
    h. VPCは該当のものを選択
    i. サブネット:
    ECSが存在するサブネットを選択 複数のAZにまたがるように → VPC設定の確認
    j. セキュリティグループ設定
     -インバウンドルール:設定なし
     -アウトバウンドルール
      タイプ: HTTPS
     プロトコル: TCP
     ポート範囲: 443
     送信先: 0.0.0.0/0

    k.ビルド仕様:buildspecファイルを使用する
    l. CloudWatch logsの設定を行う
    m. CodePipeline に進む

  16. ビルドタイプは単一ビルドを選択。

    単一ビルド:1回のトリガーにつき1つのビルドを実行
    バッチビルド:複数のビルドをまとめて1つのトリガーで実行。結果を1つの「バッチ」として扱うことができ、複数のビルドを並列で処理することができます。

  17. 次に

  18. デプロイステージを追加するページで、デプロイプロバイダAmazon ECSに設定

  19. クラスター名でサービスを実行するクラスタを選択

  20. サービス名で更新するサービスを選択

  21. 次に

  22. 確認画面で、内容を確認し、パイプラインを作成するを押下
    ※このタイミングでいったんデプロイが動きますが、ECR 側に接続する権限を付与していないので必ずエラーになります

Amazon ECR 権限を CodeBuild ロールに追加する

  1. AWS コンソールでIAMからロールを選択します。
  2. 検索ボックスにcodebuild-と入力し、CodePipeline ウィザードによって作成されたロールを選択
    3.AmazonEC2ContainerRegistryPowerUserを選択し、ポリシーをアタッチを押下

動作確認

ソースコードの変更をコミットした後、CodePipelineの画面でデプロイ状況を確認します。

  1. ソースコードの変更:ローカル環境で対象のソースコードを変更。たとえば、index.htmlや他のファイルを編集。

  2. 変更をコミット:変更したファイルをGitに追加し、コミット。

    git add .
    git commit -m "Updated source code for deployment"
    
  3. リモートリポジトリにプッシュ:変更をGitHubにプッシュ。

    git push origin main
    

    mainはデフォルトのブランチ名です。自分のブランチ名に置き換えてください。

  4. CodePipelineの確認:
    AWS Management Consoleにログインし、CodePipelineの画面に移動。プッシュしたコードに基づいて、新しいパイプラインの実行がトリガーされるはず。パイプラインの進行状況を監視。

  5. デプロイ状況の確認:
    CodePipelineが各ステージ(ソース、ビルド、デプロイ)を通過するのを確認。特に「デプロイ」ステージでECSに正常にデプロイされていることを確認。各ステージの状態が「成功」となっていることを確認

  6. ECSサービスの確認:
    AWS Management ConsoleからECSのダッシュボードに移動、
    該当のECSクラスターを選択し、サービスの状態が更新されたことを確認

  7. アプリケーションの動作確認:
    ブラウザやAPIクライアントを使用して、アプリケーションのエンドポイントにアクセスし、変更が反映されているかを確認


まとめ

この記事では、参考にさせていただいたブログをもとに、GitHubとAWS ECS (Fargate) を用いて自動デプロイの仕組みを構築しました。初心者としての視点を活かし、つまづいたポイントも紹介しましたので、これから同じようにチャレンジする方にとって少しでも参考になれば幸いです。

感想

手順通りに手を動かせば完成するものの、個々のサービスの理解はまだまだ足りないと思いました。日々学習ですね。

参考

【AWS Black Belt Online Seminar】AWS CodeBuild

Last modified: 2024-10-21

Author