How to auto stop and auto start AWS EC2 instances at regular intervals using AWS Lambda.

Amazon Web Services

Note: This is cheapest and easiest solution. For a more robust solution, see AWS Instance Scheduler.

In this setup, you’ll create Lambda functions that stop and start your EC2 instances. This function will use Instance tags to identify which instances needs to be start and stop at intervals or certain times that you specify.   Then, you’ll create CloudWatch events that trigger your functions at intervals or certain times that you specify.

Note: Tag all the instance which needs to be auto stop and auto start. Here in this article I have used this tagging’s.

Region = ap-south-1 (Mumbai)

Name = AutoStart ; Value = True (To start the instances)

Name = AutoStop ; Value = True (To stop the instances)

Step 1 – Create IAM role for lambda

First step is to create a IAM role for the lambda function so that it can perform certain actions like start & stop of EC2 instance and some other additional roles.

1.    In AWS console click on Services and Then IAM.

2.    Click on Roles in left side navigation panel.

3.    Click on create role.

4.    Select lambda from the list of AWS Service.

5.    Click Next:Permission

6. Now click on create policy, a new window will open. (Here we need to create a new custom policy for the new role, in this policy we will define what all the access is needed to run our lambda).

7.    Click on JSON tab. Remove default code and add below json data.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "ec2:DescribeInstances",
                "ec2:DescribeTags",
                "logs:CreateLogGroup",
                "logs:PutLogEvents",
                "ec2:DescribeInstanceStatus"
            ],
            "Resource": "*"
        }
    ]
}

8.  Click on Review Policy and enter policy name as lambda_stop_start_ec2_policy and description of the policy and then click on create policy.

9.    New policy with name lambda_stop_start_ec2_policy has been created now.

10.  Now comeback to the previous tab where we was creating roles.

11.  Here search and select the new policy which we just created
lambda_stop_start_ec2_policy . (click on Refresh button available on top right first).

12.  Click Next:tags and then Next:review. Now on review page enter Role name as lambda_stop_start_ec2 And some description of the role.

13.  Now click on Create role.

14.  New role has been created with EC2 start and stop permission with some additional CloudWatch logs permission.

Step 2 – Lambda to stop EC2 Instance

1.    Click on services then lambda.

2.    Click on Create function. Then Select Author from scratch.

3. Under Basic information tab enter Function Name as AutoStopEC2Instance and select runtime as Python 3.7.

4.    Click on Choose or create an execution role to expand.

5.    Under Execution role select Use an Existing Role and select the role lambda_stop_start_ec2 which we have created in previous step and click on Create function.

6.    Lambda Designer will open scroll down where you can find Function Code.

7.    Under Function code you will find an inline editor with lambda_function.py. Delete the content of the file and paste below code.

Note: For region, replace “ap-south-1” with the AWS Region your instances are in.

import boto3
import logging

#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#define the connection and set the region
ec2 = boto3.resource('ec2', region_name='ap-south-1')

def lambda_handler(event, context):

    # all running EC2 instances.
    filters = [{
            'Name': 'tag:AutoStop',
            'Values': ['True']
        },
        {
            'Name': 'instance-state-name', 
            'Values': ['running']
        }
    ]
    
    #filter the instances which are stopped
    instances = ec2.instances.filter(Filters=filters)

    #locate all running instances
    RunningInstances = [instance.id for instance in instances]
    
    #print the instances for logging purposes
    #print RunningInstances 
    
    if len(RunningInstances) > 0:
        #perform the shutdown
        shuttingDown = ec2.instances.filter(InstanceIds=RunningInstances).stop()
        print(shuttingDown)
    else:
        print("Nothing to see here")

8. Scroll Down to Basic settings and enter 30 Seconds in Time out. Rest leave it to the default and click on save top right corner.  

Testing Lambda

9.    Now scroll to the top of the page and click on Test button (Top right corner)

10.  First time it will ask you to configure test event.  Select Create new test event and Event template as Hello World & Event Name as anything you prefer i.e. TestEC2Stop and click on Create. It will create the test event.

11.  Now select the test event and click on Test. You will get the output as (Execution result: succeeded(logs)) means your lambda function is working. You can now check the ec2 console where you can see the tagged instance has stopped.

Step 3 – Lambda to Start Instance

Repeat the steps mentioned in Step 2

1.    Click on services then lambda.

2.    Click on Create function. Then Select Author from scratch.

3.    Under Basic information tab enter Function Name as AutoStartEC2Instance and select runtime as Python 2.7.

4.    Click on Choose or create an execution role to expand.

5.    Under Execution role select Use an Existing Role and select the role lambda_stop_start_ec2 which we have created in previous step and click on create function.

6.    Lambda Designer will open and below that you can find Function Code.

7.    Under Function code you will find an inline editor with lambda_function.py. Delete the content of the file and paste below code.

Note: For region, replace “ap-south-1” with the AWS Region your instances are in.

import boto3
import logging

#setup simple logging for INFO
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#define the connection
ec2 = boto3.resource('ec2', region_name='ap-south-1')

def lambda_handler(event, context):

    # all stopped EC2 instances.
    filters = [{
            'Name': 'tag:AutoStart',
            'Values': ['True']
        },
        {
            'Name': 'instance-state-name', 
            'Values': ['stopped']
        }
    ]
    
    #filter the instances
    instances = ec2.instances.filter(Filters=filters)

    #locate all stopped instances
    RunningInstances = [instance.id for instance in instances]
    

    #print StoppedInstances 
       
    if len(RunningInstances) > 0:
        #perform the startup
        AutoStarting = ec2.instances.filter(InstanceIds=RunningInstances).start()
        print(AutoStarting)
    else:
        print("Nothing to see here")

8. Scroll Down to Basic settings and enter 30 Seconds in Time out. Rest leave it to the default and click on save top right corner.

Testing Lambda

9.    Now scroll to the top of the page and click on test button (Top right corner)

10.  First time it will ask you to configure test event.  Select Create new test event and Event template as Hello World & Event Name as anything you prefer i.e. TestEC2Start and click on Create. It will create the test event.

11.  Now select the test event and click on test. If you Got the (Execution result: succeeded(logs)) means your lambda function is working. You check the ec2 console you can see the tagged instance has stopped.

Step 4 – Scheduling auto start and auto stop using CloudWatch events.

Method 1

1.    Come back to the lambda functions AutoStopEC2Instance which we have just created and tested.

2.    On the lambda Designer tab click on cloudwatch events from left pane. Cloudwatch event will get added under lambda function.

3.    Click on the cloudwatch event which shows as configuration required. Scroll down to configure triggers.

4.    Under rule select create a new rule.

5.   Mention rule name as AutoStopEC2Instance and description of the same.

6.  Select rule type Schedule Expression and mention — cron(0 21 ? * * *) – Everday at 9:00 PM UTC. Learn more about AWS Schedule expression

7.    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.

8.    Enable Trigger will be already checked as default, If not enable it by check in.

9.    Click on add It will show you as new trigger 1 -unsaved changes.

10.  Click Save on top right corner to save the changes.

11.  Repeat the steps 1 to 5 for another lambda function AutoStopEC2Instance.

12.  Select rule type Schedule Expression and mention — cron(0 9 ? * MON-FRI * *) – Everday at 9:00 AM UTC except Saturday & Sunday. Learn more about AWS Schedule expression

Repeat the same from 1-12 for AutoStartEC2Instance lambda function.

Method 2

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.

Leave a comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.