【Python】LambdaでAWS ECSサービスのタスク起動数を操作/取得する

container

こんにちは、エンジニアの田代です。
バッチ処理等において、ECSサービスのタスク数を調整したいケースがあるのではないでしょうか。
Step Functionsを利用する等複数の方法が考えられますが、今回はAWS外のジョブ管理システムから操作することを想定して、
API Gateway + Lambdaで実装したのでサンプルを共有したいと思います。

ECSサービスのタスク起動数を更新するLambda

Lambdaコード

import boto3

ecs = boto3.client('ecs')


def lambda_handler(event, context):
    params = event['queryStringParameters']
    # クエリパラメータから対象のECSクラスターを取得
    cluster = params['cluster']
    # クエリパラメータから対象のECSサービスを取得
    service = params['service']
    # クエリパラメータから設定する起動数を取得
    desired_count = int(params['desiredCount'])
    
    response = ecs.update_service(
        cluster=cluster,
        service=service,
        desiredCount=desired_count
    )
    print(response)
    
    return {
        'statusCode': 200
    }

実行ロール用のIAMポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-update-service",
            "Effect": "Allow",
            "Action": "ecs:UpdateService",
            "Resource": "*"
        }
    ]
}

ECSサービスのタスク起動数を取得するLambda

Lambdaコード

import boto3
import json

ecs = boto3.client('ecs')


def get_healthy_task_count(cluster: str, tasks_list: list) -> int:
    # 各タスク内の全てのコンテナのヘルスチェックステータスがHEALTHYの場合, 起動タスク数を1加算する
    healthy_task_count = 0
    if len(tasks_list) == 0:
        return healthy_task_count
    describe_tasks_response = ecs.describe_tasks(
        cluster=cluster,
        tasks=tasks_list
    )
    for task in describe_tasks_response['tasks']:
        if all(i['healthStatus'] == 'HEALTHY' for i in task['containers']):
            healthy_task_count += 1
    return healthy_task_count


def lambda_handler(event, context):
    params = event['queryStringParameters']
    # クエリパラメータから対象のECSクラスターを取得
    cluster = params['cluster']
    # クエリパラメータから対象のECSサービスを取得
    service = params['service']
    
    # RUNNINGステータスのタスクを取得
    list_tasks_response = ecs.list_tasks(
        cluster=cluster,
        serviceName=service,
        desiredStatus='RUNNING'
    )
    running_tasks = list_tasks_response['taskArns']
    healthy_task_count = get_healthy_task_count(cluster, running_tasks)

    body = {'taskCount': healthy_task_count}
    return {
        'statusCode': 200,
        'body': json.dumps(body),
        'headers': {
            'Content-Type': 'application/json'
        }
    }

実行ロール用のIAMポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-list-tasks",
            "Effect": "Allow",
            "Action": [
                "ecs:ListTasks",
                "ecs:describeTasks"
            ],
            "Resource": "*"
        }
    ]
}

実行結果

各LambdaのトリガーとしてAPI Gatewayを設定して、それぞれ実行してみます。

$ curl https://xxx.execute-api.ap-northeast-1.amazonaws.com/xxx/update-desired-count?cluster=EcsClusterName&service=EcsServiceName&desiredCount=2

ecs

指定した数のタスクが起動しました。
この状態でタスク起動数取得Lambdaを実行します。

$ curl https://xxx.execute-api.ap-northeast-1.amazonaws.com/xxx/get-task-count?cluster=EcsClusterName&service=EcsServiceName
{"taskCount": 2}

期待通りの結果が返りました。
今回の記事が皆様の参考になれば幸いです。

田代 侑大システム開発部 マネックス・ラボ