Using AWS Instance Scheduler

Carlos Andrés Herrera
Useless Nerd
Published in
8 min readDec 2, 2019

Automate the start/stop of your EC2 and RDS instances and save money

A clockwork mechanism
Your cloud environment, whether a small try or a production app must be fine tuned

For starters in AWS, it can be a painful experience to set up environments and try not to consume all the free-tier capacity or the budget you have provisioned for your tests, or any new small app; and as consequence of forgetting to shutdown or deleting things, receiving the infamous bill and the subsequent panic.

AWS is a behemoth and many have come to believe, that because of this, that it wants you to consume its services, through periodic and tiny amount expenses, disregarding any economic impact that may have on their potential or actual customers; every penny counts some say.

But no, the most interested party in the issue of keeping your costs at bay its AWS itself. For that reason, they provide a handy tool to control the costs of two of the headaches that usually accompany us when we’re starting spinning up things, EC2s and RDSs, we forgot about those too often and commonly, they’re the costliest services. This tool is the AWS Instance Scheduler (https://aws.amazon.com/fr/solutions/instance-scheduler/)

o setup this we’re going to need:

The Architecture

© Amazon Web Services

For this solution we’re going full server-less, this solution uses AWS Lambda as the engine that will do the heavy lifting, CloudWatch for event scheduling and monitoring, and DynamoDB for storing the configuration of the scheduler.

The solution works by checking a custom tag that will be applied to the EC2 and RDS resources that will be linked to the schedule you want to apply. This schedules are stored in a DynamoDB table; and yes you can have many schedules for different resources.

More clearly:

  • You define during the initial instance scheduler configuration a tag key named “Schedule”, and then you create a schedule named “weekdays-office-hours”. Also you define the AWS Regions on which the scheduler will be checking resources.
  • The key name and the schedule name are stored on the DynamoDB table
  • You apply this Key:value pair to the resources (EC2 and RDS instances) you want to monitor for start/stop
  • A CloudWatch event that runs regularly runs the Lambda Function that will check the compliance with the schedule defined for each resource, and apply the necessary actions according to that schedule, whether to start or stop the resources
  • The scheduler also, will be able to apply user-defined tags when any action is taken over the resources

We launch all services through a CloudFormation template kindly provided by AWS. On this template we can configure the behavior we want from the scheduler, and also we can make changes to the parameters and schedules through ChangeSets (changes made to a previously created CloudFormation Stack, if you’re not familiar with the term). Finally we’re going to see how to use the scheduler-cli, through which we can make configuration changes among other things.

The Configuration

Launching the CloudFormation template

We’re doing all the configuration through the AWS Console just for graphic illustration, my preferred method of doing this is through the AWS CLI. This is an overview of what’s next:

  • Deploy the cloudformation template
  • Define instance scheduler parameters
  • Configure Schedules
  • Tag Instances
  • Check metrics and use scheduler-cli

First, take a look at the diagram of what we’re going to deploy:

Scheduler CloudFormation Template

We have two DynamoDB tables, one for configuration and one for storing instances state. Also, we have a policy to allow certain services to be used by the scheduler, as well as a role for the lambda function to assume; and of course, the lambda function that will do the heavy lifting and the CloudWatch configuration for triggering it.

Choose wisely a name

First the usual, type a name, but must importantly, choose a Tag name. This tag name will need to be present at the instances we want to control through our scheduler.

You can choose EC2, RDS or both to be controlled

Then the services we’re going to watch over…ahh! and if the scheduler should create an RDS snapshot before shutting down.

The heavy stuff

Aurora clusters, yes we can! but in this post: no we won't. Yes we will enable the schedule…and we must define which regions are going to be probed by the instance scheduler.

Specs and times

We have to indicate the frequency of our probes, also the memory footprint of our lambda function; because I’m still on the free tier, I chose 128Mb, in that manner my runtime will be free of charge (for the moment 😂). Then, there are some CloudWatch configuration parameters, such as, if we enable detailed information (red banner! this cost US$1 per schedule). Finally we set a couple of tags the scheduler will set on the instances that it starts/stops.

Tags tags tags!

Then we should tag our stack, because YOU SHOULD TAG EVERYTHING in AWS, that’s not optional, is good for your mental (and financial) health.

Review and check everything is in order

Then we check everything is OK and ACK that CloudFormation should allow certain capabilities for the resources to be created.

There’s always an user terms and conditions.

Then after 5–10 minutes we check everything is created, in our resources and outputs tabs.

Stack…done

Outputs…check.

Some redaction necessary for security purposes

We’re now ready to continue to configure the periods, schedules and see if everything works well.

Configuring Periods and Schedules

Now we have to configure the periods on which we’ll start and stop instances, these periods are associated with the schedules, that finally will be tagged to the instances we want.

For this configuration we are going to use the scheduler-cli, this because is the most straightforward way to do it, without tinkering with DynamoDB table (can mess things up), or creating a CloudFormation custom resource, that could be complex if you’re just starting with AWS.

First we need to install the scheduler-cli, this we do by downloading a zip file from here: https://s3.amazonaws.com/solutions-reference/aws-instance-scheduler/latest/scheduler-cli.zip, then we unzip it and run:

python setup.py install

Of course you’ll have to install Python3 before that. You can play a little with the command to see what options are:

scheduler-cli --help

Trying not to make this post any longer, than it already is; we are going to bypass the lots of options that the tool offers.

Configuring the period

We could configure a lot of periods, saying for instance, start all my instances on Mondays at 9am, and then on Friday night stop them all. For sake of time (mine), and because as the time of this post is Sunday, I’ll implement a period that starts all my RDS and EC2 at 3pm UTC-5 (Bogota time, I’m from Colombia! 🇨🇴) and that stops them at 6pm; but I’ll put an example command of a weekday start-weekend stop after that.

First, we specify the start period, don’t forget your CloudFormation Stack name!:

scheduler-cli create-period --stack MyInstanceSchedulerStack --name sun-start-3pm
--weekdays sun --begintime 15:00 --endtime 17:59 --profile your-profile
(and yes, you can specify the AWS CLI profile name for the scheduler-cli)

And finally, the schedule:

scheduler-cli create-schedule --stack MyInstanceSchedulerStack --name sun-3pm-6pm --periods sun-start-3pm --timezone America/Bogota --profile your-profile --region us-west-2

The name of this schedule is what we’ll need to put in our EC2 or RDS instances.

You have to add the tag name, and the value is the schedule name

After we add this tag and the schedule name as value, we just wait and see that our instances are started at 3pm:

The AWS Instance Scheduler appended the tag we configured to register the start or stop

And we can see the launch time in the EC2 console:

Sweet!

And after a couple of hours we see that our instances are stopped after 6pm:

Nice and tidy

So, what if you want the mon-fri typical schedule? Here it is!

scheduler-cli create-period --stack <stackname> --name mon-start-8am
--weekdays mon --begintime 8:00 --endtime 23:59
scheduler-cli create-period --stack <stackname> --name tue-thu-full- day --weekdays tue-thuscheduler-cli create-period --stack <stackname> --name fri-stop-6pm - -weekdays fri --begintime 0:00 --endtime 18:00scheduler-cli create-schedule --stack <stackname> --name mon-9am-fri- 5pm --periods mon-start-8am,tue-thu-full-day,fri-stop-6pm –timezone America/New_York

The bottom line

Instance Scheduler may seem a little overkill by the amount of configuration and resources needed to make it work, but it certainly will help to control your costs in AWS; and I think it worths the effort (and money), just to prevent a very expensive bill to arrive.

And of course, it’s just limited to two AWS services, maybe in the future will be more, who knows; but you could achieve a lot more of things with AWS Config (https://aws.amazon.com/config/), CloudCustodian (http://cloudcustodian.io/) and Terraform (https://www.terraform.io).

All your comments are welcome. If you like to connect with me here is my LinkedIn profile: LinkedIn

--

--

Carlos Andrés Herrera
Useless Nerd

DevOps Engineer. AWS Architect. This guy is a MSc from @CMU Heinz. Coffee and chocolate lover.