Use AWS Lambda to schedule instance starts/stops and save some money!

By | 2017-09-30

I’m currently running a PoC and I only want the systems available to play with Monday – Friday, 9am to 5pm EST.  In order to save a good bit of money I’ve decided to turn off the instances at night.  I’m also super lazy, so I don’t want to have to log into the servers and manually turn them on/off everyday 🙂  So let’s create some lambda functions to do it for us!

For this to be successful, there are 2 steps involved:

  1.  Create 2 lambda functions, 1 to stop them every night and 1 to start them every morning.
  2.  Create 2 CloudWatch events to trigger the lambda functions at the appropriate times

So let’s get started!

(note:  the following steps are pulled from the AWS docs, but some steps were unclear, so I’ve added screenshots & additional verbiage where necessary, make sure your indentation on python and JSON code bits are accurate where necessary!)

1.    Open the AWS Lambda console and choose Create function:

 

2.    Choose Author from scratch from the available blueprints:

3.    In Configure triggers, just click Next:

4.    Enter the following information to configure your Lambda function:
Enter a Name, such as “StopEC2Instances”.
Enter the Description, such as “stops EC2 instances every day at night”.
Chooose Python 2.7 as your Runtime.

5.    To stop your instances, run a command similar to the following:

import boto3
# Enter the region your instances are in. Include only the region without specifying Availability Zone; e.g., ‘us-east-1’
region = ‘XX-XXXXX-X’
# Enter your instances here: ex. [‘X-XXXXXXXX’, ‘X-XXXXXXXX’]
instances = [‘X-XXXXXXXX’]

def lambda_handler(event, context):
    ec2 = boto3.client(‘ec2’, region_name=region)
    ec2.stop_instances(InstanceIds=instances)
    print ‘stopped your instances: ‘ + str(instances)

6.    Expand the Role drop-down menu and choose Create a custom role. This should open a new tab or window in your browser.

7.    Enter the following information to create a role for Lambda to use:
Under IAM Role, choose Create a new IAM Role.
For Role Name, enter “lambda_start_stop_ec2” or another name that’s meaningful to you.

8.    Choose View Policy DocumentEdit, and then edit the policy as follows:

{
“Version”: “2012-10-17”,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [
“logs:CreateLogGroup”,
“logs:CreateLogStream”,
“logs:PutLogEvents”
],
“Resource”: “arn:aws:logs:*:*:*”
},
{
“Effect”: “Allow”,
“Action”: [
“ec2:Start*”,
“ec2:Stop*”
],
“Resource”: “*”
}
]
}

9.    Choose Allow:

10.   From Advanced settings, input 10 seconds for the function timeout.

11.   Choose Next to review your function configuration, and then choose Create function.

12.   Repeat steps 1-4 and 9 to create another function that starts your instances again, using code similar to the following:

import boto3
# Enter the region your instances are in. Include only the region without specifying Availability Zone; e.g.; ‘us-east-1’
region = ‘XX-XXXXX-X’
# Enter your instances here: ex. [‘X-XXXXXXXX’, ‘X-XXXXXXXX’]
instances = [‘X-XXXXXXXX’]

def lambda_handler(event, context):
    ec2 = boto3.client(‘ec2’, region_name=region)
    ec2.start_instances(InstanceIds=instances)
    print ‘started your instances: ‘ + str(instances)

When you are done with this first part, you will have 2 new lambda functions to play with:

 

You can test them by clicking on the function and then clicking “save and test” – confirm that they do indeed stop then restart the correct instances before proceeding to the next steps, automating the process via CloudWatch:

Create a CloudWatch event that triggers your Lambda function at 5 pm EST

1.    Open the CloudWatch console.

2.    Choose Events, and then choose Create rule:

3.    Select Schedule under Event Selector.

4.    Enter an interval of time or cron expression that tells Lambda when to stop your instances; for more information on the correct syntax, see Schedule Expression Syntax for Rules.
Note #1: Cron expressions are evaluated in UTC. Make sure to adjust for your preferred time zone.

Note #2: AWS Cron expressions don’t use the YEAR variable, so only 6 fields instead of 7… this took me a bit to suss out :-/

5.    Choose Add target.

6.    Under Targets, choose Lambda function.

7.    For Function, choose the Lambda function that stops your instances.

8.    Choose Configure details.

9.    Enter the following information in the provided fields:
For Name, enter “StopEC2Instances”, or another name that’s meaningful to you.
For Description, add a meaningful description; for example, “stops EC2 instances every weekday night @ 5pm EST”.
For State, check Enabled.

10.   Choose Create rule.

To restart your instances in the morning, repeat these steps using your preferred time.

When you are finished, you will have 2 new CloudWatch rules:

To add/remove instances from your on/off cycle, simply go back into your both of your Lambda functions and add/remove them from the instances list (note that it’s in string format!):

 

 

Category: AWS

Leave a Reply

Your email address will not be published. Required fields are marked *