Click here to Skip to main content
15,867,704 members
Articles / Hosted Services / AWS

Start/Stop RDS Instances on Schedule

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
5 Jun 2017CPOL3 min read 56.3K   759   7   26
How to start/stop RDS instances on schedule with aws-sdk, nodeJs Lambda function and CloudWatch

Introduction

As you might know, AWS recently added an ability to start and stop RDS instances, which can be really helpful for anyone who wants to save some costs on AWS bill. Let's use AWS Lambda function with CloudWatch events to stop RDS instances used by testing environment at night and on weekends.

Using the Code

First, let's create policy, which is in AWS IAM console. Go to Services -> Policies -> Create Policy -> Create Your Own Policy.

Let's call it RDSManagement. Put the code given below to the 'Policy Document' field:

JavaScript
{
    "Version": "2012-10-17",
    "Statement": [        
        {
            "Action": [
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

Press 'Create policy', Create Your Own Policy put name, description and JSON to the appropriate fields and press Save. Eventually, you have to get something like on the screenshot below:

The second step is to create a role which will be associated with lambda function and allow it to manage RDS instances.

Navigate to Services -> Roles -> Create New Role. Select 'AWS Lambda' in 'AWS Service Role' section. Search for the policy we created previously, select it, and press 'Next'. Put LambdaRDSManagement as a Role Name, set some description and press 'Create Role'.

Now we are ready to go and create lambda function which will manage our instances. Navigate to Services -> Lambda -> Create a Lambda function -> Blank function. Let's call it 'ManageRDSInstances', select latest Node js 6.x as a runtime. Ignore lambda function code for now, and select 'Choose an existing role' in 'Role' field. You have to be able to find the previously created role in 'Existing role' field. Press 'Next' -> 'Create function'.

Good, a puppet for the function is created and ready to go. You can check out a repo on github, clone it, run 'npm install', archive the whole folder to a '.ZIP' file. (Or just download it - rds-lambda-stop-start.zip). We are using original aws-sdk for node js provided by Amazon.

It contains mainly three files:

  1. index.js - which is an actual lambda function which will handle your CloudWatch event:
    JavaScript
    var startInstance = require('./start');
    var stopInstance = require('stop');
    
    exports.handler = (event, context, callback) => {
        event.instances.forEach((instance) => {
            switch (event.action) {
                case 'stop':
                    console.log(`Stopping instance '${instance}'...`);
                    stopInstance(instance);
                    break;
                case 'start':
                    console.log(`Starting instance '${instance}'...`);
                    startInstance(instance);
                    break;
                default:
                    throw `Invalid action ${event.action}`;
            }
        })
        callback(null, 'Done!');
    };
  2. stop.js, which stops running instance and create RDS snapshot in format "{instanceId}-{day}-{month}-{year}-{ticks}":
    JavaScript
    var AWS = require('aws-sdk');
    
    module.exports = (instanceId) => {
      var rds = new AWS.RDS();
      var today = new Date();
      var params = {
        DBInstanceIdentifier: instanceId,
        DBSnapshotIdentifier: `${instanceId}-${today.getDate()}-
                               ${today.getMonth() + 1}-${today.getFullYear()}-
                               ${today.getTime()}`
      };
      rds.stopDBInstance(params, function (err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else console.log(data);           // successful response
      });
    };
  3. start.js which starts stopped instance.
    JavaScript
    var AWS = require('aws-sdk');
    
    module.exports = (instanceId) => {
      var rds = new AWS.RDS();
      var params = {
        DBInstanceIdentifier: instanceId
      };
      rds.startDBInstance(params, function (err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else console.log(data);           // successful response
      });
    };

Now let's upload our archive to newly created lambda function. Services -> Lambda -> ManageRDSInstances, and change Code entry type to 'Upload a .ZIP file'. Press 'Upload', select your zip file and press 'Save'. Now we need to configure test event: Actions -> Configure test event.

JavaScript
{  
   "instances":[  
      "some-test-instance-1",
      "some-test-instance-2"
   ],
   "action":"stop"
}

Where some-test-instance-1 and some-test-instance-2 are your testing RDS instances. After pressing 'Save and Test', you will see that your RDS instances changed state to 'Stopping' and soon to 'Stopped'. Presto!

After they are stopped, you can run the same test with action 'start', which will run change state of instances to running.

The last thing is to set up CloudWatch rules to trigger these function on schedule. Services -> CloudWatch -> Rules -> Create Rule. Select Schedule instead of default Event Pattern. Now you need to set up cron time, you can read more about it here. Keep in mind that time must be set in GMT timezone. For instance, to correctly start instances every morning Monday to Friday at 8 am in GMT+12 timezone cron time will look like this: '0 20 ? * SUN-THU *'.

After you set cron time for waking up your instances, select Lambda function as a Target and pick your newly create lambda function. Then in Configure Input section, put your JSON to Constant(JSON text) field:

JavaScript
{ "instances": ["some-test-instance-1",
"some-test-instance-2"], "action":"start" }

Configure Details -> Update rule. Done!

Now your instances will be woken every morning from Monday to Friday. Create a similar rule with correct cron time for stopping them, do not forget to change action from start to stop in the json:

JavaScript
{ "instances": ["some-test-instance-1",
"some-test-instance-2"], "action":"stop" }

Points of Interest

Starting/stopping RDS instances was a feature which was expected for a long while, and finally, guys from Amazon provided this functionality. Hopefully, this will reduce your AWS bill as well. :)

History

  • 2nd June, 2017 - Article created
  • 3rd June, 2017 - Fixed small mistakes, added images

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) MYOB
New Zealand New Zealand
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to get notifications through email after Start/Stop RDS Instances on Schedule !! Pin
Member 148252508-May-20 11:32
Member 148252508-May-20 11:32 
QuestionAWS Node.js 10.x Pin
Member 1404125920-Oct-19 18:17
Member 1404125920-Oct-19 18:17 
QuestionWork like charm Pin
Member 1455499911-Aug-19 18:14
Member 1455499911-Aug-19 18:14 
Questionurgent question why .zip file tobe upload required?? Pin
abhishekmittal25-Nov-18 18:37
abhishekmittal25-Nov-18 18:37 
AnswerRe: urgent question why .zip file tobe upload required?? Pin
abhishekmittal25-Nov-18 19:57
abhishekmittal25-Nov-18 19:57 
QuestionCloudwatch logs setup Pin
Member 1168407415-Nov-18 23:38
Member 1168407415-Nov-18 23:38 
QuestionThank you ! Pin
Member 140412591-Nov-18 22:08
Member 140412591-Nov-18 22:08 
QuestionQuantity Pin
Member 139322763-Aug-18 0:24
Member 139322763-Aug-18 0:24 
QuestionAWS Billing without any update Pin
Member 1391194917-Jul-18 4:46
Member 1391194917-Jul-18 4:46 
AnswerRe: AWS Billing without any update Pin
Matthew Dennis18-Jul-18 1:02
sysadminMatthew Dennis18-Jul-18 1:02 
QuestionRegarding instance id for RDS Pin
Radhika Peddi9-Apr-18 20:12
Radhika Peddi9-Apr-18 20:12 
Questionthanks Pin
Member 137090335-Mar-18 2:00
Member 137090335-Mar-18 2:00 
QuestionVery helpfull Pin
Member 4631993-Dec-17 7:37
Member 4631993-Dec-17 7:37 
QuestionThanks for this RDS stop start Pin
Member 134937881-Nov-17 9:41
Member 134937881-Nov-17 9:41 
Thanks for this RDS stop start
Chandan
dba.chandan@gmail.com

QuestionStop instance Part Not Working Pin
Member 1341541718-Sep-17 0:15
Member 1341541718-Sep-17 0:15 
AnswerRe: Stop instance Part Not Working Pin
Ivan Perevernykhata22-Nov-17 21:51
Ivan Perevernykhata22-Nov-17 21:51 
QuestionChange to TAGS Pin
Member 114298678-Sep-17 3:43
Member 114298678-Sep-17 3:43 
AnswerRe: Change to TAGS Pin
Ivan Perevernykhata22-Nov-17 21:53
Ivan Perevernykhata22-Nov-17 21:53 
GeneralRe: Change to TAGS Pin
Member 136085725-Jan-18 3:18
Member 136085725-Jan-18 3:18 
QuestionWhen I do npm install, I get the following error. Pin
ShabbirBata15-Aug-17 11:51
ShabbirBata15-Aug-17 11:51 
AnswerRe: When I do npm install, I get the following error. Pin
Ivan Perevernykhata22-Nov-17 21:54
Ivan Perevernykhata22-Nov-17 21:54 
QuestionSingle file/code? Pin
Jason Bradley15-Aug-17 10:36
Jason Bradley15-Aug-17 10:36 
GeneralMy vote of 5 Pin
Member 133446983-Aug-17 13:15
Member 133446983-Aug-17 13:15 
Questionvery good Pin
Member 133446983-Aug-17 13:14
Member 133446983-Aug-17 13:14 
AnswerRe: very good Pin
rammanusani26-Mar-19 8:47
rammanusani26-Mar-19 8:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.