Stop EC2 instances whenever you need, through AWS CloudFormation!
In this article, I have articulated how we can STOP EC2 instances as and when we need. There may be times when we actually don't need EC2 instances running but terminating them may result in loosing the instance completely. So many prefer to stop the instances instead and automating this to schedule daily at specific time periods like weekends or after work hours would be a real cost optimizing step.
Pre-cursor
Before we look into the cloudformation script directly, lets look how we will be stopping the instances using CFN. When we actually look into the steps involved in stopping EC2 using CFN, some of you may think that stopping instances manually instead would be simple (like just clicking a button). But we need someone to always manually stop the instances at odd times and here comes the benefit of automating it.
What the script does?
Stopping EC2 instances using cloudformation involves the following steps. The cloudformation script would do all the below mentioned steps.
Creating a role for lambda and attach a policy with permission to stop the EC2 instances.
Creating a lambda event handler to execute a script (Python script in our example) for stopping EC2 instances.
Create a script to stop EC2 instances by runing the lambda event handler at the specific time and specific days.
Here, the specific time and days are provided in the form of a CRON expression. So one need to clearly understand the CRON expression before running the CFN script.
This script has been taken from AWS documentation but I have modified and separated the scripts for STOP and START actions.
Understanding CRON Expression


For more information on CRON expression, please follow the amazon documentation link.
Cloud formation script to STOP (or schedule to stop) instances whenever we need.
AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda function with cfn-response.
Parameters:
instances:
Default: i-0c33ad649583812e1
Description: Instance ID's separated by commas
Type: String
Region:
Default: ap-southeast-1
Description: region only 1 region supported
Type: String
StopScheduled:
Default: cron(0 18 ? * MON-SUN *)
Description: enter an Schedule expression example cron(0 18 ? * MON-FRI *) see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
Type: String
Resources:
StopEC2Instances:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.8
Role: !GetAtt Role.Arn
Handler: index.lambda_handler
Timeout: 60
Environment:
Variables:
instances: !Ref instances
Region: !Ref Region
Code:
ZipFile: |
import json
import re
import os
import boto3
def lambda_handler(event, context):
# TODO implement
instances_str = os.environ['instances']
region = os.environ['Region']
ec2 = boto3.client('ec2', region_name=region)
instances= re.findall(r"i-[0-9a-z]{17}|i-[0-9a-z]{8}", instances_str)
print('stopped your instances: ' + str(instances) + "in Region "+ region)
ec2.stop_instances(InstanceIds=instances)
return {
'statusCode': 200,
'body': json.dumps('stopped your instances: ' + str(instances))
}
Description: Function that stops instances
permissionForEventsToInvokeStopEC2Instances:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt StopEC2Instances.Arn
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
"SourceArn" : !GetAtt StopScheduledRule.Arn
Role:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Policies:
- PolicyName: Ec2permissions
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "ec2:StopInstances"
Resource: '*'
StopScheduledRule:
Type: AWS::Events::Rule
Properties:
Description: "ScheduledRule"
ScheduleExpression: !Ref StopScheduled
State: "ENABLED"
Targets:
-
Arn: !GetAtt StopEC2Instances.Arn
Id: "TargetFunctionV1"
Formatted Script



How to execute the script?
To execute the STOP script you must ensure that you have one or more EC2 instances running.

Enter the instance(s) Id in the cloud formation in the instances field under parameters section.
Enter the appropriate region of your EC2 instance(s)
Enter the hours, minutes and the days in the CRON expression either in the script or in the CRON field while uploading
Upload the script in CloudFormation on clicking Create Stack

5. click on Next, provide a name to the stack and enter the time to stop the EC2 instance in the StopScheduled field.

6. Click on the acknowledgement for creating a role and create the stack. The stack runs successfully.

7. Once the script has been successfully run, check the status of the instance under EC2

8. Also, check for the lambda function being created in the Lambda section.

TIP:
If you do not want to stop or schedule everyday and want to stop instances at an adhoc basis, you could just go ahead run the stack by providing the hours and minutes on the CRON expression and then delete the stack when instance is stopped.
I hope the above article will be useful for many AWS users who want to stop the EC2 instances instead of terminating, on need basis. My next article will be obviously on how to START stopped EC2 instances with a similar script.
If you find this article helpful, kindly share this with your known groups and also provide your valuable comments here. Thank you.