[PYTHON] Create a bot with AWS Lambda that automatically starts / stops Instances with specific tags

Magic words, cost savings

--When using EC2 for the development environment, it is easy to forget to Shutdown the Instance when returning home. ――It seems that there is a saying, "If dust accumulates, it becomes a mountain." ――Maybe everywhere is doing the same thing, EC2 Instance automatic stop bot-kun is made with Lambda. (In a company with a lot of overtime, when everyone forgets their existence, they mercilessly release the tragic Shutdown and tend to be relatively disliked) --A Chance to kill Instances that just run cron every day with ScheduleEvent attached to Lambda.

References of ancestors, etc.

――I hope you can get a feel for the Role and GUI settings around here. [Class method] I tried to automatically start & stop EC2 with Lambda's Schedule event [Prevent forgetting to stop or delete EC2, RDS, and ELB! LambdaSchedule Event] (http://dev.classmethod.jp/cloud/aws/lambda-scheduled-event-info/ "Prevent forgetting to stop or delete EC2, RDS, ELB! LambdaSchedule event")

What I want to do this time

--Until now, there was EC2 dedicated to cron execution that automatically started at the start time and automatically stopped at a little later at night. ――When starting automatically, identify Saturdays, Sundays, and holidays, and start automatically only on weekdays. --Since boto3 can be used by default with Lambda's python, narrow down the target to Instance of a specific tag with Filter.

Weekdays or Saturdays, Sundays, and holidays

--For weekday or Saturday and Sunday judgment, if you specify MON-FRI in Lambda's ScheduleEvent (cron), it can be executed only on weekdays, but due to the UTC problem described later, if necessary, python standard date.weekday () etc. use ――There are various ways to judge holidays, but in the end, I rely on Google Calendar's Japanese holidays. So, I have a python module made by Google, so I will use it. [google-api-python-client] (https://github.com/google/google-api-python-client "google-api-python-client")

When using an external module with Lambda, zip it and upload the entire code

--There are two ways to write code in Lambda, one is to write while editing inline on the browser, and the other is to zip each module and upload the code if you want to use an external module. --Google-api-python-client can't be used, of course, so install it locally in any directory with pip.

cd [Appropriate directory]
sudo pip install --upgrade google-api-python-client -t ./

#Write the main file to run on Lambda in the same directory
vim hoge.py

hoge.py


import boto3
import datetime
import sys

from apiclient.discovery import build


# https://console.developers.google.com/project from here
API_KEY = '[Google development API key]'
CALENDAR_ID = 'ja.japanese#[email protected]'

#The year-end and New Year holidays and company holidays do not start automatically(YYYY-MM-Enumerate with DD)。
company_holiday_list = []


#Function name(Here lambda_handler)And the file name(Here hoge.py)To
#Set to Lambda Handler name ex.) hoge.lambda_handler
def lambda_handler(event, context):
    client = boto3.client('ec2')

    #Automatically starts when the tag name "Auto Shutdown" is AUTO/Stop
    #If the tag name "Auto Shutdown" is ON, only automatic stop is performed.
    query_start = [
        {'Name': 'tag:AutoShutdown', "Values": ['AUTO']},
        {'Name': 'instance-state-name', "Values": ['stopped']}
    ]
    query_stop = [
        {'Name': 'tag:AutoShutdown', "Values": ['ON', 'AUTO']},
        {'Name': 'instance-state-name', "Values": ['running']}
    ]

    service = build(serviceName='calendar', version='v3', developerKey=API_KEY)
    events = service.events().list(calendarId=CALENDAR_ID).execute()
    holiday_list = []

    for item in events['items']:
        holiday_list.append(item['start']['date'])

    holiday_list.extend(company_holiday_list)

    #Confirmation of ignition source event name
    try:
        #In case of automatic start, operate only on weekdays except Saturdays, Sundays, and holidays
        if '[Event source ARN(ScheduleEvent for automatic startup)Copy]' in event['resources']:
            if not str(datetime.date.today()) in holiday_list:
                client.start_instances(InstanceIds=get_instanceid(query_start))

        elif '[Event source ARN(ScheduleEvent for automatic stop)Copy]' in event['resources']:
            client.stop_instances(InstanceIds=get_instanceid(query_stop))

        elif '[Event source ARN(ScheduleEvent for automatic stop X minutes advance notification)Copy]' in event['resources'] \
                and (not str(datetime.date.today()) in holiday_list):
            #It's kinder to write a process here that notifies you of Slack 5 or 10 minutes in advance.(Automatic stop explosion prevention)

    except Exception as e:
        #Error handling. Like throwing a stack trace into Slack.

    print("SUCCESS: task succeeded")
    return


def get_instanceid(query):
    client = boto3.client('ec2')
    response = client.describe_instances(Filters=query)

    ec2_count = len(response['Reservations'])
    ec2_list = []

    if not ec2_count == 0:
        for i in range(0, ec2_count):
            ec2_list.append(response['Reservations'][i]['Instances'][0]['InstanceId'])
        return ec2_list
    else:
        print("SUCCESS: specified hosts is None")
        sys.exit()

--Upload code to Lambda

zip -r ~/hoge.zip .
aws lambda update-function-code --function-name [Function name set when creating Lambda] --zip-file fileb://~/hoge.zip

Temporary supplement

-Please rewrite [Event source ARN] to your own environment m (_ _) m The ARN part in the image below is a copy and paste. hoge.png --I don't want to divide Lambda Functions into multiple functions by automatic start / stop, so Branch whether it is start or stop depending on the firing source event (ScheduleEvent name). --Lambda's ScheduleEvent is UTC, so be careful when setting and handling it! For example, I want JST to start automatically at 8 am! In that case, UTC will change the date from JST, so it will not start automatically.

Recommended Posts

Create a bot with AWS Lambda that automatically starts / stops Instances with specific tags
I wrote a Slack bot that notifies delay information with AWS Lambda
Create a Layer for AWS Lambda Python with Docker
Create a Mastodon bot with a function to automatically reply with Python
I wrote a script to create a Twitter Bot development environment quickly with AWS Lambda + Python 2.7
[AWS] Create API with API Gateway + Lambda
[LINE Messaging API] Create a BOT that connects with someone with Python
How to create a serverless machine learning API with AWS Lambda
Create a BOT that can call images registered with Discord like pictograms
[AWS] Create a Python Lambda environment with CodeStar and do Hello World
Let's create a chat function with Vue.js + AWS Lambda + dynamo DB [AWS settings]
Create a bot that boosts Twitter trends
Create a private repository with AWS CodeArtifact
Try implementing a Cisco Spark bot with AWS Lambda + Amazon API Gateway (Python)
[AWS SAM] Create API with DynamoDB + Lambda + API Gateway
Create a LINE BOT with Minette for Python
Create a page that loads infinitely with python
LINE BOT with Python + AWS Lambda + API Gateway
Steps to create a Twitter bot with python
Create a discord bot that notifies unilaterally with python (use only requests and json)
[AWS] I made a reminder BOT with LINE WORKS
Create a chatbot that supports free input with Word2Vec
Procedure for creating a Line Bot on AWS Lambda
Create a bot that only returns the result of morphological analysis with MeCab on Discord
Let's create a program that automatically registers ID/PW from CSV to Bitwarden with Python + Selenium
Create a slack bot
Create a web application that recognizes numbers with a neural network
Create a PythonBox that outputs with Random after PEPPER Input
I made a LINE BOT that returns parrots with Go
I tried to automatically create a report with Markov chain
Create a machine learning app with ABEJA Platform + LINE Bot
Let's create a script that registers with Ideone.com in Python.
Create a life game that is manually updated with tkinter
Create a Twitter BOT with the GoogleAppEngine SDK for Python
Try automating Start / Stop for EC2 instances with AWS Lambda
I just built a virtual environment with AWS lambda layer
Tornado-Let's create a Web API that easily returns JSON with JSON
Create a web API that can deliver images with Django
Create API with Python, lambda, API Gateway quickly using AWS SAM
[AWS] I made a reminder BOT with LINE WORKS (implementation)
The story of creating a bot that displays active members in a specific channel of slack with python