LoginSignup
8
10

More than 5 years have passed since last update.

AWS Lambda(Python)によるサーバー簡易監視と、Slackでの結果通知

Posted at

実現したかったこと

  • 運用中サーバーの簡易監視として、定期的にHTTPアクセスを行い、結果を確認したい。
  • サーバーレスで実行したい。
    • 対象サーバーにアクセスするIPを制限しているため、監視元は固定IPの必要がある。
  • 完全自動化し、監視結果だけが通知されて欲しい。

最終的に実現したこと

  • 全体イメージ 全体イメージ

  • S3に監視先サーバーデータを配置する。

    • データの形式は以下の通り。

      servers.json
      {
          "servers": [
              {"name": "Google", "url": "http://www.google.co.jp"},
              {"name": "Yahoo", "url": "http://www.yahoo.co.jp"}
          ]
      }
      
  • AWS Lambda(Python)から上記のデータを読み込み、各サーバーにHTTPアクセスを行う。

  • 監視結果をSlackに通知する。

  • 上記を、CloudWatch Events - Scheduleで定期実行する。

設定詳細

VPC設定

IAM設定

  • Lambda作成時に、roleのtemplateとして、Simple Microservice permissionsを選択。
  • S3にアクセスするため、AmazonS3ReadOnlyAccessのポリシーをアタッチ。
  • LambdaVPC上で実行するため、AWSLambdaVPCAccessExecutionRoleのポリシーをアタッチ。

CloudWatch Events - Schedule設定

Slack

AWS Lambda(Python)

  • エラーハンドリング周りは改善の余地あり。
lambda_function.py
import json
import requests
import boto3

BUCKET_NAME = 'xxxxxxxxxx'
OBJECT_NAME = 'xxxxxxxxxx/servers.json'
SLACK_POST_URL = 'https://hooks.slack.com/services/xxxxxxxxxx/xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxx'

def lambda_handler(event, context):
    json_data = __getServers()
    __check_server(json_data)

def __getServers():
   s3 = boto3.resource('s3')
   obj = s3.Object(BUCKET_NAME, OBJECT_NAME)
   response = obj.get()
   body = response['Body'].read()
   return body.decode('utf-8')

def __check_server(json_data):
    data = json.loads(json_data)
    servers = data['servers']

    has_error = False

    for server in servers:
        name = server['name']
        url = server['url']
        print("Check: " + name)

        try:
            r = requests.get(url)
            if r.status_code != 200:
                __send_error_message(name, url)
                has_error = True
        except requests.exceptions.RequestException as e:
            __send_request_error_message(name, url)
            has_error = True

    if has_error == False:
        __send_success_message()

def __send_error_message(name, url):
    payload = {
        "text": name + '\n' + url + '\n' + '*ERROR!*',
        "icon_emoji": ":x:"
    }
    __send_message(payload)

def __send_request_error_message(name, url):
    payload = {
        "text": name + '\n' + url + '\n' + '*Request Error!*',
        "icon_emoji": ":warning:"
    }
    __send_message(payload)

def __send_success_message():
    payload = {
        "text": "All Servers OK!",
        "icon_emoji": ":o:"
    }
    __send_message(payload)

def __send_message(payload):
    try:
        return requests.post(SLACK_POST_URL, json=payload)
    except requests.exceptions.RequestException as e:
        return None


AWS Lambda(Python)設定時の注意点

  • ライブラリはソースコードと同じディレクトリに配置する。
pip install requests -t .
  • ソースコードとライブラリをまとめて、zipにして配置する。
zip -r lambda_function.zip *

雑感

  • AWS LambdaにVPCを設定できるようになったことで、データ送信元を固定IPアドレスにしてLambdaを実行できるようになったため、使いどころが広がった。
  • 手軽な通知先として、Slackとの連携が簡単で便利すぎ。
  • servers.jsonの中身をbodyに詰めた、HTTP POST通信をトリガーに、API Gateway経由で実行させる方法も試したが、最終的に定期実行がラクな現在の形とした。
8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10