Last active
June 5, 2025 01:31
-
-
Save Pabl0Aceved0/3577b388fb253470d04b41f60b4e4b91 to your computer and use it in GitHub Desktop.
Below is a runbook for AWS Systems Manager Automation to terminate EC2 instances that have been stopped or unused for a specified duration. This runbook uses AWS Lambda to check the instance's stopped duration and terminates it if it exceeds a defined threshold (e.g., 7 days). The runbook is written in YAML, as is standard for AWS Systems Manage…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
description: Terminates EC2 instances stopped for more than a specified number of days. | |
schemaVersion: '0.3' | |
assumeRole: "{{ AutomationAssumeRole }}" | |
parameters: | |
AutomationAssumeRole: | |
type: String | |
description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf. | |
default: '' | |
MaxStoppedDays: | |
type: Integer | |
description: Number of days an instance can remain stopped before termination. | |
default: 7 | |
mainSteps: | |
- name: GetStoppedInstances | |
action: aws:executeAwsApi | |
inputs: | |
Service: ec2 | |
Api: DescribeInstances | |
Filters: | |
- Name: instance-state-name | |
Values: | |
- stopped | |
outputs: | |
- Name: InstanceIds | |
Selector: $.Reservations[*].Instances[*].InstanceId | |
Type: StringList | |
- name: CheckStoppedDuration | |
action: aws:executeScript | |
inputs: | |
Runtime: python3.8 | |
Handler: check_stopped_duration | |
Script: | | |
import boto3 | |
from datetime import datetime, timezone | |
def check_stopped_duration(event, context): | |
instance_ids = event['InstanceIds'] | |
max_stopped_days = int(event['MaxStoppedDays']) | |
ec2_client = boto3.client('ec2') | |
instances_to_terminate = [] | |
for instance_id in instance_ids: | |
response = ec2_client.describe_instance_attribute( | |
Attribute='disableApiStop', | |
InstanceId=instance_id | |
) | |
stop_time = ec2_client.describe_instances( | |
InstanceIds=[instance_id] | |
)['Reservations'][0]['Instances'][0].get('StateTransitionReason') | |
if stop_time: | |
stop_time_str = stop_time.split('(')[1].split(')')[0] | |
stop_time = datetime.fromtimestamp(int(stop_time_str.split()[0]), timezone.utc) | |
days_stopped = (datetime.now(timezone.utc) - stop_time).days | |
if days_stopped >= max_stopped_days: | |
instances_to_terminate.append(instance_id) | |
return {'InstancesToTerminate': instances_to_terminate} | |
InputPayload: | |
InstanceIds: "{{ GetStoppedInstances.InstanceIds }}" | |
MaxStoppedDays: "{{ MaxStoppedDays }}" | |
outputs: | |
- Name: InstancesToTerminate | |
Selector: $.Payload.InstancesToTerminate | |
Type: StringList | |
- name: TerminateInstances | |
action: aws:executeAwsApi | |
inputs: | |
Service: ec2 | |
Api: TerminateInstances | |
InstanceIds: "{{ CheckStoppedDuration.InstancesToTerminate }}" | |
isEnd: true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment