🐿️

Terraform + AWS Batch + Golangで スケジュール実行/手動バッチを作成する

2023/07/19に公開


はじめに

ご覧いただきありがとうございます。阿河です。

バッチやジョブを単発/定期実行させたいとき、さくっとLambdaで実装して対応することが多いです。ただしLambdaには実行時間の問題があり あらゆる場面で対応できるとは限りません。

代替策としてAWS BatchやAmazon ECSが考えられますが、今回はAWS Batch(スケジュール実行/AWS CLIベースの手動実行)をTerraform + Golangコンテナイメージで構成しています。

本記事で扱っている処理内容は簡易的なものですが、今回の構成をベースに皆様の環境に合わせてカスタマイズして使って頂けると幸いです。

対象者

  • AWSを利用中/検証中
  • 比較的処理時間がかかるバッチやジョブをスケジュール/手動実行したい
  • Terraformでデプロイを自動化したい

概要

  1. 環境のセットアップ
  2. スケジューリングジョブの挙動確認
  3. 手動ジョブの挙動確認

1. 環境のセットアップ

前提条件

前提として下記のセットアップが必要です。

- AdministratorAccess相当のIAMユーザー権限
- git
- docker
- terraform

https://github.com/agamemnon-ai/golang-test.git

ローカル環境にセットアップすることが難しい場合は、AWS Cloud9を使ってECRへのイメージアップロードまで完了させてください。

ローカルでのテスト

$ cd golang-test
$ docker build .

git clone実行後、ローカルで挙動確認を行います。

main.go

package main

import (
	"fmt"
	"os"
)

func main() {
	env1 := os.Getenv("ENV1")
	env2 := os.Getenv("ENV2")
	fmt.Println(env1)
	fmt.Println(env2)
}

処理の内容はシンプルで、環境変数の値を表示するものです。
デフォルトでは「"Hello golang"」と表示されますが、ENV1およびENV2の値を渡すと表示するテキスト内容を変えることができます。

$ docker container run [※image id]
Hello golang

$ docker container run -e ENV1=GoodBye -e ENV2=all [※image id]
GoodBye all

挙動が確認できたら、次にAWS Batch実行環境を作成します。
バージニア北部リージョンの利用を想定しています。

Terraform実行の準備

$ cd terraform

"terraform.tfvars"ファイルのそれぞれのパラメータを設定します。

  • project/environtment: デプロイされる各AWSリソースの名前に反映されます。任意の値に設定してください。

  • account: お使いのAWSアカウント番号です。

  • shot-batch-vcpu: バッチのvCPUですが、特段変更の必要がなければデフォルト値のまま。

  • shot-batch-image:
    [※Account_No].dkr.ecr.us-east-1.amazonaws.com/golang-test:[※Tag]

  • scheduling-batch-interval: スケジューリングジョブが実行される周期です。テストのために15分ごとに設定していますが、任意の時間に設定してください。

https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rate-expressions.html

Terraform実行

$ terraform init
$ terraform plan

// If there are no problems with the results of the execution of the "terraform plan"
$ terraform apply

デプロイされるAWSリソースは下記の通りです。

  • ネットワーク
    パブリック * 2/プライベートサブネット * 2
    NATゲートウェイあり。

  • AWS Batch
    EventBridgeと連携させたスケジューリングジョブ/AWS CLIでのトリガーを想定した手動ジョブをそれぞれ作成します。

  • セキュリティグループ

  • ECRリポジトリ

  • AWS Batch/EventBridge用のIAMロール

  • スケジューリングジョブ/手動ジョブそれぞれと連携するCloudWatchロググループ

ECRへのイメージPUSH

エラーなくデプロイが完了したら、ECRリポジトリにイメージをPUSHします。

ECRへのアップロード手順は、AWSマネジメントコンソールの「View push commands」の手順に従ってください。

以上で環境のセットアップは完了です。

2. スケジューリングジョブの挙動確認

ジョブ確認

15分置きに処理が実行されていることが分かります。

ログ確認

  • AWSマネジメントコンソールのCloudWatchページ⇒Log groups⇒/aws/ecs/blog-dev-scheduling-execution-batch

デフォルト値である"Hello golang"が表示されています。

Terraform側で環境変数を指定

batch.tf

#-----------------------------------------------------------------
# Job Definition for Scheduling Batch
#-----------------------------------------------------------------

resource "aws_batch_job_definition" "scheduling_batch_definition" {
  name = "${var.project}-${var.environment}-scheduling-batch-definition"
  type = "container"

  platform_capabilities = [
    "FARGATE",
  ]

  container_properties = jsonencode({
    image = "${var.shot-batch-image}"

    fargatePlatformConfiguration = {
      platformVersion = "LATEST"
    }
    
    environment = [
      {
        name  = "ENV1"
        value = "GoodBye"
      },
      {
        name  = "ENV2"
        value = "All"
      }
    ]

    resourceRequirements = [
      {
        type  = "VCPU"
        value = "0.25"
      },
      {
        type  = "MEMORY"
        value = "512"
      }
    ]

    "logConfiguration" : {
      "logDriver" : "awslogs",
      "options" : {
        "awslogs-group" : "${aws_cloudwatch_log_group.cloudwatch_log_group-scheduling.name}",
        "awslogs-region" : "us-east-1",
        "awslogs-stream-prefix" : "ecs"
      }
    }

    executionRoleArn = aws_iam_role.aws_batch_service_execution_role.arn
  })
}

AWS Batch用のtfファイル⇒スケジューリングバッチのジョブ定義で、"environment"を指定します。

 environment = [
      {
        name  = "ENV1"
        value = "GoodBye"
      },
      {
        name  = "ENV2"
        value = "All"
      }
    ]
$ terraform plan

// If there are no problems with the results of the execution of the "terraform
$ terraform apply

適用後CloudWatch Logsを確認すると

処理結果が変わりました。

3. 手動ジョブの挙動確認

AWS CLIで2種類のバッチジョブ実行

# 1
# Run without specifying environment variables
$ aws batch submit-job --job-name "test-job" --job-queue "blog-dev-shot-batch-queue" --job-definition "blog-dev-shot-batch-definition"
{
    "jobName": "test-job", 
    "jobArn": "arn:aws:batch:us-east-1:xxxxxxxx:job/xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
    "jobId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

# 2
# Run again without specifying environment variables
$ aws batch submit-job --job-name "test-job" --job-queue "blog-dev-shot-batch-queue" --job-definition "blog-dev-shot-batch-definition"
{
    "jobName": "test-job", 
    "jobArn": "arn:aws:batch:us-east-1:xxxxxxxx:job/xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
    "jobId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

# 3
# Run with environment variable specification
$ aws batch submit-job --job-name "test-job" --job-queue "blog-dev-shot-batch-queue" --job-definition "blog-dev-shot-batch-definition" --container-overrides 'environment = [{name = ENV1 , value = GoodBye},{name = ENV2 , value = all}]'                        
{
    "jobName": "test-job", 
    "jobArn": "arn:aws:batch:us-east-1:xxxxxxxx:job/xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
    "jobId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

ジョブキューやジョブ定義名は、ご自身の環境のものに置き換えてください。

ジョブ確認

ログ確認

  • AWSマネジメントコンソールのCloudWatchページ⇒Log groups⇒/aws/ecs/blog-dev-shot-batch
  1. 環境変数なしで実行

  2. 環境変数なしでもう一度実行

  3. 環境変数ありで実行

複数回の実行、環境変数の指定による挙動変更が可能であることを確認できました。

さいごに

以上簡単な処理をスケジュール実行/CLIベースで単発実行させてみました。
こちらの構成をベースに、是非皆様の環境に合わせてカスタマイズ頂けると幸いです。

御覧いただき ありがとうございました。

MEGAZONE株式会社 Tech Blog

Discussion