継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

RDS ログを S3 にアップロードする Python スクリプトを ECS で実行する

タダです.

前回記事で RDS ログを S3 にアップロードする Python スクリプトを Docker で動作するようにしました.今回は GitHub Actions でコンテナイメージを ECR に格納し,EventBridge Scheduler で ECS Runtask を実行するようにしてきます.

sadayoshi-tada.hatenablog.com

コンテナイメージを ECR に格納する

コンテナイメージを ECR に格納する処理は GitHub Actions で行うようにしました.

name: ecr push

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  deploy:
    name: ecr push
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    timeout-minutes: 15
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-1
          role-to-assume: "arn:aws:iam::1234567891012:role/ecr-image-push"
          role-duration-seconds: 1800
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      - name: Build docker images and push its to ECR
        id: build-image
        env:
          registory: ${{ steps.login-ecr.outputs.registry }}
          repository: hoge-repository
          image_tag: latest
        run: |
          docker build . --tag ${{ env.registory }}/${{ env.repository }}:${{ env.image_tag }}
          docker push ${{ env.registory }}/${{ env.repository }}:${{ env.image_tag }}

ECS クラスターと ECS タスク定義を作成する

次に ECS クラスターと ECS タスク定義を作ります.ECS クラスターはコスト観点で ECS Fargate Spot を実行できるようにし,タスク定義は次のように指定しました.

タスク定義の containerDefinitions 抜粋

"containerDefinitions": [
        {
            "name": "rds-log-to-s3-upload",
            "image": "1234567891012.dkr.ecr.ap-northeast-1.amazonaws.com/hoge-repository:latest",
            "cpu": 1024,
            "memory": 2048,
            "portMappings": [],
            "essential": true,
            "entryPoint": [
                "python3",
                "rds_donwload_to_s3_upload.py"
            ],
            "environment": [],
            "mountPoints": [],
            "volumesFrom": [],
            "readonlyRootFilesystem": true,
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-create-group": "true",
                    "awslogs-group": "/ecs/rds-log-to-s3-upload",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "rds-log-to-s3-upload"
                }
            }
        }
    ],

これで ECS Runtask の実行準備が完了です.

EventBridge Scheduler で ECS Runtask を実行する

そして,EventBridge Scheduler で ECS Runtask を実行するようにしていきます.この記事では Terraform で設定を行いました.EventBridge Scheduler で ECS Runtask を実行する際に気をつけたのは input で渡している containerOverrides 部分です.ここではコマンドの上書きを行っています.自分が作成したスクリプトでは引数で Aurora クラスター名とログを格納する S3 バケットを指定する必要があります.その引数をコマンドの上書きとして containerOverrides で行っております.これで input に指定したパラメーターに応じて Aurora クラスターとバケットを分けてログを出したりが可能です.

resource "aws_iam_role" "evnetbridge_scheduler" {
    name = "evnetbridge-scheduler-role"
    assume_role_policy = data.aws_iam_policy_document.eventbridge_scheduler_assume_policy.json
    inline_policy {
      name = "evnetbridge-scheduler-role-inline-policy"
      policy = jsonencode({
        Version = "2012-10-17"
      Statement = [
        {
          Action = [
            "ecs:StopTask",
            "ecs:RunTask",
            "ecs:DescribeTasks",
          ]
          Effect   = "Allow"
          Resource = "arn:aws:ecs:ap-northeast-1:1234567891012:task-definition/hoge-task-definition:*"
        },
        {
          Action   = "iam:PassRole"
          Effect   = "Allow"
          Resource = ["*"]
          Condition = {
            StringLike = {
              "iam:PassedToService" = "ecs-tasks.amazonaws.com"
            }
          }
        },
      ]
    }
}
data "aws_iam_policy_document" "eventbridge_scheduler_assume_policy" {
  statement {
    effect = "Allow"
    actions = [
      "sts:AssumeRole",
    ]
    principals {
      type = "Service"
      identifiers = [
        "scheduler.amazonaws.com",
      ]
    }
  }
}
resource "aws_scheduler_schedule" "test_scheduler" {
    name = "test-scheduler"
    state = "ENABLED"
    schedule_expression = "cron(0 0 * * ? *)"
    schedule_expression_timezone = "Asia/Tokyo"
    flexible_time_window {
      mode = "OFF"
    }
   target {
    arn      = aws_ecs_cluster.hoge.arn
    role_arn = aws_iam_role.hoge.arn
    ecs_parameters {
      task_count          = 1
      launch_type         = "FARGATE"
      task_definition_arn = aws_ecs_task_definition.hoge_task_definition.arn
      platform_version    = "1.4.0"
      network_configuration {
        assign_public_ip = false
        security_groups  = [aws_security_group.hoge.id]
        subnets          = [var.hoge_subnet1_id,var.hoge_subnet2_id]
      }
    }
    input = jsonencode({
      "containerOverrides" : [
        {
          "name" : "rds-log-to-s3-upload", 
          "command" : ["[Aurora クラスター名]", " [S3 バケット名]"]
        }
      ]
    })
  }
}

以上で ECS 上での RDS ログを S3 にアップロードの定期実行の仕組み化ができました.

関連記事

sadayoshi-tada.hatenablog.com

まとめ

RDS ログを S3 にアップロードする仕組みを EventBridge Scheduler と ECS を使って実現するまでの工程を記載しました.これで定期実行ができるようになったのですが,運用し始めての気づきもあったので次の記事ではその辺の話を書きます.

関連記事

sadayoshi-tada.hatenablog.com

sadayoshi-tada.hatenablog.com