Stop/Start RDS Instances Automatically Using System Manager for Cost Optimization
Tags: aws, optimazation, cost, ssm
Published: 2023-09-12 01:15:56

Amazon Relational Database Service (Amazon RDS) is a web service that makes it easier to set up, operate, and scale a relational database in the AWS Cloud. It provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks. But there are some things that users should be manage like availability of the database, choosing the right size of database engine, maintaining backups, cost optimization and so on. 

In this post, we're going to take about Cost Optimization with the runtime of the database. For example, If you want to run your database instance only a certain time like 9 am to 6 pm in working days. But manually start the database in morning 9 am and stop it in evening 6 pm is boring. Some times you forget to start the database and it will lead the application downtime in the working hours.

But if you setup an automation process which is stop and start the RDS database daily, at the time which you specified. Could that be amazing? AWS provides a service called System Manager, which is we are gonna use to stop and start our database. Let’s get into the details now.

## What is AWS System Manager
[AWS Systems Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/what-is-systems-manager.html) is the operations hub for your AWS applications and resources and a secure end-to-end management solution for hybrid and multi-cloud environments that enables secure operations at scale. In the post, we will use one of capabilities of [System Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-state.html), which named State Manager. State Manager is a secure and scalable service that automates the process of keeping managed nodes in a hybrid and multi-cloud infrastructure in a state that you define.

In our example, RDS instance is a type of nodes that can be managed using automate process. To enable the automation, you should do the following steps:

1. Create IAM role and Policy for System Manager
2. Create SSM Associations for Stop/Start RDS Instance

## Create IAM role and Policy for System Manager
Firstly, you need to create an automation IAM role which grants start/stop RDS instance permissions to SSM. You can do it from AWS Console or any other IaC tools. Here are the details for the IAM role.

**Role Name**
StartStopRebootRDS

**Trust Relationships**

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

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds:Describe*",
                "rds:Start*",
                "rds:Stop*",
                "rds:Reboot*"
            ],
            "Resource": "*"
        }
    ]
}
```
## Create SSM Associations for Stop/Start RDS Instance
In the example, I'm going to implement: start RDS instance at 8:30 AM and stop it at 17:30 PM from Monday to Friday. As there is a limitation for the scheduled expression as below. We have to create a specific association for each day. 

> Schedule expression cron(0 30 08 ? * MON-FRI *) is currently not accepted. Supported expressions are every half, 1, 2, 4, 8 or 12 hour(s), every specified day and time of the week. Supported examples are: cron(0 0/30 * 1/1 * ? ), cron(0 0 0/4 1/1  ? ), cron (0 0 10 ?  SUN ), cron (0 0 10 ?  * *)
 
That's a batch of repeated manual stuff if creating associations from AWS console. I use AWS CLI to simplify the creation process.

Run below shell script to create SSM associations to start target RDS instances (billing-test) at 00:30 AM (UTC+8) from Monday to Friday. 

> My local time is UTC+0800, so the start instance cron expression for 08:30 AM is 00:30. So does the stop instance cron expression.

```bash
#!/bin/sh

WORKDAY="MON TUE WED THU FRI"

for day in $WORKDAY; do
    aws ssm create-association \
        --name AWS-StartRdsInstance \
        --schedule-expression "cron(30 0 ? * $day *)" \
        --association-name StartRDSInstance_$day\
        --parameters InstanceId=billing-test,AutomationAssumeRole=arn:{aws::partition}:iam::{aws:accountid}/role/StartStopRebootRDS \
        --profile your-credentials
done
```
Run below shell script to create SSM associations to stop target RDS instances (billing-test) at 17:30 PM (UTC+8) from Monday to Friday.

```bash
#!/bin/sh

WORKDAY="MON TUE WED THU FRI"

for day in $WORKDAY; do
    aws ssm create-association \
        --name AWS-StopRdsInstance \
        --schedule-expression "cron(30 9 ? * $day *)" \
        --association-name StopRDSInstance_$day\
        --parameters InstanceId=billing-test,AutomationAssumeRole=arn:{aws::partition}:iam::{aws:accountid}:role/StartStopRebootRDS \
        --profile your-credentials
done
```
Here is a screenshot of the associations I created using AWS CLI.


![Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdrwh7ztbm9zc0bocxpr.png)

## References

https://docs.aws.amazon.com/cli/latest/reference/ssm/create-association.html
https://www.easydeploy.io/blog/automate-rds-instance-using-system-manager/#Introduction
https://docs.aws.amazon.com/systems-manager/latest/userguide/state-manager-about.html