これは何?
ECSの自動停止・自動起動の設定を入れたので記載します。
※自分用のメモです
コンソールでポチポチするんも面倒なので、terraformで作成できるようにしました。
用途
コスト削減等で夜間のECSタスク数を0にして停止、早朝にタスク起動する場合に使う。
構成イメージ
terraform
├── ecs-start
│ └── lambda_function.py ← ECS起動用の関数コードを記載
└── ecs-start
│ └── lambda_function.py ← ECS停止用の関数コードを記載
└── lambda.tf ← lambda,IAM,CWlog,EventBridge(cloudwatch_event)設定を記載
各ファイルの設定内容
ECS起動用の関数コード(lambda_function.py)
lambda_function.py
import boto3
from botocore.exceptions import ClientError
def lambda_handler(event, context):
try:
client = boto3.client('ecs')
for cluster_name, service_name in [('#対象のECSクラスター1を記載#', '#対象のECSサービス1を記載#'),
('#対象のECSクラスター2を記載#', '#対象のECSサービス2を記載#'),]:
service_update_result = client.update_service(
cluster = cluster_name,
service = service_name,
desiredCount = 1 # ここの数を増減させる
)
print(service_update_result)
except ClientError as e:
print("exceptin: %s" % e)
ECS停止用の関数コード(lambda_function.py)
lambda_function.py
import boto3
from botocore.exceptions import ClientError
def lambda_handler(event, context):
try:
client = boto3.client('ecs')
for cluster_name, service_name in [('#対象のECSクラスター1を記載#', '#対象のECSサービス1を記載#'),
('#対象のECSクラスター2を記載#', '#対象のECSサービス2を記載#'),]:
service_update_result = client.update_service(
cluster = cluster_name,
service = service_name,
desiredCount = 0 # 停止用なので0を記載
)
print(service_update_result)
except ClientError as e:
print("exceptin: %s" % e)
lambda,IAM,CWlog,EventBridge設定を記載(Lambda.tf)
lambda.tf
## lambda_function
### ECS起動用のLambda設定
resource "aws_lambda_function" "ecs-start" {
function_name = "${var.project-name}-ecs-start" # 任意の名称
handler = "lambda_function.lambda_handler"
role = aws_iam_role.ecs_stop_start_lambda_role.arn
runtime = "python3.8"
filename = data.archive_file.function_source_ecs-start.output_path
source_code_hash = data.archive_file.function_source_ecs-start.output_base64sha256
depends_on = [aws_iam_role_policy_attachment.ecs_stop_start_lambda_policy, aws_cloudwatch_log_group.ecs_start_lambda]
}
data "archive_file" "function_source_ecs-start" {
type = "zip"
source_dir = "app-ecs-start"
output_path = "archive/ecs-start_lambda_function.zip"
}
### ECS停止用のLambda設定
resource "aws_lambda_function" "ecs-stop" {
function_name = "${var.project-name}-ecs-stop" # 任意の名称
handler = "lambda_function.lambda_handler"
role = aws_iam_role.ecs_stop_start_lambda_role.arn
runtime = "python3.8"
filename = data.archive_file.function_source_ecs-stop.output_path
source_code_hash = data.archive_file.function_source_ecs-stop.output_base64sha256
depends_on = [aws_iam_role_policy_attachment.ecs_stop_start_lambda_policy, aws_cloudwatch_log_group.ecs_stop_lambda]
}
data "archive_file" "function_source_ecs-stop" {
type = "zip"
source_dir = "app-ecs-stop"
output_path = "archive/ecs-stop_lambda_function.zip"
}
## IAM
### Lambda用のIAMロール設定(ECSを操作する権限を付与)
locals {
lambda_role_default_assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role" "ecs_stop_start_lambda_role" {
name = "${var.project-name}-ecs-stop-start-Lambda-Role" # 任意の名称
assume_role_policy = local.lambda_role_default_assume_role_policy
}
resource "aws_iam_role_policy_attachment" "ecs_stop_start_lambda_role_aws_lambda_basic_execution_role" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
role = aws_iam_role.ecs_stop_start_lambda_role.name
}
data "aws_iam_policy_document" "ecs_stop_start_lambda_policy" {
statement {
effect = "Allow"
actions = [
"ecs:DescribeServices",
"ecs:UpdateService"
]
resources = ["*"]
}
}
resource "aws_iam_policy" "ecs_stop_start_lambda_policy" {
name = "${var.project-name}-ecs-stop-start-Lambda-Policy"
policy = data.aws_iam_policy_document.ecs_stop_start_lambda_policy.json
}
resource "aws_iam_role_policy_attachment" "ecs_stop_start_lambda_policy" {
role = aws_iam_role.ecs_stop_start_lambda_role.name
policy_arn = aws_iam_policy.ecs_stop_start_lambda_policy.arn
}
## cloudwatch_log
### Lambda用のcloudwatch_log設定
resource "aws_cloudwatch_log_group" "ecs_start_lambda" {
name = "/aws/lambda/${var.project-name}-ecs-start" # 任意の名称
}
resource "aws_cloudwatch_log_group" "ecs_stop_lambda" {
name = "/aws/lambda/${var.project-name}-ecs-stop" # 任意の名称
}
## cloudwatch_event
### Lambda用のEventBridge設定(
#### START 月〜金 8:00
resource "aws_cloudwatch_event_rule" "ecs-start" {
name = "${var.project-name}-ecs-start" # 任意の名称
description = "${var.project-name}-ecs-start" # 任意の内容
is_enabled = "true"
schedule_expression = "cron(00 23 ? * SUN-THU *)"
}
resource "aws_cloudwatch_event_target" "ecs-start" {
arn = aws_lambda_function.ecs-start.arn
rule = aws_cloudwatch_event_rule.ecs-start.name
target_id = "${var.project-name}-ecs-start"
}
#### STOP 月〜金 21:00
resource "aws_cloudwatch_event_rule" "ecs-stop" {
name = "${var.project-name}-ecs-stop" # 任意の名称
description = "${var.project-name}-ecs-stop" # 任意の内容
is_enabled = "true"
schedule_expression = "cron(00 12 ? * MON-FRI *)"
}
resource "aws_cloudwatch_event_target" "ecs-stop" {
arn = aws_lambda_function.ecs-stop.arn
rule = aws_cloudwatch_event_rule.ecs-stop.name
target_id = "${var.project-name}-ecs-stop"
}
以上です。