0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Actionsで安全にECS on Fargateへのデプロイ・ロールバックを行うためのサンプル

Last updated at Posted at 2024-09-09

目的

  • ECS on Fargateで動いてるサイトがある
    1. このサイトへのデプロイを完全自動化したい
    2. 何か問題が合った時にすぐ切り戻せるようにしたい

目的を達成するための手段

  1. デプロイまでの処理をGitHub Actionsで完全自動化する
  2. ロールバック用のワークフローを作っておき、問題があったときに手動実行できるようにしておく

デプロイまでの処理をGitHub Actionsで完全自動化して何も問題ないの?危なくない?

  • GitHub Actionsを使用してDockerイメージをECRにプッシュし、ECS on Fargateで動作しているサイトを更新する自動化プロセスは一般的で、適切に設定すれば問題なし。逆に適切に設定されたCI/CDパイプラインは、デプロイプロセスの効率と信頼性を向上させ、人為的ミスを減らすことができる。
  • ただし、いくつかの重要なポイントを考慮する必要がある:
    1. 自動化の安全性:
      • 適切なIAM権限設定を行い、必要最小限の権限のみを付与します。
      • OIDCを使用してGitHub ActionsとAWSの認証を安全に行います。
    2. イメージのタグ付け:
      • 適切なタグ付け戦略を使用し、各ビルドを一意に識別できるようにします。
      • 例えば、GitコミットSHAやビルド番号をタグに含めます。
    3. ECSサービスの更新:
      • 新しいイメージをプッシュした後、ECSサービスを更新するステップを含めます。
      • ローリングアップデートを使用して、ダウンタイムを最小限に抑えます。
    4. テストと検証:
      • プロダクション環境にデプロイする前に、ステージング環境でテストを行います。
      • 自動テストをワークフローに組み込みます。
    5. ロールバック戦略:
      • 問題が発生した場合に備えて、簡単にロールバックできる仕組みを用意します。
    6. 監視とアラート:
      • デプロイ後のアプリケーションの健全性を監視します。
      • 問題が発生した場合に迅速に通知を受け取れるようにします。
    7. ブランチ保護:
      • 本番環境へのデプロイは特定のブランチ(例:main)からのみ行うようにします。
      • プルリクエストのレビューと承認プロセスを設定します。
    8. シークレット管理:
      • AWS認証情報などの機密情報はGitHub Secretsを使用して安全に管理します。

コードサンプル

ECSデプロイまでを自動でやるワークフロー(ロールバック考慮済み):

deploy_to_ecs.yml
name: Deploy to ECS

on:
  push:
    branches: [ main ]

# OIDCトークンの生成と読み取り権限を設定
permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    # リポジトリのコードをチェックアウト
    - uses: actions/checkout@v2

    # AWS認証情報を設定(OIDCを使用)
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        role-to-assume: arn:aws:iam::<YOUR-AWS-ACCOUNT-ID>:role/<YOUR-IAM-ROLE-NAME>
        aws-region: us-east-1

    # Amazon ECRにログイン
    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    # Dockerイメージをビルド、タグ付け、ECRにプッシュ
    - name: Build, tag, and push image to Amazon ECR
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        ECR_REPOSITORY: my-ecr-repo
        IMAGE_TAG: ${{ github.sha }} # GitHubのコミットSHAをタグとして使用
      run: |
        # GitHubのコミットSHAをタグ付けしたDockerイメージをビルド
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        # ビルドしたイメージをECRにプッシュ
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

    # ECSサービスを更新
    - name: Update ECS service
      run: |
        # 最新のタスク定義を使用してECSのサービスを強制的に更新
        aws ecs update-service \
          --cluster my-cluster \
          --service my-service \
          --force-new-deployment \
          --task-definition my-task-definition:latest

    # プッシュしたイメージに"production"タグを追加
    - name: Tag as production
      run: |
        # 先ほどプッシュしたGitHub SHAタグ付けイメージに "production" タグも追加
        # これにより、最新のプロダクションイメージを簡単に識別できる
        aws ecr put-image \
          --repository-name my-ecr-repo \
          --image-tag production \
          --image-manifest $(aws ecr batch-get-image \
            --repository-name my-ecr-repo \
            --image-ids imageTag=${{ github.sha }} \
            --query 'images[].imageManifest' \
            --output text)

    # デプロイ情報を記録
    - name: Record deployment
      run: |
        # デプロイに使用したイメージのタグ(GitHub SHA)をファイルに書き込み
        echo ${{ github.sha }} > last_deployed_tag.txt
        # 書き込んだファイルをS3バケットにアップロード
        # これにより、最後にデプロイされたイメージのタグを記録し、必要に応じてロールバックできるようにする
        aws s3 cp last_deployed_tag.txt s3://my-deployment-bucket/last_deployed_tag.txt
rollback_ecs_service.yml
### ECSロールバック用のワークフロー:
 name: Rollback ECS Service

# 手動でワークフローを実行できるようにする
on:
  workflow_dispatch:

# OIDCトークンの生成と読み取り権限を設定
permissions:
  id-token: write
  contents: read

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
    # AWS認証情報を設定(OIDCを使用)
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        role-to-assume: arn:aws:iam::<YOUR-AWS-ACCOUNT-ID>:role/<YOUR-IAM-ROLE-NAME>
        aws-region: us-east-1

    # S3から最後にデプロイされたタグを取得
    - name: Get last deployed tag from S3
      run: |
        # S3バケットから最後にデプロイされたタグ情報をダウンロード
        aws s3 cp s3://my-deployment-bucket/last_deployed_tag.txt .
        # ファイルの内容を環境変数に設定
        ROLLBACK_TAG=$(cat last_deployed_tag.txt)
        # GitHub Actionsの環境変数としてROLLBACK_TAGを設定
        echo "ROLLBACK_TAG=$ROLLBACK_TAG" >> $GITHUB_ENV

    # Amazon ECRにログイン
    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    # ロールバック用のイメージでECSサービスを更新
    - name: Update ECS service with rollback image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        ECR_REPOSITORY: my-ecr-repo
      run: |
        # ECSサービスを更新し、ロールバック用のイメージを指定
        aws ecs update-service \
          --cluster my-cluster \
          --service my-service \
          --task-definition my-task-definition \
          --force-new-deployment \
          --overrides '{
            "containerOverrides": [{
              "name": "container-name",
              "image": "${ECR_REGISTRY}/${ECR_REPOSITORY}:${ROLLBACK_TAG}"
            }]
          }'

    # デプロイメントの完了を確認
    - name: Verify deployment
      run: |
        # ECSサービスが安定状態になるまで待機
        aws ecs wait services-stable \
          --cluster my-cluster \
          --services my-service
        # ロールバックの完了を通知
        echo "Rollback completed successfully"

ECRのタグ付け戦略イメージの具体例

  1. デプロイ前の状態:
my-ecr-repo:2023-09-10-v1.0.5 (最新のデプロイ)
my-ecr-repo:production (= 2023-09-10-v1.0.5)
my-ecr-repo:2023-09-05-v1.0.4
my-ecr-repo:2023-09-01-v1.0.3
  1. 新しいバージョン v1.0.6 をデプロイ後:
my-ecr-repo:2023-09-15-v1.0.6 (新しくデプロイされたイメージ)
my-ecr-repo:production (= 2023-09-15-v1.0.6)
my-ecr-repo:2023-09-10-v1.0.5 (以前のproduction)
my-ecr-repo:2023-09-05-v1.0.4
my-ecr-repo:2023-09-01-v1.0.3
  1. 問題が発生し、ロールバックが必要な状況:
my-ecr-repo:2023-09-15-v1.0.6 (問題のあるイメージ)
my-ecr-repo:production (= 2023-09-15-v1.0.6)
my-ecr-repo:2023-09-10-v1.0.5 (ロールバック先の安定バージョン)
my-ecr-repo:2023-09-05-v1.0.4
my-ecr-repo:2023-09-01-v1.0.3
  1. 2023-09-10-v1.0.5 へのロールバック後:
my-ecr-repo:2023-09-10-v1.0.5 (ロールバックされたイメージ)
my-ecr-repo:production (= 2023-09-10-v1.0.5)
my-ecr-repo:2023-09-15-v1.0.6 (問題のあったイメージ)
my-ecr-repo:2023-09-05-v1.0.4
my-ecr-repo:2023-09-01-v1.0.3

この例では:

  • 各イメージは日付とバージョン番号の組み合わせでタグ付けされています(例:2023-09-15-v1.0.6)。
  • production タグは常に現在のプロダクション環境で使用されているイメージを指しています。
  • ロールバック時は、以前の安定したバージョン(この場合は2023-09-10-v1.0.5)に production タグを移動させます。
  • 全てのイメージバージョンが保持されているため、必要に応じて任意のバージョンにロールバックできます。

この命名規則により:

  • デプロイの日付が明確になります。
  • バージョン番号により、イメージの順序や進捗が分かりやすくなります。
  • production タグにより、現在の本番環境のイメージが一目で分かります。

この方法を使用することで、イメージの管理がより直観的になり、デプロイ履歴の追跡やロールバックの実行が容易になります。

注意点:

  • この方法では多くのイメージが保存されるため、ECRのライフサイクルポリシーを設定して古いイメージを自動的に削除することをお勧めします。ただし、productionタグが付いたイメージは削除されないようにポリシーを設定する必要があります。

おわりに

  • 作ってみて思ったけど、ロールバック用のワークフローは、特定のこのバージョンに戻したい!には対応できない。
  • バージョン指定してロールバックできるようにしないと。が今後の課題。
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?