Techfirm Cloud Architect Blog

テックファーム株式会社クラウドインフラグループのブログ

メンテナンスウィンドウ、リソースグループ、オートメーションを使用して、複数EC2、RDSを自動起動・停止する方法

はじめに

AWSのリソースは、EC2やRDSの様に、起動時間によって課金されるものが多くあります。
そのため、不要な時には停止したいという要望はいろんな場面で出てくるでしょう。
とくにRDSは停止してから7日経過すると自動で起動するので、何もせずに放っておくと予想外の金額が請求されてしまうことがあり得ます。

リソースの起動管理の自動化は、広く認知・認識され、方法は多様化しています。
多く使われているのは、EventBridgeなどで起動や停止を行う方法でしょう。
最近ではオートメーションと組み合わせる方法がより多く採用される手法かもしれません。

EC2の起動を行う「AWS-RestartEC2Instance」や、RDSの停止を行う「AWS-StartRdsInstance」といったオートメーションは、メンテナンスウィンドウでターゲットを指定する際、リソースグループを使用する事でタグベースで複数のインスタンスをタスクのターゲットに指定できます。
環境毎にインスタンスをタグで区分している場合、たとえば開発環境のリソースの一括起動、一括停止を自動化することが可能です。

今回この記事では、前述の様な、メンテナンスウィンドウ、リソースグループ、オートメーションを使用して、複数EC2、RDSを自動起動・停止する方法を紹介したいと思います。

設定の方法

準備

まずは必要なものを準備します。

  • 複数インスタンスに任意のタグを設定する
  • リソースグループを設定する
  • 必要なロールを作成する
複数インスタンスに任意のタグを設定する

RDSやEC2はすでに準備されているものとします。
まず、自動起動および停止を行いたい対象のRDSやEC2インスタンスにタグを設定します。
今回は、Keyを「env」、Valueを「stg」とします。
自動起動したいすべてのインスタンスに同じタグを指定します。

リソースグループを作成する

次にリソースグループを作成します。
AWS Management Consoleの、AWS Resource Groupsコンソールに移動し、「リソースグループの作成」を選択します。

リソースグループの作成
新規作成画面での入力内容を説明します。

まず、「グループタイプ」では「タグベース」を選択します。
次に、グループ分けの条件の、リソースタイプは、対象のリソースの種類を選択します。
対象がEC2の場合は「AWS::EC2::Instance」を、RDSの場合は「AWS::RDS::DBInstance」を、クラスターの場合は「AWS::RDS::DBCluster」を選択します。

タイプを指定せず、タグのみを条件にすることも可能です。
タグでは、対象のリソースに設定したものを指定しますので、タグキーに「env」、オプションのタグ値に「stg」と入力し、「追加」ボタンを押します。

ここで、右下にある「グループリソースをプレビュー」をクリックすると、下の「グループリソース」に、「グループ分けの条件」で指定したものに当てはまるものが一覧で出てきます。
これにより、「グループ分けの条件」が、実際に対象としたいものだけを抽出できるか、あらかじめ確認することができます。

続いて、「グループの詳細」や「グループタグ」で任意の情報を入力し、「グループを作成」で、リソースグループを作成します。

必要なロールを作成する

メンテナンスウィンドウでは、タスクを設定する際、ふたつのロールが必要です。
ひとつは、メンテナンスウィンドウを操作するためのロール、もうひとつはオートメーションを実行するためのロールです。
それぞれどのような権限が必要か、次に説明します。

メンテナンスウィンドウを操作するためのロール

下記権限を持つポリシーを、作成します。
ポリシー名を「my-maintenance-window-role-policy」とします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:SendCommand",
                "ssm:CancelCommand",
                "ssm:ListCommands",
                "ssm:ListCommandInvocations",
                "ssm:GetCommandInvocation",
                "ssm:GetAutomationExecution",
                "ssm:StartAutomationExecution",
                "ssm:ListTagsForResource",
                "ssm:GetParameters"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "states:DescribeExecution",
                "states:StartExecution"
            ],
            "Resource": [
                "arn:aws:states:*:*:execution:*:*",
                "arn:aws:states:*:*:stateMachine:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:*:*:function:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "resource-groups:ListGroups",
                "resource-groups:ListGroupResources"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "tag:GetResources"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:PassedToService": [
                        "ssm.amazonaws.com"
                    ]
                }
            }
        }
    ]
}

次に、ロールを作成し、「my-maintenance-window-role-policy」を紐づけます。
「信頼できるエンティティ」には[Systems Manager]を選択します。
ロール名を仮に「my-maintenance-window-role」とし、作成が完了したら、「信頼関係」では、下記内容となっていることを確認し、ロールのARNをメモしておきます。

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

参考URL:AWSユーザーガイド - コンソールを使用して、メンテナンスウィンドウのアクセス許可を設定します。

オートメーションを実行するためのロール

次に、EC2やRDSを起動、停止する権限を持つロールを作成します。
まず、ロールに紐づけるポリシーから作っていきます。
ポリシーでは、起動や停止を行う対象がEC2の場合、ec2:StartInstances、ec2:StopInstancesの権限を持たせます。
対象は、下記の様にタグで対象を指定してもよいでしょう。

"Resource": "arn:aws:ec2:<region>:<AccoundID>:instance/*",
  "Condition": {
    "StringEquals": {"aws:ResourceTag/env": "stg"}
  }

対象にRDSがある場合は、rds:StartDBInstance、rds:StopDBInstanceを、クラスターの場合は、rds:StartDBCluster、rds:StopDBClusterを追加します。

ただし、Describe権限は、上記のように一部リソースに対してのみ与えず、全リソースを対象としましょう。
EC2であれば、ec2:DescribeInstanceStatus、RDSはrds:DescribeDBInstances、クラスターではrds:DescribeDBClustersです。
これらの権限のResourceは、EC2の場合、Resource": "arn:aws:ec2:<region>:<AccoundID>:instance/*の様にすべてが対象となるように記載すればOKです。
その他RDSやクラスターも同様に、*ですべてが対象となるようにしましょう。

必要な権限を記載したら、保存します。
このポリシー名は「my-automation-execution-role-policy」とします。
ポリシーが作成できたら、次にロールを作成し、「my-automation-execution-role-policy」を紐づけます。
ロール名は、「my-automation-execution-role」とします。 信頼関係は、「my-maintenance-window-role」と同様下記となるように、「信頼できるエンティティ」には[Systems Manager]を選択します。

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

一度この状態で保存し、このロールのARNもメモしておきます。
再度、この「オートメーションを実行するためのロール」を編集し、インラインポリシーを追加します。
権限は下記内容で、「SSMAutomationPassRolePolicy」という名称で保存し、ロールを更新します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "<my-automation-execution-roleのARN>"
        }
    ]
}

これですべての準備が整いました。
続いて、メンテナンスウィンドウの設定に移ります。

メンテナンスウィンドウの作成

AWS Management ConsoleのSystems Managerコンソールに移動し、「メンテナンスウィンドウの作成」を選択します。

メンテナンスウィンドウの作成
リソースグループ作成画面での入力内容を説明します。

まず、「名前」、必要であれば「説明」にそれぞれ情報を入力します。

「未登録ターゲット」は、デフォルトでチェックがついています。あとからターゲットが増える場合があるので、このままにしておくことを推奨します。
スケジュールでは、時間の設定やCRON式で実行頻度を指定できます。
CRON式では、下記の様な設定が可能です。

内容
cron(0 2 ? * THU#3 *) 毎月第 3 木曜日午前 2 時
cron(15 10 ? * * *) 毎日午前 10 時 15 分
cron(15 10 ? * MON-FRI *) 毎週月~金曜日、午前 10 時 15 分
cron(0 2 L * ? *) 毎月末日の午前 2 時
cron(15 10 ? * 6L *) 毎月最終金曜日午前 10 時 15 分

参考URL:System Manager の Cron および rate 式

「期間」には、1~24 の値でメンテナンスウィンドウの実行時間を設定します。
「タスクの開始を停止する」では、メンテナンス時間枠が終了する前に、システムが新しいタスクの実行スケジュールを停止する時間数を入力します。
参考URL:

  1. AWS公式 Use Case Labs MAINTENANCE WINDOW
  2. [EC2 Systems Manager] Maintenance Windowsの「Duration」と「Stop initiating tasks」とは何か? | DevelopersIO

「ウィンドウ開始日」には、指定したスケジュールをいつから、もしくはいつまで実行したいという希望がある場合に指定します。

「スケジュールのタイムゾーン」では、指定したスケジュールのタイムゾーンを設定できます。
日本時間で記載したのであれば、「(GMT+9:00) Asia/Tokyo」を選択します。

「スケジュールのオフセット」では、CRON 式で指定された日時からメンテナンスウィンドウを実行するまでに待機する日数を指定します。
CRON式でcron(0 30 23 ? * TUE#3 *)と指定した場合、毎月第 3 火曜日の午後 11:30 にメンテナンスウィンドウがスケジュールされますが、「スケジュールのオフセット」に 2 を指定すると、メンテナンスウィンドウは、毎月第 3 火曜日の 2 日後の午後 11:30 PM まで実行されません。
参考URL: メンテナンスウィンドウのスケジューリングおよび有効期間のオプション

「タグの管理」では、タグキーの名前と値のペアをメンテナンスウィンドウに適用します。

すべて入力が完了したら「メンテナンスウィンドウの作成」で新規作成を完了させます。

ターゲットの登録

メンテナンスウィンドウを新規作成すると、作成したウィンドウが一覧にリストされます。
ターゲットを追加したいウィンドウIDをクリックし、ターゲットとなるインスタンスを登録します。
EC2やRDSなど、種類ごとに起動や停止で実行するオートメーションが異なるため、ターゲットでは種類別に登録します。

メンテナンスウィンドウの詳細画面で、「ターゲット」タブをクリックし、「ターゲットの登録」を選択します。

「ターゲットの選択」で「リソースグループを選択」を選び、先ほど作成したリソースグループを選択します。
次に、「リソースタイプ」で、EC2やRDSインスタンス、RDSクラスターなどから1つのものを選択します。
「Target name」には、「TargetEC2Instances」「TargetRDSInstances」など、種類が判別できるようなものを設定するとよいでしょう。

これでターゲットの入力は完了です。

タスクの登録

メンテナンスウィンドウの詳細画面へ戻り、「タスク」タブをクリックします。
画面右にある、「タスクの登録」というセレクトボックスから、「オートメーションタスクの登録」を選択し、タスク登録画面へ遷移します。

「オートメーションドキュメント」では、EC2を起動するタスクであれば、「AWS-StartEC2Instance」を選択し、「ターゲット」の項目で対象となるインスタンスを定義します。

「次によるターゲット」では、「登録済みターゲットグループの選択」を選択し、先ほど作成した、対象のEC2が定義されたターゲットを選択します。

「入力パラメータ」では、「InstanceId」に、{{ RESOURCE_ID }}と入力します。
「AutomationAssumeRole」は、オートメーションを実行するためのロールとして作成した「my-maintenance-window-role-policy」のARNを入力します。

「レート制御」で、「同時実行数」にはオートメーションを同時に実行するターゲットの数または割合を指定します。
「エラーのしきい値」では、何回もしくは何割失敗した場合にタスクを停止するかを指定します。

「IAM サービスロール」では、メンテナンスウィンドウを操作するためのロールとして作成した「my-maintenance-window-role」のARNを選択します。

これでオートメーションタスクの入力は完了です。
EC2の他にもターゲットがある場合や、停止は、別途タスクを登録します。

確認

メンテナンスウィンドウの一覧で、作成したウィンドウの次の実行時間を確認できます。
また、タスク実行の履歴は、Systems Managerコンソールの「オートメーション」で確認でき、正常に実行できなかった場合のエラー内容なども確認することができます。

さいごに

以上が、メンテナンスウィンドウ、リソースグループ、オートメーションを使用した、リソースの一括起動、一括停止を自動化する方法となります。
設定する箇所が多いですが、タグでのリソース管理と連動できるので、複数リソースの起動停止の管理が必要な際に活用していただければと思います。
複数のRDSインスタンスを、オートメーションの対象インスタンスに同時指定する方法は、今回紹介したやり方以外では、2023年12月現在存在していない様ですし、
また、この方法を実施する上でロールやタスク登録の詳細な説明は、公式ドキュメントをはじめ充実していなかったので、本稿が皆様のお役に立てれば幸いです。