跳至內容

如何使用 Step Functions 停止 Amazon RDS 執行個體超過 7 天?

7 分的閱讀內容
0

我想要使用 AWS Step Functions 停止 Amazon Relational Database Service (Amazon RDS) 超過 7 天的持續時間。

簡短說明

根據預設,您一次最多可以停止 Amazon RDS 資料庫執行個體 7 天。7 天後,執行個體會重新啟動,以免錯過任何維護更新。

若要停止您的執行個體超過 7 天,您可以使用 Step Functions 自動化工作流程,以免錯過維護時段。

**注意:**如需替代解決方法,請參閱如何使用 AWS Lambda 函式停止 Amazon RDS 執行個體超過七天?

解決方法

設定 IAM 權限

若要建立允許 Step Functions 啟動和停止 RDS 執行個體的 AWS Identity and Access Management (IAM) 政策,請完成以下步驟:

  1. 開啟 IAM console (IAM 主控台)。

  2. 在導覽窗格中,選擇 Policies (政策),然後選擇 Create policy (建立政策)。

  3. 選擇 JSON 索引標籤,然後輸入以下陳述式:

    {    "Version": "2012-10-17",
        "Statement":
        [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "rds:DescribeDBInstances",
                    "rds:StopDBInstance",
                    "rds:StartDBInstance"
                ],
                "Resource": "*"
            }
        ]
    }
    
  4. 選擇 Next (下一步)。

  5. 在 Policy name (政策名稱),輸入政策的名稱。例如,輸入 step-functions-start-stop-rds-policy。

  6. (選用) 若要新增標籤,請選擇 Add new tag (新增標籤),然後輸入 Key (鍵) 和 Value (值) 欄位的值。

  7. 選擇 Create policy (建立政策)。

如需更多資訊,請參閱使用 JSON 編輯器建立政策。

建立 IAM 角色並連接必要的政策

請完成以下步驟:

  1. 開啟 IAM console (IAM 主控台)。
  2. 在導覽窗格中,選擇 Roles (角色),然後選擇 Create role (建立角色)。
  3. 在 Select trusted entity (選取受信任實體),選擇 AWS service (AWS 服務)。
  4. 在 Use cases for other AWS service (其他 AWS 服務的使用案例) 下拉式清單中,選擇 Step Functions。
  5. 選擇 Next (下一步)。
    **注意:**請勿在 Add permissions (新增權限) 頁面上執行任何動作。請先建立角色,然後編輯預設權限。
  6. 選擇 Next (下一步)。
  7. 在 Role name (角色名稱),輸入角色的名稱。例如,輸入 step-functions-start-stop-rds-role。
    (選用) 輸入角色描述。
    (選用) 若要新增標籤,請選擇 Add new tag (新增標籤),然後輸入 Key (鍵) 和 Value (值) 欄位的值。
  8. 選擇 Create role (建立角色)。這會讓您返回 Roles (角色) 頁面。
  9. 在搜尋方塊中,輸入您建立的角色名稱,然後選取該角色以檢視詳細資訊。
  10. 在 Permissions (權限) 索引標籤中,選擇 Add Permissions (新增權限) 下拉式清單,然後選擇 Attach policies (連接政策)。
  11. 在搜尋方塊中,輸入您在設定 IAM 權限區段中建立的政策名稱。例如,輸入 step-functions-start-stop-rds-policy,然後選取政策。
  12. 在 Permissions (權限) 索引標籤中,選取 AWSLambdaRole AWS 受管政策,然後選擇 Remove (移除)。

如需更多資訊,請參閱為 AWS 服務建立角色 (主控台)。

為資料庫執行個體新增標籤

請完成以下步驟:

  1. 開啟 Amazon Aurora 和 RDS 主控台。
  2. 在導覽窗格中,選擇 Databases (資料庫)。
  3. 選取您要自動啟動和停止的資料庫執行個體。
  4. 選擇 Tags (標籤) 索引標籤。
  5. 選擇 Add (新增)。在 Tag key (標籤鍵),輸入 autostart。在 Value (值),輸入 yes。
  6. 選擇 Add another Tag (新增其他標籤)。在 Tag key (標籤鍵),輸入 autostop。在值中,輸入 yes。
  7. 選擇 Add (新增)。

如需更多資訊,請參閱在 Amazon RDS 中新增和刪除標籤。

建立狀態機器以啟動和停止已標記的資料庫執行個體

請完成以下步驟:

  1. 開啟 Step Functions console (Step Functions 主控台),然後選擇 Get started (開始使用)。

  2. 從 Create your state machine (建立您的狀態機器) 中,選擇 Create your own (自行建立)。

  3. 輸入狀態機器名稱。例如,輸入 step-functions-start-stop-rds-state-machine。

  4. 在 State machine type (狀態機器類型),選擇 Standard (標準),然後選擇 Continue (繼續)。

  5. 選擇 Code (程式碼) 索引標籤,然後輸入以下狀態機器定義:

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

    **注意:**在 Wait for 1 hour and 30 minutes (等待 1 小時 30 分鐘) 參數中,您可以變更 Seconds (秒) 欄位值以進行測試。例如,您可以將 Seconds (秒) 欄位值變更為較長或較短的維護時段。

  6. 選擇 Config (組態),然後選擇 Create (建立)。

  7. 在 Confirm role creation (確認角色建立),選擇 Confirm (確認)。

  8. 選擇 Start execution (開始執行)。

為處於已停止狀態的已標記資料庫執行個體執行函式測試

請完成以下步驟:

  1. 開啟 Step Functions console (Step Functions 主控台)。
  2. 在導覽窗格中,選擇 State machines (狀態機器)。
  3. 選取您建立用來啟動資料庫執行個體的狀態機器。例如,step-functions-start-stop-rds-state-machine。
  4. 選擇 Start execution (開始執行)。
    **注意:**此解決方法不需要事件承載。在 Start execution (開始執行) 對話方塊下,您可以移除事件承載或保留預設事件。
  5. 選擇 Start execution (開始執行)。

建立排程

若要為已標記的資料庫執行個體排定每週維護時段,請建立 Amazon EventBridge 規則。此規則會在維護時段前 30 分鐘自動啟動資料庫執行個體。

在以下範例中,維護時段發生在週日的 22:00-22:30。範例規則會在每週日 21:30 啟動資料庫執行個體。

若要建立排程,請完成以下步驟:

  1. 開啟 EventBridge console (EventBridge 主控台)。
  2. 選擇 EventBridge Schedule (EventBridge 排程),然後選擇 Create schedule (建立排程)。
  3. 輸入排程名稱。例如,**step-function-start-stop-schedule。**將 Schedule group (排程群組) 保留為 default (預設)。
  4. 在 Schedule pattern (排程模式),選擇 Recurring schedule (週期性排程)。
  5. 在 Schedule type (排程類型),選擇 Cron-based schedule (Cron 式排程)。
  6. 新增自動化排程的 cron 表達式。例如,輸入 cron(30 21 ? * SUN *)。
  7. 在 Flexible time window, (彈性時間範圍),選擇 Off (關閉)。
  8. 選擇 Next (下一步)。
  9. 在 Target detail (目標詳細資訊),選擇 Templated targets (範本化目標),然後選擇 StartExecution。
  10. 在 StartExecution 下,選取您在建立狀態機器以啟動和停止已標記的資料庫執行個體區段中建立的狀態機器。例如,選取 step-functions-start-stop-rds-state-machine。保留輸入的預設值 {}。
  11. 選擇 Next (下一步)。
  12. 在 Retry policy and dead-letter queue (DLQ) (重試政策和無效字母佇列 (DLQ)) 下,將 Retry policy (重試政策) 開關設定為關閉。
  13. 在 Dead-letter queue (DLQ) (無效字母佇列 (DLQ)),選擇 None (無)。
  14. 在 Permissions (權限) 下,選擇: 為此排程建立新角色,然後選擇 Next (下一步)。
    **注意:**EventBridge 會建立一個要擔任的新角色,並為您的工作流程啟動 StartExecution API。
  15. 在 Schedule detail (排程詳細資訊) 下,確認接下來 10 個調用日期符合您預期排程的日期,然後選擇 Create schedule (建立排程)。

當 EventBridge 調用規則時,Step Function 工作流程就會開始。這會在維護時段前 30 分鐘啟動資料庫執行個體。然後,工作流程會在維護時段完成後 30 分鐘停止資料庫執行個體。例如,工作流程會在 21:30 啟動您的資料庫執行個體。維護時段發生在 22:00–22:30。然後,工作流程會在 23:00 停止您的執行個體。