1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

CloudWatch Eventsでサーバの起動管理を行う

任意のタイミングでサーバ起動・停止できる仕組みとしてAWSSimpleConsoleがあります。
https://github.com/mokemokechicken/AWSSimpleConsole

ただ、dockerの使用やElasticBeanstalkでの起動管理など、新しい仕組みを取り入れていく環境の中で、AWSSimpleConsoleで運用するサーバも数台になったことから、今回、CloudWatchのEvents機能を利用した起動制御にリプレイスしました。
また、マネージメントコンソールにおける表示と設定についても注意点がありますので記述します。

要件

  • 開発上必要なサーバに対して、夜間は不要なため毎日、時間を指定して停止させておく
  • 起動は不定期であるため、都度、APIを実行して起動させる

方法

  • CloudWatch Eventsでスケジュールを使用し、ターゲットにインスタンスを指定する
  • Terraformを用いて設計・実装する

注意点

  • InstanceIdはStringList形式で指定する必要がある
  • 一度に指定できる数は最大5つという制限がある
  • cronライクにスケジュールを定義できるがUTCのタイムゾーンで記述する必要がある

設定

  • Event SourceとTargetsの設定をすることでスケジュールがトリガーされたときに起動するターゲットを選択します。そのターゲットとしてSystems Managerには定義済みオートメーションドキュメントが用意されているので arn = "arn:aws:ssm:ap-northeast-1::automation-definition/AWS-StopEC2Instance" として定義します。

cloudwatch_event_rule.tf
resource "aws_cloudwatch_event_rule" "stop_rule_1" {
  name        = "stop-rule-1"
  description = "server stop the dev server at 22:00(JST)"

  schedule_expression = "cron(0 13 * * ? *)"
}

// The number of InstanceId constants is limited within 5
resource "aws_cloudwatch_event_target" "stop_target_1" {
  target_id = "StopInstance"
  arn       = "arn:aws:ssm:ap-northeast-1::automation-definition/AWS-StopEC2Instance"
  rule      = aws_cloudwatch_event_rule.stop_rule_1.name
  role_arn  = aws_iam_role.cloudwatch_event_ssm_role.arn

  input = <<EOF
{
  "InstanceId": ["i-00000000000000000", "i-11111111111111111", "i-22222222222222222", "i-33333333333333333", "i-44444444444444444"]
}
EOF
}

resource "aws_cloudwatch_event_rule" "stop_rule_2" {
  name        = "stop-rule-2"
  description = "server stop the dev server at 22:00(JST)"

  schedule_expression = "cron(0 13 * * ? *)"
}

// The number of InstanceId constants is limited within 5
resource "aws_cloudwatch_event_target" "stop_target_2" {
  target_id = "StopInstance"
  arn       = "arn:aws:ssm:ap-northeast-1::automation-definition/AWS-StopEC2Instance"
  rule      = aws_cloudwatch_event_rule.stop_rule_2.name
  role_arn  = aws_iam_role.cloudwatch_event_ssm_role.arn

  input = <<DOC
{
  "InstanceId": ["i-55555555555555555"]
}
DOC
}
iam_role.tf
resource "aws_iam_role" "cloudwatch_event_ssm_role" {
  name = "cloudwatch_event_ssm_role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": [
         "events.amazonaws.com"
         ]
     },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "cloudwatch_event_ssm_rds_policy" {
  name = "cloudwatch_event_ssm_rds_policy"
  role = aws_iam_role.cloudwatch_event_ssm_role.id

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "rds:StopDBInstance",
        "rds:StartDBInstance",
        "rds:DescribeDBInstances"
      ],
      "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "AmazonSSMAutomationRole" {
  role       = aws_iam_role.cloudwatch_event_ssm_role.id
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole"
}

tips

  • AWS管理のRoleであるcloudwatch_event_ssm_roleだが、なぜかRDSについての権限がないので、RDSインスタンスを指定する場合は別途ポリシーを作成する必要がある。 また、RDSインスタンスのID指定はDB identifierを記述する。
cloudwatch_event_ssm_role.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:*:*:function:Automation*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateImage",
                "ec2:CopyImage",
                "ec2:DeregisterImage",
                "ec2:DescribeImages",
                "ec2:DeleteSnapshot",
                "ec2:StartInstances",
                "ec2:RunInstances",
                "ec2:StopInstances",
                "ec2:TerminateInstances",
                "ec2:DescribeInstanceStatus",
                "ec2:CreateTags",
                "ec2:DeleteTags",
                "ec2:DescribeTags",
                "cloudformation:CreateStack",
                "cloudformation:DescribeStackEvents",
                "cloudformation:DescribeStacks",
                "cloudformation:UpdateStack",
                "cloudformation:DeleteStack"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": [
                "arn:aws:sns:*:*:Automation*"
            ]
        }
    ]
}

  • マネージメントコンソールにおいてルールを編集するとInstanceIdの入力値がStringList形式ではないカンマ区切りの文字列へと変更されている。(機能改善要求済み)

image.png

確認

  • 指定時間に指定したインスタンスが停止していることが確認できる

image.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?