CLI & module for terminating instances that match tag and age requirements.
- Searches all (or specified) regions for instances.
- Matches instances against a tag pattern.
- Allows instances a grace period before termination.
- Can be used as a Python module, CLI application, or an AWS Lambda function
Ensure your user or instance profile has the following permissions prior to running:
- ec2:TerminateInstances
- ec2:DescribeInstances
- ec2:DescribeRegions
- ec2:DescribeTags
Matchers let you specify tag names, values to match (includes), and values to ignore (excludes). Wildcards can be used to either match all values (includes) or to match empty/non-existant tags (excludes).
This is the default tag matcher and it will match anything that lacks a Name tag:
[{"tag": "Name", "includes": [], "excludes": ["*"]}]To terminate any instance named "cirunner", the filter would look like so:
[{"tag": "Name", "includes": ["cirunner"], "excludes": []}]reap(tags=None, min_age=DEFAULT_MIN_AGE, regions=DEFAULT_REGIONS, debug=True)- tags: List of dicts like
{'tag': 'sometag', include=['val1', ...], exclude=['val2', ...]} - min_age: Instance must be (int)N seconds old before it will be considered for termination. Default: 300
- regions: Stringy AWS region name or list of names to search. Searches all available regions by default.
- debug: If True, perform dry-run by skipping terminate API calls. Default: True
Returns a list of dicts with instance that partially matches and their reap status.
eg: [{'id': i.id, 'tag_match': True, 'age_match': False, 'tags': i.tags, 'launch_time': i.launch_time, 'reaped': False, 'region': i.region}]
ec2-reaper [--min-age <seconds>] [--region region-1 --region region-2 ...] [--dry-run] <tag matcher>
- --dry-run will enable debug output and prevent the reaper from actually terminating anything.
- The Tag Matcher has to be specified as a quoted JSON string.
A stock handler is included with the module, so very little is needed to deploy it to AWS Lambda. Here's an example using the Serverless framework.
serverless.yml
service: ec2-reaper
frameworkVersion: ">=1.2.0 <2.0.0"
provider:
name: aws
runtime: python3.6
stage: prod
region: us-west-2
memorySize: 128
timeout: 300
environment:
# enable debug logging and live NO-OP testing. default: true
DEBUG: false
# instances will not be terminated unless they are MIN_AGE seconds old
# MIN_AGE: 300 # default: 300
# search *only* the specified regions. space separated string.
# REGIONS: 'us-east-1 us-west-2' # default: all regions
# specify tag names, values to match (includes), and values to ignore (excludes)
# wildcards can be used to either match all values (includes) or to
# match empty/non-existant tags (excludes).
# default: matches any instance that has an empty/non-existant Name tag.
# TAG_MATCHER: '[{"tag": "Name", "includes": [], "excludes": ["*"]}]'
# the function can report on instances terminated and instances which
# match tag-wise but are too young to Slack. it uses the webhook defaults, so
# be sure to configure it to your desired channel, bot name, etc.
# default: no slack endpoint, no notifications
SLACK_ENDPOINT: https://hooks.slack.com/services/M00...
iamRoleStatements:
# the function only needs a few specific permissions.
- Effect: Allow
Action:
- ec2:TerminateInstances
- ec2:DescribeInstances
- ec2:DescribeRegions
- ec2:DescribeTags
Resource: "*"
functions:
cron:
handler: handler.run
events:
# Invoke Lambda function every 15th minute from Mon-Fri
- schedule: cron(0/15 * ? * MON-FRI *)
plugins:
# takes care of bundling python requirements for us.
- serverless-python-requirementshandler.py
import ec2_reaper
def run(event, context):
return ec2_reaper.aws_lambda.handler(event, context)requirements.txt
ec2-reaper>=0.1.8
Deploy
sudo npm install -g serverless cd /path/to/lambda-reaper-repo serverless deploy
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.