LoginSignup
0
0

[Terraform]Github ActionからECSへデプロイ(タスク定義の更新)する場合に、タスク定義をJsonファイルとして分離させず、Terraformで直接管理する方法

Posted at

概要

ECSで稼働させているサービスをGithubActionからデプロイする際は、ECSタスク定義をJsonファイルで定義して、GithubActionのワークフロー内でaws-actions/amazon-ecs-render-task-definition@v1を利用してタスク定義を上書きした上でECSリソースに反映する、というのが一般的な流れです。

TerraformなどのIaCを利用している場合は、Terraform内で対象のjsonファイルを呼び出すことにより、タスク定義の二重管理についても避けることができます。

しかし、このようにECSのタスク定義を管理する箇所を分離すると、感覚的にどこで何を管理しているのか分かりにくくなります。そこで、ECSのタスク定義をTerraformで直接管理しつつ、GithubActionでデプロイするための手順を考え、その手順について以下にまとめました。

ECSのタスク定義をterraformで定義する

ECSのタスク定義の例を以下に示します。
注目する点は、imageのバージョンを変数で定義している点です。Github Actionでデプロイする際に、この変数を更新することになります。

ecs.tf
#タスク定義
resource "aws_ecs_task_definition" "example_task" {
  family                = "example-task"
  requires_compatibilities = ["FARGATE"]
  network_mode          = "awsvpc"
  cpu    = 256
  memory = 512
  execution_role_arn    = aws_iam_role.ecs_task_execution_role.arn

  container_definitions = jsonencode([{
    name  = "example-container",

    #imageのバージョンを変数で定義
    image = "example-image:${var.image_version}",

    essential: true,
    memoryReservation = 256,
    memory = 512,
    cpu = 256,
    portMappings: [
      {
        protocol: "tcp",
        containerPort: 80
      }
    ],
  }])
}

variables.tfには以下のようにimage_versionを空で定義します。

variables.tf
variable "image_version" {}

この記事ではモジュール化した場合の例は示しませんが、例えば上位ディレクトリのmain.tfでECSのモジュールを呼び出す際には、上位ディレクトリのvariables.tfでもimage_versionは空で定義してください。

GithubActionでデプロイする際のワークフローを定義

GithubActionでデプロイする際のワークフローを定義します。
ECRにimageをpushするstepと、terraform applyを実行するstepを定義します。

.github/workflows/deploy.yml
name: deploy

on:
  push:
    branches:
      - main

env:
  AWS_REGION: ap-northeast-1
  #imageのタグをgithubのshaにすることで、常に最新のimageをデプロイする
  IMAGE_VERSION: ${{ github.sha }}

jobs:
  deploy:
    name: Push to ECR
    runs-on: ubuntu-latest

    steps:
      - name: setup aws cli
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      - uses: actions/checkout@v2

      - uses: aws-actions/amazon-ecr-login@v1
        id: amazon-ecr-login

      - name: push ex-repo image to ECR
        env:
          ECR_REGISTRY: ${{ steps.amazon-ecr-login.outputs.registry }}
          ECR_REPOSITORY: ex-image
        run: |
          docker build -t ex-image -f ./Dockerfile.prod ./
          docker tag ex-image:latest ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_VERSION }}
          docker push ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_VERSION }}

  terraform:
    name: Depploy to AWS ECS
    runs-on: ubuntu-latest

    #terraformを管理しているディレクトリに移動
    defaults:
      run:
        working-directory: terraform-folder

    steps:
    - uses: actions/checkout@v2

    #terraformのバージョンを指定
    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        terraform_version: 1.6.3

    #terraform initを実行
    - name: Terraform Init
      run: terraform init
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

    #terraform applyを実行
    #引数にimage_versionを渡す
    - name: Terraform Apply
      run: terraform apply -var "image_version=${{ env.IMAGE_VERSION }}" -auto-approve
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

ポイントとしては、まずGithubActionのワークフローでimageのタグをgithubのshaにすることで、常に最新のimageをデプロイするようにしています。
また、イメージをビルドしてshaをタグに付与しています。
そして、Terraformのワークフローでterraform applyを実行する際に、image_versionにshaを渡しています。

以上の内容をセットアップすることで、ECSのタスク定義をTerraformで直接管理しながら、Github ActionでCDを実現することができます、

運用上の注意点

この方法では、ECS以外のリソースを更新するためにTerraformをapplyする際にも、image_versionを引数として渡す必要が出てきます。AWS CLIやコンソールからの目視で現在のimage_versionを確認する必要があるため、ヒューマンエラーが起きる可能性が高いです。

そのため、Terraformを構築する際にリソース単位でtfstaeを分けるなどの対策が必要になります。

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