LoginSignup
11
8

More than 1 year has passed since last update.

ECS Fargateを自動停止・自動起動する方法

Last updated at Posted at 2022-03-28

これは何?

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"
}

以上です。

11
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8