概要
ECS上のfargateタスクをスケジュールで起動したり落としたりしたい。
例えば開発環境のfargateタスクは夜間落としておいて、朝起動しておくと
タスクの実行時間が減るので料金を節約することができる。
大まかな流れ
- Lambdaを作り、ECS Serviceを更新し、必要なタスク量を増減させる
- Cloud Watch Eventにて、cronの時間になったらLambdaを発火する
実装
Lambda
ソースコード
今回はpythonで実装。
- eventで受けとったデータの中から、操作する対象のECSのクラスタ名、サービス名、更新するタスク数を取得
- ECSに対して更新操作を発行
サンプルソース
import json
import boto3
import logging
from botocore.exceptions import ClientError
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info("Event: " + str(event))
targets = event["targets"]
desiredCount = event["desiredCount"]
for target in targets:
edit_ecs(target, desiredCount)
def edit_ecs(target, desiredCount):
try:
client = boto3.client('ecs')
# update ecs cluster
service_update_result = client.update_service(
**target,
desiredCount = desiredCount
)
print(service_update_result)
except ClientError as e:
print("exceptin: %s" % e)
IAMロールの加工
Lambda実行時のIAMロールに、ECSへの更新操作権を付与する
Lambdaに付与したIAMロールを開き、以下のようにポリシーを編集
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:DescribeServices",
"ecs:UpdateService"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
テスト実行
Lambdaでテストイベントを作成。
ECSのクラスター名が dev-ecs-cluster
で
タスクの増減をしたいサービスが dev-service1
dev-service2
の2種類があると仮定すると以下のようなJSONになる
{
"targets": [
{
"cluster": "dev-ecs-cluster",
"service": "dev-service1"
},
{
"cluster": "dev-ecs-cluster",
"service": "dev-service2"
}
],
"desiredCount": 1
}
上記でLambdaをテスト実行すると ECSの必要タスク数が1に更新され、
タスクが2つ以上上がっていた場合、自動的に1つに変更されるはず。
Lambdaを指定時間で発火させる
指定時間でLambdaを起動させたいので、 Cloud Watch
でルール設定をする。
Cloud Watch -> イベント -> ルールの作成
イベントソースをスケジュールに設定し、cron式を入力する。
たとえば毎日AM08:00に実行するなら 0 23 * * ? *
となる(時間はGMTなので注意)
イベントターゲットに上記で作成したLambdaを指定し
入力の設定で「定数(JSONテキスト)」を選択し、そこにLambdaのテストで利用したようなJSONを記載する
(入力フィールドがテキストエリアでないのが辛い・・・)
こうするとLambda実行時のeventとして指定したJSONがLambdaに渡る。
desiredCountを 0
にすると該当サービスのタスクをゼロにできる。
なので同様のルールを2つ作り、08:00にはdesiredCountを 1
に。20:00にはdesiredCountを 0
のように設定しておけば夜間にタスクを落としておくことができる