AWSで起動しているインスタンスをPythonでチェックしてSlackに投稿する

AWSで起動しているインスタンスをPythonでチェックしてSlackに投稿する:

Pythonのお勉強とEC2インスタンス停止忘れ防止のため、起動しているEC2インスタンスをチェックしてSlackに投稿するようにしたメモ。

と基本的に同じ。


参考リンク

以下の先人の記事を参考に作成。


動作イメージ

image.png


Slackの準備


Webhook URLの取得

以下を参考にWebhook URLを取得する。


AWS CLI

Pythonの前にAWS CLIで起動しているインスタンスを確認してみる。

AWS CLIをセットアップする。

pip3 install awscli 
aws configure 
インスタンスを確認する。

コマンド
aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" 


Python + AWS Lambda

AWS Lambda上のPythonからSlackに投稿する。


Roleの作成

IAMコンソールでRoleを作成する。AWSLambdaBasicExecutionRoleCloudWatchReadOnlyAccessAmazonEC2ReadOnlyAccessのポリシーをアタッチする。



image.png


作成したRoleのARNを確認しておく。


コード作成

作成するファイルは以下の3つ。

├── lambda.json 
├── lambda_function.py 
└── requirements.txt 
lambda.jsonはlambda-uploderが使用するJSON形式のLambda関数の定義ファイル。先ほど作成したRoleのARN、Slack Webhook URL、Slackチャンネル名を指定する。lambda-uploaderの使い方と、jsonの書き方は以下を参照。

lambda.json
{ 
  "name": "aws_instance_checker", 
  "description": "My AWS instance checker.", 
  "region": "ap-northeast-1", 
  "runtime": "python3.7", 
  "handler": "lambda_function.lambda_handler", 
  "role": "arn:aws:iam::hogehoge", 
  "timeout": 300, 
  "memory": 128, 
  "variables": 
    { 
      "SLACK_WEBHOOK_URL": "https://hooks.slack.com/services/hogehoge", 
      "SLACK_CHANNEL": "#hogehoge" 
    } 
} 
lambda_function.pyが関数本体。以下を参考に作成。

lambda_function.py
import datetime 
import os 
import json 
 
import boto3 
import pytz 
import requests 
 
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL'] 
SLACK_CHANNEL = os.environ['SLACK_CHANNEL'] 
 
 
def get_instances(): 
    """boto3を使って全てのリージョンで起動しているEC2インスタンスを取得する 
 
    :return: instances 
    """ 
 
    # 全リージョンを取得 
    client = boto3.client('ec2') 
    regions = client.describe_regions()['Regions'] 
 
    instances = [] 
 
    # 各リージョン毎に繰り返し 
    for region in regions: 
        client = boto3.client('ec2', region_name=region['RegionName']) 
 
        response = client.describe_instances( 
            Filters=[ 
                { 
                    'Name': 'instance-state-name', 
                    'Values': [ 
                        'running', 
                    ] 
                }, 
            ] 
        ) 
 
        reservations = response['Reservations'] 
 
        if not reservations: 
            continue 
 
        for reservation in reservations: 
            instance = dict() 
            instance['id'] = reservation['Instances'][0]['InstanceId'] 
            tags = reservation['Instances'][0]['Tags'] 
            instance['name'] = 'null' 
            for tag in tags: 
                if tag['Key'] == 'Name': 
                    instance['name'] = tag['Value'] 
            instance['type'] = reservation['Instances'][0]['InstanceType'] 
            instance['region'] = region['RegionName'] 
            instances.append(instance) 
 
    return instances 
 
 
def build_message(instances): 
    """SlackにPOSTするメッセージボディを作成する 
 
    :param instances: 
    :return: message 
    """ 
 
    if not instances: 
        return None 
 
    now = datetime.datetime.now(pytz.timezone('Asia/Tokyo')) 
 
    text = '{}現在稼働しているEC2インスタンス一覧'.format(now.strftime('%Y年%m月%d日%H時%M分')) 
    atachements_text = '' 
    for instance in instances: 
        atachements_text += 'name: {}, type: {}, id: {}, region: {}\n'.format( 
            instance['name'], instance['type'], instance['id'], instance['region']) 
 
    atachements = {'text': atachements_text, 'color': 'red'} 
 
    message = { 
        'text': text, 
        'channel': SLACK_CHANNEL, 
        'attachments': [atachements], 
    } 
    return message 
 
 
def post_message(message): 
    """SlackにPOSTする 
 
    :param message: 
    :return: 
    """ 
 
    response = requests.post(SLACK_WEBHOOK_URL, data=json.dumps(message)) 
    response.raise_for_status() 
 
 
def lambda_handler(event, context): 
 
    instances = get_instances() 
 
    message = build_message(instances) 
 
    if message: 
        post_message(message) 
requirements.txtは使用するモジュールの定義。

requirements.txt
boto3 
pytz 
requests 


アップロード

lambda-uploaderをインストールする。

pip3 install lambda-uploader  
アップロードする。

$ lambda-uploader 
λ Building Package 
λ Uploading Package 
λ Fin 
$ 


スケジュール実行

関数の設定で、トリガーとしてCloudWatch Eventsを追加する。



image.png


スケジュールを設定する。確認のためとりあえずcron(* * * * ? *)(毎分実行)を設定する。



image.png


Slackに投稿されることを確認する。



image.png


上手く投稿できなかったら、CloudWatch Logsでログを確認する。上手く投稿が確認できたら、CloudWatch Eventsでスケジュールをcron(0 * * * ? *)(毎時)に変更する。



image.png


コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)