AWS Lambda Function to Stop and Start EC2 Instances

 
 

AWS Lambda Function to Stop and Start EC2 Instances based on Tags is our next tutorial where we will guide you, step by step, how to save money on AWS monthly bill just by using a simple AWS Lambda Function backed up by a Python script. Nowadays most of the modern companies relies on many cloud technologies from various cloud providers like AWS for pretty much any environments and tiers that we can think of like production, QA, staging, development and so on but everything comes at a price. We can reduce our monthly AWS bill and also, indirectly, becoming a greener business by simply scheduling our EC2 instances state designed for development or staging environments for example to only be available to our development or testing teams during weekdays between specific hours. Having some of these tiers powered on during business hours and powered off out of business hours make perfect sense, cost-wise and also taking our project / business one step closer in becoming environmentally friendly.

Table of Contents

AWS IAM Policy
AWS IAM Role
AWS Lambda Function to Stop and Start EC2 Instances
AWS CloudWatch
AWS EC2 Tags

AWS IAM Policy

On our first step with this tutorial we have to create a custom IAM Policy called autoStartStopSchedulerPolicy where we will allow only three major actions like ec2:Describe*, ec2:StartInstances and ec2:StopInstances, these three are the most important actions from our policy, logs:* action is optional but good to have. Within Identity and Access Management we will create a new custom IAM Policy named autoStartStopSchedulerPolicy and we will use the next JSON formatted lines to it:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:*",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2:Describe*",
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*"
        }
    ]
}

AWS IAM Role

On the second step of our tutorial we have to create a new IAM Role called for example autoStartStopSchedulerRole, this new role will make use of our previously created policy autoStartStopSchedulerPolicy as its main policy.

From AWS Web Console we have to navigate once again to IAM service and create a new role by selecting AWS Service and also Lambda options. Once these two main options were selected then we can move to Permissions section where we will attach our existing autoStartStopSchedulerPolicy custom policy. As we said before, we have save our new role under the name autoStartStopSchedulerRole, is not a must but nice to have naming consistency. By using consistent names for all IAM related services – and all other services – we will make things easy, this will help us in the future to easily identify and manage for example the role that we have just created.

AWS Lambda Function to Stop and Start EC2 Instances

In this particular step we will configure our AWS Lambda Function to Stop and Start EC2 Instances. Once the IAM Policy and IAM Role are bounded then we can start working on our new Lambda function, this function plays the most important role in our exercise.

So let’s browse now to Lambda service from AWS Web Console and create a new function, first thing to do is to specify its Type, here we have to select Author from scratch. Next we will be asked to provide a name for our new Lambda Function, we will be calling our function autoStartStopSchedulerFunction as for the Runtime environment we will be using Python 3.6. This solution may very well work with newer versions but it has been tested using Python 3.6.

We are very close to finish with this step but before that we have to set the permissions for our Lambda Function. For this we need click and expand Choose or create an execution role option and select Use an existing role radio button. Once the option has been selected we will choose from the drop-down menu our IAM role, in our case autoStartStopSchedulerRole.

Quick summary of our Lambda Function steps:

- Type: Author from scratch
- Name: autoStartStopSchedulerFunction
- Runtime: Pyhton 3.6
- Permissions > Use an existing Role: autoStartStopScheduleRole

If all above actions were completed then we can safely click on Create Function button which will led us to our newly created Lambda Function configuration page.

Here, using Function Code editor we have to insert the next Python code for our function:

import boto3
import time

# Defining boto3 the connection
ec2 = boto3.resource('ec2')

def timeInRange(startRange, endRange, currentRange):
    if startRange <= endRange:
        return startRange <= currentRange <= endRange
    else:
        return startRange <= currentRange or currentRange <= endRange

def lambda_handler(event, context):
    
    currentTime = time.strftime("%H:%M")

    filters = [{
            'Name': 'tag:autoSchedulerEnabled',
            'Values': ['True']
        }
    ]

    instances = ec2.instances.filter(Filters=filters)

    stopInstancesList = []
    startInstancesList = []

    for instance in instances:
            
        for tag in instance.tags:

            if tag['Key'] == 'autoStopSchedule':

                stopTime = tag['Value']
                pass

            if tag['Key'] == 'autoStartSchedule':

                startTime = tag['Value']
                pass

            pass

        instanceState = instance.state['Name']

        if timeInRange(startRange=startTime, endRange=stopTime, currentRange=currentTime):

            if (instanceState == "running") or (instanceState == "pending"):
                print("[", currentTime, "]", "Instance", instance.id, "already running, it won't be added to START list")
            else:
                startInstancesList.append(instance.id)
                print("[", currentTime, "]", "Instance", instance.id, "has been added to START list")
                
                pass

        elif timeInRange(startRange=startTime, endRange=stopTime, currentRange=currentTime) == False:

            if (instanceState == "stopped") or (instanceState == "stopping"):
                print("[", currentTime, "]", "Instance", instance.id, "already stopped, it won't be added to STOP list")
            else:
                stopInstancesList.append(instance.id)
                print("[", currentTime, "]", "Instance", instance.id, "has been added to STOP list")
                
                pass

        pass

    if len(stopInstancesList) > 0:
        stop = ec2.instances.filter(InstanceIds=stopInstancesList).stop()
        print(stop)
    else:
        print("[", currentTime, "]", "No instances to stop in the list")

    if len(startInstancesList) > 0:
        start = ec2.instances.filter(InstanceIds=startInstancesList).start()
        print(start)
    else:
        print("[", currentTime, "]", "No instances to start in the list")

The above code uses Boto3 library needed for interaction with AWS API. We won’t explain line by line how the code works but in simple terms our Function searches for some specific tags – we will talk about this shortly – all EC2 instances from the Region where the Lambda Function has been created. If tags were found then according to our Role and Policy we can turn them on or off based on a schedule that will be also defined via Tags.

AWS CloudWatch

AWS CloudWatch plays also a very important role in our exercise, this will execute our Lambda Function based on a Schedule. From AWS Web Console let’s go to CloudWatch service and select from the left-hand side Events > Rules option.

We will be creating a new rule using Create Rule button, on the next page we have to select Schedule radio button and also Cron expression. In the Cron expression field we will use the next line:

0/10 * ? * MON-FRI *

The above line basically says that a cron job will be triggered every 10 minutes, Monday to Friday. You can adjust this for your specific case.

On the Targets panel after clicking Add target button we will chose Lambda function from the drop-down menu and then from the Function drop-down menu we will select autoStartStopSchedulerFunction.

Next step is to click on Configure details button where we have to name our CloudWatch Event, once again for consistency we will name this autoStartStopSchedulerCWEvent as well.

Recap for our CloudWatch steps:

- Events > Schedule 
- Cron Expression: 0/10 * ? * MON-FRI *
- Lambda Function: autoStartStopSchedulerFunction
- [ Configure details ]
- Name: autoStartStopSchedulerCWEvent

We are now done, all that’s let is to configure our EC2 instances.

AWS EC2 Tags

Having everything in place now we can start configuring our EC2 instances being Development, Staging or Production. All we have to do is just to place three tags across all EC2 instances like autoSchedulerEnabled, autoStartSchedule and autoStopSchedule.

Example:

autoSchedulerEnabled 	True
autoStartSchedule 	08:29
autoStopSchedule	18:29

That is all, we are now done and we can proudly say that our short tutorial about AWS Lambda Function to Stop and Start EC2 Instances ends here.

Video

No video posted for this page.

Screenshots

No screenshots posted for this page.

Source code

No code posted for this page.

About this page

Article
AWS Lambda Function to Stop and Start EC2 Instances
Author
Category
Published
21/08/2019
Updated
24/09/2019
Tags

Share this page

If you found this page useful please share it with your friends or colleagues.