如何使用 Step Functions 将 Amazon RDS 实例停止 7 天以上?
我想使用 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) 策略,请完成以下步骤:
-
打开 IAM 控制台。
-
在导航窗格中,选择 Policies(策略),然后选择 Create policy(创建策略)。
-
选择 JSON 选项卡,然后输入以下语句:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "rds:DescribeDBInstances", "rds:StopDBInstance", "rds:StartDBInstance" ], "Resource": "*" } ] } -
选择 Next(下一步)。
-
对于 Policy name(策略名称),输入您的策略的名称。例如,输入 step-functions-start-stop-rds-policy。
-
(可选)要添加标签,请选择 Add new tag(添加新标签),然后为 Key(键)和 Value(值)字段输入相应的值。
-
选择 Create policy(创建策略)。
有关更多信息,请参阅使用 JSON 编辑器创建策略。
创建 IAM 角色并附加所需的策略
完成以下步骤:
- 打开 IAM 控制台。
- 在导航窗格中,选择 Roles(角色),然后选择 Create role(创建角色)。
- 对于 Select type of trusted entity(选择可信实体类型),选择 AWS service(AWS 服务)。
- 在 Use cases for other AWS service(其他 AWS 服务的使用案例)下拉列表中,选择 Step Functions。
- 选择 Next(下一步)。
**注意:**请勿在 Add permissions(添加权限)页面上执行任何操作。首先创建角色,然后编辑默认权限。 - 选择 Next(下一步)。
- 对于 Role name(角色名称),输入角色的名称。例如,输入 step-functions-start-stop-rds-role。
(可选)输入角色描述。
(可选)要添加标签,请选择 Add new tag(添加新标签),并为 Key(键)和 Value(值)字段输入相应的值。 - 选择 Create role(创建角色)。这样会让您返回到 Roles(角色)页面。
- 在搜索框中,输入您创建的角色的名称,然后选择该角色以查看详细信息。
- 在 Permissions(权限)选项卡中,选择 Add permissions(添加权限)下拉列表,然后选择 Attach policies(附加策略)。
- 在搜索框中,输入您在 Configure IAM permissions(配置 IAM 权限)部分中创建的策略的名称。例如,输入 step-functions-start-stop-rds-policy,然后选择该策略。
- 在 Permissions(权限)选项卡中,选择 AWSLambdaRole AWS 托管式策略,然后选择 Remove(移除)。
有关更多信息,请参阅创建用于 AWS 服务的角色(控制台)。
为数据库实例添加标签
完成以下步骤:
- 打开 Amazon Aurora 和 RDS 控制台。
- 在导航窗格中,选择 Databases(数据库)。
- 选择要自动启动和停止的数据库实例。
- 选择 Tags(标签)选项卡。
- 选择 Add(添加)。对于 Tag key(标签键),输入 autostart。对于 Value(值),输入 yes。
- 选择 Add another Tag(添加其他标签)。对于 Tag key(标签键),输入 autostop。对于 Value(值),输入 yes。
- 选择 Add(添加)。
有关更多信息,请参阅在 Amazon RDS 中添加和删除标签。
创建状态机以启动和停止已标记的数据库实例
完成以下步骤:
-
打开 Step Functions 控制台,然后选择 Get started(开始)。
-
从 Create your state machine(创建状态机)中,选择 Create your own(创建自己的状态机)。
-
输入状态机名称。例如,输入 step-functions-start-stop-rds-state-machine。
-
对于 State machine type(状态机类型),选择 Standard(标准),然后选择 Continue(继续)。
-
选择 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(秒)字段值更改为更长或更短的维护时段。
-
选择 Config(配置),然后选择 Create(创建)。
-
对于 Confirm role creation(确认角色创建),选择 Confirm(确认)。
-
选择 Start execution(开始执行)。
对处于“已停止”状态的已标记的数据库实例运行功能测试
完成以下步骤:
- 打开 Step Functions 控制台。
- 在导航窗格中,选择 State machines(状态机)。
- 选择您为启动数据库实例而创建的状态机。例如,step-functions-start-stop-rds-state-machine。
- 选择 Start execution(开始执行)。
**注意:**此解决方法不需要事件有效载荷。在 Start execution(开始执行)对话框下,您可以移除事件有效载荷或保留默认事件。 - 选择 Start execution(开始执行)。
创建计划
要为已标记的数据库实例计划每周维护时段,请创建 Amazon EventBridge 规则。此规则会在维护时段前 30 分钟自动启动数据库实例。
在以下示例中,维护时段是星期日的 22:00-22:30。示例规则会在每个星期日的 21:30 启动数据库实例。
要创建计划,请完成以下步骤:
- 打开 EventBridge 控制台。
- 选择 EventBridge Schedule(EventBridge 计划),然后选择 Create schedule(创建计划)。
- 输入计划名称。例如,**step-function-start-stop-schedule。**将 Schedule group(计划组)保留为 default(默认)。
- 对于 Schedule pattern(计划模式),选择 Recurring schedule(定期计划)。
- 对于 Schedule type(计划类型),选择 Cron-based schedule(基于 Cron 的计划)。
- 为自动计划添加 cron 表达式。例如,输入 cron(30 21 ? * SUN *)。
- 对于 Flexible time window(弹性时间范围),选择 Off(关闭)。
- 选择 Next(下一步)。
- 对于 Target detail(目标详细信息),选择 Templated targets(模板化目标),然后选择 StartExecution。
- 在 StartExecution 下,选择您在 Create a state machine to start and stop the tagged database instances(创建状态机以启动和停止已标记的数据库实例)部分中创建的状态机。例如,选择 step-functions-start-stop-rds-state-machine。保留输入的默认值 {}。
- 选择 Next(下一步)。
- 在 Retry policy and dead-letter queue (DLQ)(重试策略和死信队列 (DLQ))下,将 Retry policy(重试策略)开关设置为关闭。
- 对于 Dead-letter queue (DLQ)(死信队列 (DLQ)),选择 None。
- 在 Permissions(权限)下,选择: Create new role for this schedule(为此计划创建新角色),然后选择 Next(下一步)。
**注意:**EventBridge 会创建一个要代入的新角色,并为您的工作流启动 StartExecution API。 - 在 Schedule detail(计划详细信息)下,验证接下来的 10 个调用日期是否与您的预期计划日期相符,然后选择 Create schedule(创建计划)。
Step Functions 工作流会在 EventBridge 调用该规则时启动。这会在维护时段前 30 分钟启动数据库实例。然后,工作流会在维护时段完成 30 分钟后停止数据库实例。例如,工作流在 21:30 启动您的数据库实例。维护时段是在 22:00–22:30。然后,工作流会在 23:00 停止您的实例。
- 语言
- 中文 (简体)
