DEV Community

loading...
Cover image for Simple EC2 Stopinator in Lambda
AWS

Simple EC2 Stopinator in Lambda

John Rotenstein
Technical Evangelist at AWS
・4 min read

A Stopinator is the general term applied to a utility that can start/stop Amazon EC2 instances on a particular schedule or in particular circumstances.

There are quite a few Stopinators available, such as the Instance Scheduler from AWS. However these Stopinators tend to be quite complex, involving CloudFormation templates and databases.

Therefore, I set myself a challenge to create a Simple Lambda Stopinator to help people in situations such as this StackOverflow question asking how to send a notification when an EC2 instance is still running and then eventually terminate it after a given period. How simple? Just paste some code into a Lambda function and you're done!

I have, in fact, written two stopinators:

  • Type 1: Run this Lambda function once per night to stop/terminate tagged Amazon EC2 instances
  • Type 2: Run this Lambda function throughout the day to notify/stop/terminate instances after a given period of time

You can find them in: GitHub: Simple Lambda Stopinators

(I hope to also write another Stopinator with start/stop scheduling, but that gets a bit more complicated with weekdays/weekends and timezones.)

Here's an explanation of the Stopinators and how to use them.


Type 1 Stopinator: Stop/Terminate instances at night

I originally wrote this Stopinator when I was delivering AWS training courses. I would launch Amazon EC2 instances for demonstrations during the day and would often forget to terminate them. So, I wanted a script that could identify instances tagged as 'temporary' and terminate them at night, so things were clean for teaching the next day.

However, I didn't always remember to tag the temporary instances, so I also added functionality that would stop unidentified instances at night rather than terminating them (just in case I still needed them). This then also required the ability to mark instances that the Stopinator should 'ignore' because I wanted them to keep running.

This is how the Type 1 Stopinator works:

  • The Lambda function should be scheduled to run each night (eg 7pm) using Amazon CloudWatch Events
  • It looks at every running instance in every region (or just the regions you specify)
  • If the instance has an Auto-Stop = Terminate tag, it terminates the instance
  • If the instance has an Auto-Stop = Ignore tag, it does nothing
  • Otherwise, it stops the instance

That's it — simple, eh‽ (Yes, that's an interrobang.)

To install it:

  • Create an IAM Role and add an in-line policy with permissions from the Stopinator IAM Role
  • Create a new AWS Lambda Python function that uses the IAM Role
  • Paste in the Type 1 Stopinator code
  • Go to Amazon CloudWatch, click Events and add a Scedule with a cron expression that triggers the Lambda function each night. Be careful — AWS uses the UTC timezone, so you'll need to adjust for your particular timezone.

By default, it will automatically stop any untagged instances. If you want to terminate instances instead of stopping them, add an Auto-Stop = Terminate tag (that is, Key = Auto-Stop, Value = Terminate). If there are instances you don't want it to touch, use Auto-Stop = Ignore.

You can also edit this section to control which regions are checked:

# Provide regions here (eg ['us-west-2', 'ap-southeast-2'], or use [] for all regions
regions_to_check = []

That's it. So simple! Enjoy.


Type 2 Stopinator: Stop/Terminate/Notify instances after a given duration

This Stopinator was inspired by a StackOverflow question that was asking for a way to send notifications about a running instance, and then eventually turn it off.

This AWS Lambda function needs to be scheduled to run at regular intervals, so that it continually checks whether instances have exceeded their duration. The more often it runs, the closer it will match the desired running duration.

This is how the Type 2 Stopinator works:

  • The Lambda function should be scheduled to run throughout the day (eg every 5 minutes) using Amazon CloudWatch Events
  • It looks at every running instance in every region (or just the regions you specify) and checks for one of these tags (in this order):
    • Terminate-After
    • Stop-After
    • Notify-After (or any tag that starts with Notify-After, such as Notify-After1, Notify-After2, etc)
  • It checks the duration supplied in the tag value (eg 30m, 1.5h, 24h)
  • If the instance has been running longer than the given duration, it will terminate/stop the instance or send a notification to an Amazon SNS topic.

To install it:

  • Create an IAM Role and add an in-line policy with permissions from the Stopinator IAM Role
  • Create a new AWS Lambda Python function that uses the IAM Role
  • Paste in the Type 2 Stopinator code
  • Go to Amazon CloudWatch, click Events and add a Schedule at a "Fixed rate of 5 minutes" (or whatever frequency you wish) that triggers the Lambda function
  • Optional: Create an Amazon SNS topic and insert the ARN in this line at the top of the Lambda function:
# To send a notification, insert SNS Topic ARN here
SNS_TOPIC_ARN = ''
  • Then, subscribe to the Amazon SNS topic to receive notifications

To remember whether a notification has been sent, the Stopinator will remove the Notify-After tag once it has been used. This allows multiple notifications to be tracked by supplying multiple tags that start with Notify-After in the tag key.

You can also edit this section to control which regions are checked:

# Provide regions here (eg ['us-west-2', 'ap-southeast-2'], or use [] for all regions
regions_to_check = []

If you find any problems with the Stopinators, feel free to add an issue to the GitHub repository.

If they have been useful for you, feel free to add a comment below. Enjoy!

Discussion (2)

Collapse
rosswilliams profile image
rosswilliams

I’d scope down the IAM role in Type 1. Adding a condition to only allow termination of instances with certain tags makes this a lot safer.

Collapse
aws_john profile image
John Rotenstein Author

Yes, that's an interesting idea. Effectively it's limiting the Lambda function to only do what it's meant to do, so the role can't be used to stop/terminate other instances. Of course, this then needs limitations on who can edit Tags.

I'll admit I was lazy — I made one IAM Role that would work with both Stopinators, but it should be scoped-down to be safer.