top of page

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.

  1. Creating a role for lambda and attach a policy with permission to stop the EC2 instances.

  2. Creating a lambda event handler to execute a script (Python script in our example) for stopping EC2 instances.

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


  1. Enter the instance(s) Id in the cloud formation in the instances field under parameters section.

  2. Enter the appropriate region of your EC2 instance(s)

  3. Enter the hours, minutes and the days in the CRON expression either in the script or in the CRON field while uploading

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

 


680 views0 comments
bottom of page