AWS Batchでキューの数を監視するCloudWatchカスタムメトリクスを作成してputしてみた

2017.10.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、臼田です。

皆さん、Lambdaしてますか?

AWS BatchはLambdaより長い時間を要する処理などに利用でき、マネージドでキューの管理やリトライ、AutoScaling等をやってくれて便利です。

初めてのAWS Batch – 必要な各コンポーネントを理解する –

しかし、まだ比較的新しいということもあってかBatchに投げたキューを確認するためのCloudWatchメトリクスが存在しません。

現状はマネジメントコンソールからGUIでキューの状態を確認するしかありません。

Batch上のスクリプト等の問題によりキューが溜まっていても検知できないと困るので、カスタムメトリクスとして定期的にポーリングするLambdaスクリプトを作成しました。

下記のように表示されます。

005_graph

Lambdaスクリプト

Python3.6で記述しました。

import os
import boto3


batch = boto3.client('batch')
cloudwatch = boto3.resource('cloudwatch')
statuses = ['SUBMITTED','PENDING','RUNNABLE','STARTING','RUNNING']

# get params
jobqueue_name = os.environ['JOBQUEUE_NAME']
namespace = os.environ['NAMESPACE']
metric_name = "QueueCount"

# set metric
metric = cloudwatch.Metric(namespace, metric_name)

def lambda_handler(event, context):
    # get queue count
    queue_count = 0
    for status in statuses:
        r = batch.list_jobs(
            jobQueue = jobqueue_name,
            jobStatus = status,
        )
        # add queue count
        queue_count += len(r['jobSummaryList'])
    print("count is: " + str(queue_count))
    
    # send queue count to cloudwatch
    metric.put_data(
        MetricData = [
            {
                'MetricName': 'QueueCount',
                'Value': queue_count,
                'Unit': 'Count',
                'Dimensions': [{
                    'Name': 'QueueName',
                    'Value': jobqueue_name
                }]
            }
        ]
    )

簡単に内容を説明します。

概要

  • 環境変数で指定されたJob queuesのアクティブなキューを取得
  • 環境変数で指定されたNamespace、Queue Name、メトリクス名: QueueCountでアクティブなキューをputする

アクティブなキュー

キューのステータスは下記の通り。

'SUBMITTED'|'PENDING'|'RUNNABLE'|'STARTING'|'RUNNING'|'SUCCEEDED'|'FAILED'

この中の、'SUCCEEDED'|'FAILED'が終了しているキューなので、それ以外の値の合計をlist_jobで取得します。

なお、複数ステータスを同時にクエリすることはできない模様。

Lambda作成

作成時には下記の設定を行って下さい。

  • IAM Roleでbatch:ListJobscloudwatch:putMetricDataを許可する
  • 環境変数でカスタムメトリクスのNamespace(任意の値)とJob Queue Nameを指定する
  • LambdaのトリガーをCloudWatch Eventのcronで指定する

詳細に説明します。

IAM Role作成

どんな方法でもいいですが、Lambdaのテンプレートからだとベーシックに必要なLambdaのポリシーとAWS Batchのポリシーが適用できるので比較的簡単に設定できます。

関数の作成から「hello」で絞って「hello-world-python3」を利用します。

001_create_lambda

「テンプレートから新しいロールを作成」にて「AWS Batch アクセス権限」を追加しておきます。

002_create_role

この状態で作成するとLambdaがLogを出力する権限とAWS Batchでキューを確認する権限があてられます。

作成後にIAM Roleの該当ロールへ移動してcloudwatch:putMetricDataを追加します。

インラインポリシーを作成してもいいですが、一番簡単なのは「CloudWatchFullAccess」をあてることです。

003_role

最小権限ではないですが、FullAccessでもあまり問題になる可能性は考えられないのでこちらでも問題ないでしょう。

環境変数の設定

NAMESPACEJOBQUEUE_NAMEを設定して下さい。

004_env

サンプルではカスタムメトリクスと分かるようにCustom/Batchというスキーマにしていますが、任意で問題ありません。

cronの設定

Lambda関数の「トリガー」から設定可能です。

CloudWatch Eventを選択して「新規ルールの作成」にてスケジュール式をrate(5 minutes)と設定してください。

005_trigger

場合によってはもっと短くしても問題ないと思います。

以上で全体的な設定は完了です。

まとめ

今後純正のメトリクスが追加されるかもしれませんが、それまでのつなぎとして参考にしていただければ幸いです。

おまけ: boto3カスタムメトリクスについての解釈

本スクリプトを作成するにあたりboto3のドキュメントのCloudWatch.Metric.put_dataを参照したのですが、わかりづらい部分があったので確認した内容を書いておきます。

まず、Metricリソースのput_data()メソッドのパラメータについての説明が書いてありませんが、通常のput_metric_dataとほぼ同じパラメータを使用する事ができます。

違いとしてはMetricリソースを利用する際に'namespace'を使用するためNamespaceは必要ありません。

しかし、MetricDataについては複数個指定することが可能なためか'name'(metric name)をリソースで指定していてもMetricData内のMetricNameを省略することはできませんでした。

以上です。よいboto3ライフを