スキップしてコンテンツを表示

ステップ関数を使用して Amazon RDS インスタンスを 7 日以上停止する方法を教えてください。

所要時間6分
0

AWS Step Functions を使用して Amazon Relational Database Service (Amazon RDS) を 7 日間以上停止したいです。

簡単な説明

デフォルトでは、Amazon RDS データベースインスタンスを一度に最大 7日間停止することができます。7 日後、インスタンスはメンテナンスの更新を見逃さないように再起動します。

インスタンスを 7 日以上停止する場合は、Step Functions を使用してワークフローを自動化することで、メンテナンスウィンドウを逃さないで済みます。

注: 別の解決策については、「Lambda 関数を使用して Amazon RDS インスタンスを 7 日以上停止する方法を教えてください」を参照してください。

解決方法

IAM アクセス許可を設定する

Step Functions が RDS インスタンスを開始および停止できるようにする AWS Identity and Access Management (IAM) ポリシーを作成するには、次の手順を実行します。

  1. IAM コンソールを開きます。

  2. ナビゲーションペインで [ポリシー] をクリックし、[ポリシーの作成] を選択します。

  3. [JSON] タブをクリックし、次のステートメントを入力します。

    {    "Version": "2012-10-17",
        "Statement":
        [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "rds:DescribeDBInstances",
                    "rds:StopDBInstance",
                    "rds:StartDBInstance"
                ],
                "Resource": "*"
            }
        ]
    }
    
  4. [次へ] をクリックします。

  5. [ポリシー名] にポリシー名を入力します。例えば、step-functions-start-stop-rds-policy と入力します。

  6. (オプション) タグを追加するには、[新しいタグを追加] をクリックし、[キー] フィールドと [値] フィールドに値を入力します。

  7. [ポリシーを作成] をクリックします。

詳細については、「JSON エディターを使用したポリシーの作成」を参照してください。

IAM ロールを作成し、必要なポリシーをアタッチする

次の手順を実行します。

  1. IAM コンソールを開きます。
  2. ナビゲーションペインで [ロール] をクリックし、[ロールを作成] を選択します。
  3. [信頼するエンティティを選択][AWS サービス] を選択します。
  4. [他の AWS サービスのユースケース] ドロップダウンリストから、[Step Functions] を選択します。
  5. [次へ] をクリックします。
    注: [アクセス許可を追加] ページでは何も実行しないでください。最初にロールを作成してから、デフォルトのアクセス許可を編集します。
  6. [次へ] をクリックします。
  7. [ロール名] に、ロールの名前を入力します。例えば、step-functions-start-stop-rds-role と入力します。
    (オプション) ロールの説明を入力します。
    (オプション) タグを追加するには、[新しいタグを追加] を選択してから、[キー] フィールドと [値] フィールドに値を入力します。
  8. [ロールの作成] をクリックします。これにより、[ロール] ページに戻ります。
  9. 検索ボックスに、作成したロールの名前を入力し、そのロールを選択して詳細を表示します。
  10. [アクセス許可] タブで、[アクセス許可の追加] ドロップダウンリストを選択してから、[ポリシーをアタッチ] を選択します。
  11. 検索ボックスに、「IAM アクセス許可を設定する」セクションで作成したポリシーの名前を入力します。例えば、step-functions-start-stop-rds-policy と入力してからポリシーを選択します。
  12. [アクセス許可] タブで AWSLambdaRole AWS マネージドポリシーを選択し、[削除] をクリックします。

詳細については、「AWS のサービス用ロールの作成 (コンソール)」を参照してください。

データベースインスタンスにタグを追加する

次の手順を実行します。

  1. Amazon Aurora と RDS コンソールを開きます。
  2. ナビゲーションペインで [データベース] をクリックします。
  3. 自動的に開始および停止するデータベースインスタンスを選択します。
  4. [タグ] タブをクリックします。
  5. [追加] をクリックします。[タグキー]autostart と入力します。[値]yes と入力します。
  6. [別のタグを追加] をクリックします。[タグキー]autostop と入力します。[値] に yes と入力します。
  7. [追加] をクリックします。

詳細については、「Amazon RDS でのタグの追加と削除」を参照してください。

タグ付けされたデータベースインスタンスを開始および停止するステートマシンを作成する

次の手順を実行します。

  1. Step Functions コンソールを開いて、[今すぐ始める] をクリックします。

  2. [ステートマシンを作成][自分で作成する] を選択します。

  3. ステートマシン名を入力します。例えば、step-functions-start-stop-rds-state-machine と入力します。

  4. [ステートマシンタイプ][標準] をクリックし、[続行] を選択します。

  5. [コード] タブをクリックし、次のステートマシン定義を入力します。

    {  "Comment": "State Machine Definition to start and stop RDS DB instances",
      "StartAt": "Describe DBInstances to Start",
      "States": {
        "Describe DBInstances to Start": {
          "Type": "Task",
          "Parameters": {},
          "Resource": "arn:aws:states:::aws-sdk:rds:describeDBInstances",
          "Next": "Iterate on Instances to Start",
          "Retry": [
            {
              "ErrorEquals": [
                "Rds.InternalFailure",
                "Rds.ServiceUnavailable",
                "Rds.ThrottlingException",
                "Rds.SdkClientException"
              ],
              "BackoffRate": 2,
              "IntervalSeconds": 1,
              "MaxAttempts": 2
            }
          ]
        },
        "Iterate on Instances to Start": {
          "Type": "Map",
          "ItemProcessor": {
            "ProcessorConfig": {
              "Mode": "INLINE"
            },
            "StartAt": "Format Array before Start",
            "States": {
              "Format Array before Start": {
                "Type": "Pass",
                "Next": "Check If Instance stopped, if no Tags or if Tags contains 'autostart=yes'",
                "Parameters": {
                  "DbInstanceStatus.$": "$.DBInstance.DbInstanceStatus",
                  "DbInstanceIdentifier.$": "$.DBInstance.DbInstanceIdentifier",
                  "TagList.$": "$.DBInstance.TagList",
                  "TagsArrayLength.$": "States.ArrayLength($.DBInstance.TagList)",
                  "TagContainsKey.$": "States.ArrayContains($.DBInstance.TagList,$.LookingFor)"
                }
              },
              "Check If Instance stopped, if no Tags or if Tags contains 'autostart=yes'": {
                "Type": "Choice",
                "Choices": [
                  {
                    "Not": {
                      "Variable": "$.DbInstanceStatus",
                      "StringEquals": "stopped"
                    },
                    "Next": "Instance is not in 'stopped' status"
                  },
                  {
                    "Variable": "$.TagsArrayLength",
                    "NumericEquals": 0,
                    "Next": "No Tags found to Start"
                  },
                  {
                    "Variable": "$.TagContainsKey",
                    "BooleanEquals": true,
                    "Next": "Tags found Start DBInstance"
                  }
                ],
                "Default": "No Tags found to Start"
              },
              "Tags found Start DBInstance": {
                "Type": "Task",
                "Parameters": {
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                },
                "Resource": "arn:aws:states:::aws-sdk:rds:startDBInstance",
                "Retry": [
                  {
                    "ErrorEquals": [
                      "Rds.InternalFailure",
                      "Rds.ServiceUnavailable",
                      "Rds.ThrottlingException",
                      "Rds.SdkClientException"
                    ],
                    "BackoffRate": 2,
                    "IntervalSeconds": 1,
                    "MaxAttempts": 2
                  }
                ],
                "Catch": [
                  {
                    "ErrorEquals": [
                      "States.ALL"
                    ],
                    "Next": "Failed to Start DBInstance"
                  }
                ],
                "ResultSelector": {
                  "message": "Instance Started",
                  "DbInstanceIdentifier.$": "$.DbInstance.DbInstanceIdentifier"
                },
                "End": true
              },
              "Failed to Start DBInstance": {
                "Type": "Pass",
                "Parameters": {
                  "message": "Failed to start instance",
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                },
                "End": true
              },
              "No Tags found to Start": {
                "Type": "Pass",
                "End": true,
                "Parameters": {
                  "message": "No Tags found to Start",
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                }
              },
              "Instance is not in 'stopped' status": {
                "Type": "Pass",
                "End": true,
                "Parameters": {
                  "message": "Instance is not in 'stopped' status",
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                }
              }
            }
          },
          "InputPath": "$.DbInstances",
          "Next": "Wait for 1 hour and 30 minutes",
          "ItemSelector": {
            "LookingFor": {
              "Key": "autostart",
              "Value": "yes"
            },
            "DBInstance.$": "$$.Map.Item.Value"
          }
        },
        "Wait for 1 hour and 30 minutes": {
          "Type": "Wait",
          "Seconds": 5400,
          "Next": "Describe DBInstances to Stop"
        },
        "Describe DBInstances to Stop": {
          "Type": "Task",
          "Parameters": {},
          "Resource": "arn:aws:states:::aws-sdk:rds:describeDBInstances",
          "Retry": [
            {
              "ErrorEquals": [
                "Rds.InternalFailure",
                "Rds.ServiceUnavailable",
                "Rds.ThrottlingException",
                "Rds.SdkClientException"
              ],
              "BackoffRate": 2,
              "IntervalSeconds": 1,
              "MaxAttempts": 2
            }
          ],
          "Next": "Iterate on Instances to Stop"
        },
        "Iterate on Instances to Stop": {
          "Type": "Map",
          "ItemProcessor": {
            "ProcessorConfig": {
              "Mode": "INLINE"
            },
            "StartAt": "Format Array before Stop",
            "States": {
              "Format Array before Stop": {
                "Type": "Pass",
                "Next": "Check If Instance available, if no Tags or if Tags contains 'autostop=yes'",
                "Parameters": {
                  "DbInstanceStatus.$": "$.DBInstance.DbInstanceStatus",
                  "DbInstanceIdentifier.$": "$.DBInstance.DbInstanceIdentifier",
                  "TagList.$": "$.DBInstance.TagList",
                  "TagsArrayLength.$": "States.ArrayLength($.DBInstance.TagList)",
                  "TagContainsKey.$": "States.ArrayContains($.DBInstance.TagList,$.LookingFor)"
                }
              },
              "Check If Instance available, if no Tags or if Tags contains 'autostop=yes'": {
                "Type": "Choice",
                "Choices": [
                  {
                    "Not": {
                      "Variable": "$.DbInstanceStatus",
                      "StringEquals": "available"
                    },
                    "Next": "Instance is not in 'available' status"
                  },
                  {
                    "Variable": "$.TagsArrayLength",
                    "NumericEquals": 0,
                    "Next": "No Tags found to Stop"
                  },
                  {
                    "Variable": "$.TagContainsKey",
                    "BooleanEquals": true,
                    "Next": "Tags found Stop DBInstance"
                  }
                ],
                "Default": "No Tags found to Stop"
              },
              "Tags found Stop DBInstance": {
                "Type": "Task",
                "Parameters": {
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                },
                "Resource": "arn:aws:states:::aws-sdk:rds:stopDBInstance",
                "Retry": [
                  {
                    "ErrorEquals": [
                      "Rds.InternalFailure",
                      "Rds.ServiceUnavailable",
                      "Rds.ThrottlingException",
                      "Rds.SdkClientException"
                    ],
                    "BackoffRate": 2,
                    "IntervalSeconds": 1,
                    "MaxAttempts": 2
                  }
                ],
                "Catch": [
                  {
                    "ErrorEquals": [
                      "States.ALL"
                    ],
                    "Next": "Failed to Stop DBInstance"
                  }
                ],
                "ResultSelector": {
                  "message": "Instance Stopped",
                  "DbInstanceIdentifier.$": "$.DbInstance.DbInstanceIdentifier"
                },
                "End": true
              },
              "Failed to Stop DBInstance": {
                "Type": "Pass",
                "Parameters": {
                  "message": "Failed to stop instance",
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                },
                "End": true
              },
              "No Tags found to Stop": {
                "Type": "Pass",
                "End": true,
                "Parameters": {
                  "message": "No Tags found to Stop",
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                }
              },
              "Instance is not in 'available' status": {
                "Type": "Pass",
                "End": true,
                "Parameters": {
                  "message": "Instance is not in 'available' status",
                  "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
                }
              }
            }
          },
          "InputPath": "$.DbInstances",
          "Next": "Workflow Finished",
          "ItemSelector": {
            "LookingFor": {
              "Key": "autostop",
              "Value": "yes"
            },
            "DBInstance.$": "$$.Map.Item.Value"
          }
        },
        "Workflow Finished": {
          "Type": "Succeed"
        }
      }
    }

    注: [1 時間 30 分待機] パラメータでは、テスト用に Seconds フィールドの値を変更できます。例えば、Seconds フィールドの値を、より長いメンテナンスウィンドウまたは短いメンテナンスウィンドウに変更できます。

  6. [Config] をクリックし、[作成] を選択します。

  7. [ロールの作成の確認][確認] を選択します。

  8. [実行開始] をクリックします。

Stopped 状態のタグ付きデータベースインスタンスの機能テストを実行する

次の手順を実行します。

  1. Step Functions コンソールを開きます。
  2. ナビゲーションペインで [ステートマシン] をクリックします。
  3. データベースインスタンスを開始するために作成したステートマシンを選択します。例えば、step-functions-start-stop-rds-state-machine などです。
  4. [実行開始] をクリックします。
    注: この解決策にはイベントペイロードは必要ありません。[実行を開始] ダイアログでは、イベントペイロードを削除することも、デフォルトイベントのままにすることもできます。
  5. [実行開始] をクリックします。

スケジュールを作成する

タグ付けされたデータベースインスタンスの毎週のメンテナンスウィンドウをスケジュールするには、Amazon EventBridge ルールを作成します。このルールは、メンテナンスウィンドウの 30 分前に自動的にデータベースインスタンスを開始します。

次の例では、メンテナンスウィンドウは日曜日の 22:00~22:30 の間に発生します。このルール例では、毎週日曜日の 21:30 にデータベースインスタンスを開始します。

スケジュールを作成するには、次の手順を実行します。

  1. EventBridge コンソールを開きます。
  2. [EventBridge スケジュール] をクリックし、[スケジュールを作成] を選択します。
  3. スケジュール名を入力します。例えば、step-function-start-stop-schedule などです。[スケジュールグループ][デフォルト] のままにします。
  4. [スケジュールパターン][定期的なスケジュール] を選択します。
  5. [スケジュールの種類][cron ベースのスケジュール] を選択します。
  6. 自動スケジュールに cron 式を追加します。例えば、cron(30 21 ? * SUN *) と入力します。
  7. [フレックスタイムウィンドウ] では、[オフ] を選択します。
  8. [次へ] をクリックします。
  9. [ターゲットの詳細] で、[テンプレート化されたターゲット] を選択し、[StartExecution] を選択します。
  10. [StartExecution] で、「タグ付けされたデータベースインスタンスを開始および停止するステートマシンを作成する」セクションで作成したステートマシンを選択します。例えば、step-functions-start-stop-rds-state-machine を選択します。入力のデフォルト値は {} のままにしてください。
  11. [次へ] をクリックします。
  12. [再試行ポリシーとデッドレターキュー (DLQ)] で、[再試行ポリシー] スイッチをオフに設定します。
  13. [デッドレターキュー (DLQ)][なし] を選択します。
  14. [アクセス許可] で以下を選択します。 [このスケジュールの新しいロールを作成] を選択し、[次へ] をクリックします。
    注: EventBridge は引き受け用の新しいロールを作成し、ワークフローの StartExecution API を起動します。
  15. [スケジュールの詳細] で、次の 10 件の呼び出し日が予定されているスケジュールの日付と一致していることを確認し、[スケジュールの作成] を選択します。

EventBridge がルールを呼び出すと、Step Function ワークフローが開始されます。これにより、メンテナンスウィンドウの 30 分前にデータベースインスタンスが開始します。その後、ワークフローは、メンテナンスウィンドウが完了してから 30 分後にデータベースインスタンスを停止します。例えば、このワークフローはデータベースインスタンスを 21:30 に開始します。メンテナンスウィンドウは 22:00 ~ 22:30 です。その後、ワークフローはインスタンスを 23:00 に停止します。

コメントはありません