I want to reduce my Amazon Elastic Compute Cloud (Amazon EC2) usage by stopping and starting my EC2 instances automatically at certain times or utilization thresholds. How do I use AWS Lambda and Amazon CloudWatch Events to do that?

Note: This example setup is a simple solution. For a more robust solution, see AWS Instance Scheduler.

CloudWatch Events lets you create an event that's triggered at a specified time or interval in response to events that take place in your account. CloudWatch also lets you create an alarm for when CPU utilization for an instance reaches a specific threshold.

In this setup, you'll create Lambda functions that stop and start your EC2 instances. Then, you'll create events that trigger your functions at intervals or certain times that you specify. If you haven't done so already, launch one or more EC2 instances. Then, get the IDs of the instances you want to stop and start using this setup.

Note: Find your EC2 instances' IDs in the EC2 console from the Instance ID column. You can also use describe-instances in the AWS Command Line Interface, or Get-EC2Instance with AWS Tools for Windows PowerShell.

Create Lambda functions that stop and start your EC2 instances

1.    In the Lambda console, choose Create function.

2.    Choose Author from scratch.

3.    Under Author from scratch, do the following:
For Name, enter a name for your function, such as "StopEC2Instances".
For Runtime, choose Python2.7.
For Role, choose Create a custom role. A page in the AWS Identity and Access Management (IAM) console opens in a new browser tab or window.

4.    In the IAM console page, under Role Summary, do the following:
For IAM Role, choose Create a new IAM Role.
For Role Name, enter a name for the role, such as “lambda_stop_start_ec2."

5.    Choose View Policy Document, and then choose Edit.

6.    In the Edit Policy dialog, read the documentation as needed, and then choose Ok.

7.    Copy this policy and paste it into the policy editor, replacing the default policy:

{
  "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": "*"
    }
  ]
}

8.    Choose Allow to finish creating the custom role and return to the Lambda console.

9.    In the Lambda console, choose Create function.

10.    Copy this code, and then under Function code, paste it into the editor pane in the code editor (lambda_function). This code stops the EC2 instances you identify.

import boto3
region = 'us-west-1'
instances = ['i-12345cb6de4f78g9h', 'i-08ce9b2d7eccf6d26']

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

Note: For region, replace "us-west-1" with the AWS Region your instances are in. For instances, replace the example EC2 instance IDs with the IDs for one or more of your instances.

11.    Under Basic settings, set Timeout to 10 seconds.

12.    Choose Save.

13.    Repeat steps 1-12 to create another function. Do the following differently so that this function starts your EC2 instances:
In step 3, enter a Name that identifies the purpose of the function. For example, "StartEC2Instances."
In step 3, for Role, choose the same role you created previously.
In step 10, copy and paste this code into the editor pane in the code editor (lambda_function):

import boto3
region = 'us-west-1'
instances = ['i-12345cb6de4f78g9h', 'i-08ce9b2d7eccf6d26']

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

Note: For region and instances, use the same values that you used for the code to stop your EC2 instances.

Test your Lambda functions

1.    In the Lambda console, choose Functions.

2.    Select one of the functions you created.

3.    Choose Actions, and then choose Test.

4.    In the Configure test event dialog, choose Create new test event.

5.    Enter an Event name, and then choose Create.

Note: You don't need to change the JSON code for the test event—the function doesn't use it.

6.    Choose Test to execute the function.

7.    Repeat steps 1-6 for the other function you created.

Tip: You can check the status of your EC2 instances before and after testing to confirm that your functions work as expected.

Create a CloudWatch Events event that triggers a Lambda function

1.    Open the CloudWatch console.

2.    In the left navigation pane, under Events, choose Rules.

3.    Choose Create rule.

4.    Under Event Source, choose Schedule.

5.    Do either of the following:
For Fixed rate of, enter an interval of time in minutes, hours, or days.
For Cron expression, enter an expression that tells Lambda when to stop your instances. For information on the syntax of expressions, see Schedule Expressions for Rules.
Note: Cron expressions are evaluated in UTC. Be sure to adjust the expression for your preferred time zone.

6.    Under Targets, choose Add target.

7.    Choose Lambda function.

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

9.    Choose Configure details.

10.   Under Rule definition, do the following:
For Name, enter a name to identify the event, such as "StopEC2Instances".
(Optional) For Description, describe your event. For example, "Stops EC2 instances every night at 10 PM."
For State, select the Enabled check box.

11.   Choose Create rule.

Tip: Create one event that stops your EC2 instances at night, and another event that starts them again in the morning.


Did this page help you? Yes | No

Back to the AWS Support Knowledge Center

Need help? Visit the AWS Support Center.

Published: 2016-07-07

Updated: 2019-02-28