aws ecs

この記事では、GitHub Actionsを利用してAmazon ECSへのデプロイを自動化する方法について解説します。

参考

前提

  • AWSアカウント
  • IAM Identity Centerに登録されたユーザー
    詳しくはこちらの手順を参照してください。
  • GitHubリポジトリ

環境

  • Ubuntu 22.04.3 LTS (WSLで起動している)
  • Docker Engine 26.0.0
  • Laravel 11

デプロイ手順

  1. プロジェクトをデプロイする
  2. OIDC IDプロバイダを作成する
  3. GitHub OIDC IDプロバイダ用のロールを作成する
  4. リポジトリのシークレットにロールを追加する
  5. リポジトリ内にタスク定義を作成する
  6. ワークフローを作成する
  7. ワークフローを確認する

1. プロジェクトをデプロイする

まず、何かプロジェクトをECSにデプロイします。
詳細はこちらのガイドを参照してください。

2. OIDC IDプロバイダを作成する

AWSの認証にはOpenID Connect(OIDC)を使用します。
このページによると、OpenID Connect (OIDC)を使用すると、GitHub ActionsのワークフローがAWSのリソースにアクセスできるようになり、長期保存のAWS認証情報をGitHubのシークレットとして保存する必要がなくなります。

OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in Amazon Web Services (AWS), without needing to store the AWS credentials as long-lived GitHub secrets.

OIDC IDプロバイダを作成するには、AWSマネジメントコンソールのIAMを開き、「Identity providers」をクリックします。

IAMのサイドバー

「Add provider」をクリックします。

Identityプロバイダー一覧画面

「OpenID Connect」を選択し、以下の情報を入力します(こちらのドキュメント参照)

Provider URL https://token.actions.githubusercontent.com
Audience sts.amazonaws.com

Identityプロバイダー作成画面

3. GitHub OIDC IDプロバイダ用のロールを作成する

IAMの「Roles」に移動します。

IAMのサイドバー

「Create role」をクリックします。

ロール一覧画面

「Web identity」を選択します。

Select trusted entity画面1

以下の情報を入力して「Next」をクリックします。

項目 説明
Identity provider 作成したOIDC IDプロバイダ
Audience 設定したAudience
GitHub organization GitHubユーザー名
GitHub repository このロールを使用するリポジトリ名。すべてのリポジトリに適用するには * を使用する。
GitHub branch 対象ブランチ。すべてのブランチに適用するには * を使用する。

Select trusted entity画面2

「Add permission」画面でも「Next」をクリックします。
任意のロール名と説明を入力し、「Create role」をクリックします。

最終画面

次に、必要なポリシー(ECR、ECS、IAMについて)をインラインポリシーとして追加します。
AWSマネジメントコンソール上で、作成したロールをクリックして「Create inline policy」をクリックします。

ロール一覧画面

JSONタブに切り替え、以下のポリシーを入力します。

ECRについて:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr:BatchGetImage",
                "ecr:CompleteLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:InitiateLayerUpload",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage"
            ],
            "Resource": "arn:aws:ecr:<Your repository region>:<Your Account ID>:repository/<Your repository name>"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ecr:GetAuthorizationToken",
            "Resource": "*"
        }
    ]
}

「Next」をクリックし、任意のポリシー名を入力して「Create policy」をクリックします。

ECSとIAMについても同様に作成します。

ECSについて:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecs:UpdateService",
                "ecs:RegisterTaskDefinition",
                "ecs:DescribeServices"
            ],
            "Resource": [
                "arn:aws:ecs:<Your cluster region>:<Your Account ID>:service/<Your cluster name>/*",
                "arn:aws:ecs:<Your cluster region>:<Your Account ID>:task-definition/<Your task definition name>:*"
            ]
        }
    ]
}

IAMについて:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::<Your Account ID>:role/<Your task execution role name>"
        }
    ]
}

4. リポジトリのシークレットにロールを追加する

GitHubリポジトリに移動し、「Settings」をクリックします

GitHubリポジトリ

「Secrets and variables」 > 「Actions」をクリックします。

Click “Secrets and Variables” > “Actions”.

Settings

「New repository secret」をクリックします。

Actions secrets and variables

名前(例:ROLE_TO_ASSUME)と、先ほど作成したロールのARNを入力して「Add secret」をクリックします。

シークレット作成画面

5. リポジトリ内にタスク定義を作成する

.aws/task-definition.json などのファイル名で、タスク定義のJSONファイルをリポジトリ内に保存します。

6. ワークフローを作成する

GitHubリポジトリの「Actions」をクリックします。

GitHubリポジトリ

「New workflow」をクリックします。

Actions

「Deploy to Amazon ECS」の「Configure」を選択します。

Choose a workflow画面

このワークフローでは、DockerイメージをビルドしてECRにプッシュし、タスク定義の「image」をプッシュしたものに置き換え、ECSにデプロイします。

YAMLファイル内の環境変数を実際の値に置き換えます。

AWS_REGION: MY_AWS_REGION                   # 好きなAWSリージョン 例: us-west-1
ECR_REPOSITORY: MY_ECR_REPOSITORY           # ECRリポジトリ名
ECS_SERVICE: MY_ECS_SERVICE                 # ECSサービス名
ECS_CLUSTER: MY_ECS_CLUSTER                 # ECSクラスター名
ECS_TASK_DEFINITION: MY_ECS_TASK_DEFINITION # GitHubリポジトリのECSタスク定義のパス
                                               # 例: .aws/task-definition.json
CONTAINER_NAME: MY_CONTAINER_NAME           # タスク定義の「containerDefinitionsset」にあるコンテナ名

OIDC用に id-token: writepermissions に追加します。

permissions:
  id-token: write # 追加
  contents: read

「Configure AWS credentials」ステップを以下のように修正します。

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v1
  with:
    role-to-assume: ${{ secrets.ROLE_TO_ASSUME }}  # 変更
    aws-region: ${{ env.AWS_REGION }}

Dockerfile がルートディレクトリ以外にある場合は -f オプションでパスを指定します。

例:

docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f ./docker/web/Dockerfile .

ファイル名を入力し(例: aws.yml)、「Commit changes」をクリックします。

Workflow生成画面

このワークフローは main ブランチに変更がプッシュされたときに実行されるため、上記のコミットで実行されたはずです。

on:
  push:
    branches: [ "main" ]

7. ワークフローを確認する

GitHubリポジトリの「Actions」をクリックします。

GitHubリポジトリ

以下のような画面が表示されていればワークフローは正しく完了しています。

Workflow画面