[PYTHON] Achieve automatic shutdown of EC2 instances with Lambda + CloudWatch Events

I think there is a similar code if you google, but I keep it as a memorandum.

I've often seen code that uses AWS Instance Scheduler or sets a time for a tag and stops when Lambda runs regularly, but I also wanted to reduce the number of Lambda runs to maximize costs. Therefore, I assumed that the time was fixed.

Thing you want to do

I want to execute automatic stop of the instance set as below in the tag of EC2 instance at 21:00 on weekdays.

procedure

Creating an IAM role policy

Create an IAM role with this kind of policy


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:StopInstances",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

CloudWatch Events settings

I want to shut down automatically at 21:00 every night

cron(0 12 ? * MON-FRI *)

And set. Note that the time is UTC, so convert JST to UTC and set it.

Creating Lambda

Create Lambda by specifying the above IAM role / CloudWatch Events. The default execution time is 3 seconds, but it is not enough, so set it to about 1 minute. The runtime is Python 3.8.


import json

def lambda_handler(event, context):
    import boto3
    ec2 = boto3.client('ec2')

    #Get the target EC2 instance IDs
    instances = targetInstances(ec2,'auto-stop', 'true')
    if len(instances) != 0:
        print("--- stop instances ---")
        print(instances)
        #Stop
        ec2.stop_instances(InstanceIds=instances)

#Get the target EC2 instance IDs
def targetInstances(ec2, tag_name, tag_value):

    query = [
        {"Name": "instance-state-name", "Values": ["running"]},
        {'Name': 'tag-key', "Values": [tag_name]},
    ]
    fetch_instances = ec2.describe_instances(Filters=query)['Reservations']
    instances = []

    for i in fetch_instances:
        for tags in i['Instances'][0]['Tags']:
            if tag_name in tags['Key']:
                if tags['Value'] == tag_value:
                    instanceId = i['Instances'][0]["InstanceId"]
                    instances.append(i['Instances'][0]["InstanceId"])

    return(instances)

Summary

Let's save the instance fee by dropping EC2 instances for the development environment frequently.

If you also want to do automatic startup, add ʻec2: StartInstances` to the policy, create Cloudwatch Events with a new start time, create Lambda, and rewrite the above code for startup.

Recommended Posts

Achieve automatic shutdown of EC2 instances with Lambda + CloudWatch Events
Try automating Start / Stop for EC2 instances with AWS Lambda
Periodically start / stop Sakura's cloud server with AWS Lambda + CloudWatch Events
Prepare the environment of Chainer on EC2 spot instance with AWS Lambda
Make it easy to specify the time of AWS CloudWatch Events with CDK.