AWS LambdaでECSタスク数を自動管理する方法
背景:月末月初がアクセス数が多くサーバー負荷が高まるため、月初から5営業日はサーバーのリソースを増強しておこうという主旨から、今回の対応が必要になった。
目的:毎回ECSタスク数の変更を手動でやっていたが、Lambdaを使って、Fargateタスク数を自動的に調整し、効率的なECSタスク数の管理の実現をする。
Lambda用のポリシーとロールの作成
AWS LambdaがFargate(ECS)のタスク数を変更できるようにするためには、Lambda関数に適切なIAMロールを割り当て、そのロールに必要な権限を付与する必要があります。
必要なポリシーは2つあります。IAMのポリシー「ポリシーの作成」から作成し、その後、IAMのロール「ロールを作成」から作成します。
ECSに対する権限
Lambda関数からECSサービスを更新するためには、ecs:UpdateService
を許可する必要があります。また、特定のクラスターやサービスにアクセスするためには、ecs:DescribeServices
も必要です。(< >
で囲っている箇所は各自の環境に合わせます)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:UpdateService",
"ecs:DescribeServices"
],
"Resource": [
"arn:aws:ecs:<region>:<account-id>:service/<cluster-name>/<service-name>",
"arn:aws:ecs:<region>:<account-id>:cluster/<cluster-name>"
]
}
]
}
CloudWatchに対する権限
Lambda関数の実行ログをCloudWatchに出力するには、以下の権限が必要です。(< >
で囲っている箇所は各自の環境に合わせます)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:<region>:<account-id>:log-group:/aws/lambda/*"
}
]
}
IAMロールの作成
- IAMにアクセス
- 新しいロールを作成し、「AWSサービス」→「ユースケース:Lambda」を選択。
- 必要なポリシーを追加(上記の作成済ポリシーを選択)。
- ロールをLambda関数にアタッチ。
この設定により、Lambda関数がECSのサービスのタスク数を管理できるようになります。
Lambda関数の実装
下記条件で、Pythonのコードを記載し、関数を作成します。
- 月初から営業日5日間は、ECSのタスク数を5個起動し、それ以外は2個起動する
- 営業日は、祝日や土日を除く
- 祝日は手動で管理(直接コードに記載)
「デフォルトの実行ロールの変更」では、[既存のロールを使用する]を選択し、作成済みロールを選択します。
import boto3
import datetime
# AWSのクライアントを初期化
ecs = boto3.client('ecs')
# 日本の祝日リスト(例として2024年の一部記載)
HOLIDAYS_2024 = [
datetime.date(2024, 1, 1), # 元日
datetime.date(2024, 1, 8), # 成人の日
datetime.date(2024, 2, 11), # 建国記念の日
datetime.date(2024, 2, 12), # 建国記念の日 振替休日
datetime.date(2024, 3, 20), # 春分の日
datetime.date(2024, 4, 29), # 昭和の日
]
def is_business_day(date):
# 土日または祝日でない場合は営業日
return date.weekday() < 5 and date not in HOLIDAYS_2024
def get_business_days_from_month_start(current_date):
first_of_month = current_date.replace(day=1)
business_days = 0
current_day = first_of_month
while current_day <= current_date:
if is_business_day(current_day):
business_days += 1
current_day += datetime.timedelta(days=1)
return business_days
def get_desired_task_count(date):
if not is_business_day(date):
return 2 # 休日または土日の場合
business_days = get_business_days_from_month_start(date)
if business_days <= 5:
return 5 # 月初から5営業日まで
else:
return 2 # それ以外の営業日
def lambda_handler(event, context):
cluster_name = 'your-cluster-name'
service_name = 'your-service-name'
today = datetime.date.today()
desired_count = get_desired_task_count(today)
try:
# 現在のサービスの状態を取得
response = ecs.describe_services(cluster=cluster_name, services=[service_name])
current_count = response['services'][0]['desiredCount']
running_count = response['services'][0]['runningCount']
print(f"Current date: {today}")
print(f"Desired task count: {desired_count}")
print(f"Current desired count: {current_count}")
print(f"Current running count: {running_count}")
if current_count == desired_count and running_count == desired_count:
print("Task count is already correct. No action needed.")
return {
'statusCode': 200,
'body': 'Task count is already correct. No action needed.'
}
else:
# タスク数を更新
update_response = ecs.update_service(
cluster=cluster_name,
service=service_name,
desiredCount=desired_count
)
print(f"Updated task count from {current_count} to {desired_count}")
return {
'statusCode': 200,
'body': f'Updated task count from {current_count} to {desired_count}'
}
except Exception as e:
print(f"Error occurred: {str(e)}")
return {
'statusCode': 500,
'body': f'Error occurred: {str(e)}'
}
is_business_day
関数:
- 土日と祝日以外を営業日と判定します。
get_business_days_from_month_start
関数:
- 月初から指定日までの営業日数を計算します。
get_desired_task_count
関数:
- 日付に基づいて適切なタスク数を決定します:
- 休日または土日の場合は2
- 月初から5営業日までは5
- それ以外の営業日は2
lambda_handler
:
- 現在の日付に基づいてタスク数を決定し、ECSサービスを更新します。
- エラーハンドリングとログ記録をします。
Amazon EventBridgeでスケジューリング
AWS EventBridgeを使用してLambda関数を定期自動実行するようスケジュールすることができます。
ターゲットの設定を行います。ここでは、作成したLambdaの関数を選択します。
以上で設定完了です。
動作確認
CloudWatchログは、Lambda関数の実行ログを確認するのに最適です。ECSでも該当のサービスの状態に変更があった場合にはイベント情報で確認できます。
- Cloudwatch
- ロググループ「/aws/lambda/ecs-auto-task-scheduler(Lambdaの関数名)」
- ECS
- ECSのサービスを選択し、表示される「イベント」タブにタスク更新情報が表示される
実際にタスク数が変動するかを確認はできるが、上記に処理実行時のログ情報が表示されるので、より確実に状態を把握し、動作を確認することができます。