Rodrigo Ascenção

DevOps Engineer

Automatically stop and start an RDS DB instance using AWS Systems Manager Maintenance Windows

Introduction

Reducing costs on AWS is a very important thing. Sometimes, we struggle to identify where we can reduce costs because everything seems important and we can’t simply delete resources.

In this post, I’ll guide you through a very interesting idea to help reduce AWS costs: automatically stopping RDS instances during off-peak hours and starting them again during business hours.

AWS provides very good documentation that I followed in order to accomplish this goal. You can check it out here: AWS Documentation

I wrapped up the most important points on how to implement this solution, so feel free to follow the step-by-step guide here as well =)

Summary

This pattern demonstrates how to automatically stop and start an Amazon Relational Database Service (Amazon RDS) DB instance on a specific schedule (for example, shutting down a DB instance outside of business hours to reduce costs) by using AWS Systems Manager Maintenance Windows. For this purpose, Systems Manager is cost-effective for typical use cases.

AWS Systems Manager Automation provides the  AWS-StopRdsInstance and AWS-StartRdsInstance runbooks to stop and start RDS DB instances. This means that you don’t need to write custom logic with AWS Lambda functions or create an Amazon CloudWatch Events rule.

Maintenance Windows

Systems manager provides two capabilities for scheduling tasks: State manager and Maintenance Windows.

For our purpose here we’re gonna use Maintenance Windows, which is the standard recommended way for this kind of task.

This post provides detailed steps to configure two separate maintenance windows that use cron expressions to stop and then start an RDS DB instance.

Workflow

The workflow has the following steps:

  1. Create a maintenance window and use cron expressions to define the stop and start schedule for your Amazon RDS DB instances.

  2. Register a Systems Manager Automation task to the maintenance window by using the AWS-StopRdsInstance or AWS-StartRdsInstance runbook.

  3. Register a target with the maintenance window by using a tag-based resource group for your Amazon RDS DB instances.

Starting to build

Step 1 - IAM Service Role for Automation + Policy

In the first step we’re gonna create a service role for automation using the cloudformation template provided by AWS.

Create the service role using CloudFormation

Resources:

AutomationServiceRole:

Type: AWS::IAM::Role

Properties:

AssumeRolePolicyDocument:

Version: '2012-10-17'

Statement:

- Effect: Allow

Principal:

Service:

- ssm.amazonaws.com

Action: sts:AssumeRole

Condition:

StringEquals:

aws:SourceAccount: !Sub ${AWS::AccountId}

ArnLike:

aws:SourceArn: !Sub arn:aws:ssm:*:${AWS::AccountId}:automation-execution/*

ManagedPolicyArns:

- arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole

Path: "/"

RoleName: AutomationServiceRole

This is the CloudFormation template provided by AWS to create AutomationServiceRole. Once you have it, follow the step by step:

  1. Open the CloudFormation console
  2. Choose Create Stack
  3. In the Specify template section, choose Upload a template file.
  4. Choose Browse, and then choose the AWS-SystemsManager-AutomationServiceRole.yaml CloudFormation template file.
  5. Choose Next.
  6. On the Specify stack details page, in the Stack name field, enter a name.
  7. On the Configure stack options page, you don’t need to make any selections. Choose Next.
  8. On the Review page, scroll down and choose the I acknowledge that CloudFormation might create IAM resources option.
  9. Choose Create

Attach IAM Policy allowing Stop and Start DB Instance

Once you create the AutomationServiceRole with the template provided above, you’ll need to attach this policy to the role and provide the ARN of the DB instance that you want to perform these actions.

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "RdsStartStop",
                "Effect": "Allow",
                "Action": [
                    "rds:StopDBInstance",
                    "rds:StartDBInstance"
                ],
                "Resource": "<RDS_Instance_ARN>"               
            },
            {
                "Sid": "RdsDescribe",
                "Effect": "Allow",
                "Action": "rds:DescribeDBInstances",
                "Resource": "*"
            }
        ]
    }

Step 2 - Create a resource group

Now that we have the AutomationServiceRole deployed, we need to tag the RDS Instances that we want to stop and start automatically and attach to a resource group.

Tag the RDS Instance:

Open the Amazon RDS console and tag the Amazon RDS DB instances that you want to add to the resource group. A tag is metadata assigned to an AWS resource and consists of a key-value pair. We recommend that you use Action as the Tag key and StartStop as the Value.

Create a resource group for tagged RDS Instance:

Open the AWS Resource Groups console and create a resource group based on the tag that you created for your Amazon RDS DB instances.

Under Grouping Criteria, make sure that you choose AWS::RDS::DBInstance for the resource type and then provide the tag’s key-value pair (for example, “Action-StartStop”). This ensures that the service only checks for Amazon RDS DB instances and not other resources that have this tag. Make sure that you record the resource group’s name.

Step 3 - Configure a maintenance window to stop the RDS instance

Create a maintenance window.

  1. Open the Systems Manager console, choose Maintenance Windows, and then choose Create a maintenance window. Provide a name for your maintenance window (for example, “StopRdsInstance”), enter a description, and then uncheck Allow unregistered targets.

  2. Choose CRON/Rate expression and provide the schedule expression to define when the Amazon RDS DB instances should be stopped. Enter 1 for the Duration and 0 for Stop initiating tasks. By default, the Time zone shows UTC. You can change the time zone to initiate the maintenance window based on the timestamp defined in your cron expression.

  3. Choose Create maintenance window. The system returns you to the maintenance window page and the state of your maintenance window is Enabled.

Assign a target to the maintenance window.

  1. On the Systems Manager console, choose Maintenance Windows, choose Actions, and then choose Register targets.

  2. In the Targets area, specify Choose a resource group and then choose the name of an existing resource group in your account.

  3. For Resource types, choose AWS::RDS::DBInstance and then choose Register target.

Assign a task to the maintenance window.

  1. On the Systems Manager console, choose Maintenance Windows, and then choose your maintenance window. Choose Actions, and then choose Register Automation task

  2. For Document, choose AWS-StopRdsInstance

  3. In the Targets section, choose Selecting registered target groups, and then choose the maintenance window target that you registered with the current maintenance window.

  4. For Rate control, specify 100 percent for Concurrency and Error threshold. You can change the Rate control values according to your requirements for task concurrency and error threshold. For more information about this, see About concurrency and error thresholds in the Systems Manager documentation.

  5. In the IAM service role section, for Service role, leave this box blank or create your own custom role. If you leave the box blank, Systems Manager automatically creates the service-linked role AWSServiceRoleForAmazonSSM and then associates the role with the task. To create your own custom role, see Create a custom service role for maintenance windows (console), and then associate that custom role with the task.

  6. In the Input Parameters section, specify the following parameters for the runbook:

    InstanceId{{RESOURCE_ID}}

    Note:

    For InstanceId, a pseudo parameter is used to extract the Amazon RDS DB resource ID from the ARN. To learn more about pseudo parameters, see About pseudo parameters in the Systems Manager documentation.

    AutomationAssumeRole: Provide the ARN of the service role that you created for Systems Manager Automation.

  7. Choose Register Automation task.

Final STEP - Configure a maintenance window to start the Amazon RDS DB instances

Repeat the steps from the Configure a maintenance window to stop the Amazon RDS DB instances epic to configure another maintenance window to start the Amazon RDS DB instances at a scheduled time.

Important

You must make the following changes when you configure the maintenance window to start the DB instances:

Use a new name for the maintenance window (for example, “StartRdsInstance”).

Replace the cron expression with the cron expression that you want to use to start the DB instances.

Replace the AWS-StopRdsInstance runbook with AWS-StartRdsInstance in Task.