[小ネタ] AWS Batch のジョブ数を CloudWatch メトリクスに Put する仕組みを CloudFormation で構築してみた

[小ネタ] AWS Batch のジョブ数を CloudWatch メトリクスに Put する仕組みを CloudFormation で構築してみた

AWS Batch のジョブ数を CloudWatch メトリクスに Put する仕組み構築する CloudFormation テンプレートです
Clock Icon2025.03.24

アノテーション・テクニカルサポートチームの hato です。

2025年3月時点で、AWS Batch の各ステータスのジョブ数を CloudWatch メトリクスで監視したい場合、カスタムメトリクスを生成する必要があります。

カスタムメトリクスは次のような EventBridge ルールと Lambda の構成で生成できますが、CloudFormation テンプレートを作成する機会がありましたので、小ネタとしてご紹介します。

https://dev.classmethod.jp/articles/count-aws-batch-queue-by-custom-metrics/

なお、ブログと同様の構成ですが、次の差異があります。

  • CloudWatch メトリクスはステータス毎に生成
  • メトリクス(EventBridge ルール)は 1 分間隔
  • Lambda のランタイムは Python 3.13
  • カスタムメトリクスの Namespace 名は CloudFormation 内にハードコーディング

テンプレート

AWSTemplateFormatVersion: 2010-09-09
Description: AWS Batch Cloudwatch Metrics Job Count

Parameters:
  QueueName:
    Type: String
    Description: Name of the AWS Batch job queue to monitor

Resources:
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: BatchAndCloudWatchAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - batch:ListJobs
                  - cloudwatch:PutMetricData
                Resource: '*'

  BatchMetricsFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3
          import os

          def lambda_handler(event, context):
              batch = boto3.client('batch')
              cloudwatch = boto3.client('cloudwatch')

              queue_name = os.environ['QUEUE_NAME']

              # ジョブキューの状態別のジョブ数を取得
              submitted_count = len(batch.list_jobs(
                  jobQueue=queue_name,
                  jobStatus='SUBMITTED'
              )['jobSummaryList'])

              pending_count = len(batch.list_jobs(
                  jobQueue=queue_name,
                  jobStatus='PENDING'
              )['jobSummaryList'])

              runnable_count = len(batch.list_jobs(
                  jobQueue=queue_name,
                  jobStatus='RUNNABLE'
              )['jobSummaryList'])

              starting_count = len(batch.list_jobs(
                  jobQueue=queue_name,
                  jobStatus='STARTING'
              )['jobSummaryList'])

              running_count = len(batch.list_jobs(
                  jobQueue=queue_name,
                  jobStatus='RUNNING'
              )['jobSummaryList'])

              # CloudWatchにメトリクスを送信
              cloudwatch.put_metric_data(
                  Namespace='BatchJobMetrics',
                  MetricData=[
                      {
                          'MetricName': 'SubmittedCount',
                          'Value': submitted_count,
                          'Unit': 'Count',
                          'Dimensions': [
                              {
                                  'Name': 'QueueName',
                                  'Value': queue_name
                              }
                          ]
                      },
                      {
                          'MetricName': 'PendingCount',
                          'Value': pending_count,
                          'Unit': 'Count',
                          'Dimensions': [
                              {
                                  'Name': 'QueueName',
                                  'Value': queue_name
                              }
                          ]
                      },
                      {
                          'MetricName': 'RunnableCount',
                          'Value': runnable_count,
                          'Unit': 'Count',
                          'Dimensions': [
                              {
                                  'Name': 'QueueName',
                                  'Value': queue_name
                              }
                          ]
                      },
                      {
                          'MetricName': 'StartingCount',
                          'Value': starting_count,
                          'Unit': 'Count',
                          'Dimensions': [
                              {
                                  'Name': 'QueueName',
                                  'Value': queue_name
                              }
                          ]
                      },
                      {
                          'MetricName': 'RunningCount',
                          'Value': running_count,
                          'Unit': 'Count',
                          'Dimensions': [
                              {
                                  'Name': 'QueueName',
                                  'Value': queue_name
                              }
                          ]
                      }
                  ]
              )

              return {
                  'statusCode': 200,
                  'body': {
                      'submitted': submitted_count,
                      'pending': pending_count,
                      'runnable': runnable_count,
                      'starting': starting_count,
                      'running': running_count
                  }
              }
      Runtime: python3.13
      Timeout: 30
      Environment:
        Variables:
          QUEUE_NAME: !Ref QueueName

  MetricsScheduleRule:
    Type: AWS::Events::Rule
    Properties:
      Description: "Schedule for collecting Batch queue metrics"
      ScheduleExpression: "rate(1 minute)"
      State: ENABLED
      Targets:
        - Arn: !GetAtt BatchMetricsFunction.Arn
          Id: "BatchMetricsTarget"

  LambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref BatchMetricsFunction
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn: !GetAtt MetricsScheduleRule.Arn

かんたんな使い方

  1. 上記テンプレートを任意の名前(例:aws-batch-queue-monitoring.yaml)でテキストファイルとして保存

  2. CloudFormation コンソールの「テンプレートファイルのアップロード」からアップロード

AWS Batch Cloudwatch Metrics Job Count 1

  1. 任意のスタック名と監視対象のジョブキュー名(QueueName)を指定してスタックを作成

AWS Batch Cloudwatch Metrics Job Count 2

  1. ステータスが「CREATE_COMPLETE」になったことを確認します。

AWS Batch Cloudwatch Metrics Job Count 3

スタックデプロイ後、しばらくすると Namespace:BatchJobMetricsにステータス毎のジョブ数の CloudWatch メトリクスが生成されます。

AWS Batch Cloudwatch Metrics Job Count 4

最後に

この記事が誰かのお役にたてば幸いです。

アノテーション株式会社について

アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイト をぜひご覧ください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.