For on-demand EC2's that are not required during certain hours that are essentially wasting money running when not in use it is worth setting up a Lambda function that can stop and start the EC2's as per your requirements. This guide configures an IAM policy/role then uses a Lambda function to start/stop the EC2 during the business hours of 9am to 5pm.

Configure IAM

Within AWS Management Console navigate to IAM > Policies > Create Policy

Create a new policy, select the JSON tab and paste the following JSON code (This can be locked down to specific EC2's further if required)

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

Select review policy and give it a name (i.e. EC2_Start_Stop_Using_Lambda) and description then select Create policy


Go to Roles and create role, select AWS service, Lambda then click Next: Permissions

On the next page select the policy created earlier (EC2_Start_Stop_Using_Lambda) then add any tags that are required

Select review, give it a name (i.e. EC2_Start_Stop_Using_Lambda_IAM_Role), description and create the role

Lambda - Start Function

Within AWS Managament, go to Lambda and Create a new function

Give it a name Lambda_Start_EC2s_On_Schedule

Set runtime as Python 2.7

In the role select "Choose an existing role" and set it to the role created earlier (EC2_Start_Stop_Using_Lambda_IAM_Role)

In the Handler field leave the default

In the lambda_function.py environment window paste the following code replacing <instance id> with your instance id's and set your region

import boto3
# Enter the region your instances are in e.g., 'eu-west-1'
region = 'eu-west-1'
# Enter your instance IDs here
instances = ['<instance id 1>', '<instance id 2>', '<instance id 3>']

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

Increase the timeout to 10 seconds and leave the rest as default then save

Click Test and create a new test event, add a name the body can be left blank or as default as it is not required. Test to ensure the EC2 starts.

After running this the instance ID specified should now have started, if it hasn't check the Lambda logs and JSON permissions

Lambda - Stop Function

Create a new function

Give it a name Lambda_Stop_EC2s_On_Schedule

Set runtime as Python 2.7

In the role select "Choose an existing role" and set it to the role created earlier (EC2_Start_Stop_Using_Lambda_IAM_Role)

In the Handler field leave the default

In the lambda_function.py environment window paste the following code replacing <instance id> with your instance id's and set your region

import boto3
# Enter the region your instances are in e.g., 'eu-west-1'
region = 'eu-west-1'
# Enter your instance IDs here
instances = ['<instance id 1>', '<instance id 2>', '<instance id 3>']

def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.stop_instances(InstanceIds=instances)
    print 'The following instances are now stopping: ' + str(instances)

Increase the timeout to 10 seconds and leave the rest as default then save

Click Test and create a new test event, add a name the body can be left blank or as default as it is not required. Test to ensure the EC2 stops.

After running this the instance ID specified should now be in the process of stopping or has already stopped, if it hasn't check the Lambda logs and JSON permissions

At this point both Lambda scripts should be working and stop/start the specified EC2's, the next step is to automate the stopping and starting of EC2's as per your requirements using Cloudwatch

Cloudwatch

Navigate to Cloudwatch within the AWS Console.

Go to Events > Rules on the left hand pane then Create Rule

Select Schedule under Event Source then select cron expression then add the following for 5pm each evening;

0 17 * * ? *

For a full list of scheduled expressions see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html#CronExpressions

Select Add Target under Targets and select the stop Lambda function created earlier

Add a logical name and description then Save

Repeat this section to create a new start rule adjusting the cron expression with your start time and setting the Lambda function to the start function, i.e.

Add a logical name and description then Save

Your EC2's should now be setup to stop and start at the times you have specified in the cron expression, monitor this to prove it works and ensure no unnecessary on-demand EC2 costs are incurred.