ForgeVision Engineer Blog

フォージビジョン エンジニア ブログ

EC2インスタンス起動時にSlack通知する

こんにちは。ソリューション技術部の栗原です。

前回の記事で、CloudWatch Events と Lambda を利用した EC2インスタンス自動起動停止の方法について紹介しました。 techblog.forgevision.com

こちらの方法でインスタンスが自動的に起動停止するようになりましたが、実際にインスタンスが起動停止しているかどうかや、グローバルIPアドレスなどのインスタンスの情報はマネジメントコンソールにログインして確認する必要があります。今回は、これらをインスタンス起動時に Slack に通知するようにしてみたいと思います。

設定方法

それでは設定方法を記載していきます。

Slack Incoming Webhook URL の取得

Slack へのメッセージ投稿には Incoming Webhooks を利用します。Webhook URL が必要となりますので取得します。

通知先の Slack ワークスペースにサインイン後、下記URLにアクセスします。
https://slack.com/services/new/incoming-webhook

メッセージ投稿先チャンネルを選択し、[着信Webフックインテグレーションの追加]を選択します。 f:id:kurihara_fv:20181010174658p:plain

Webhook URL が表示されますので記録しておきましょう。 f:id:kurihara_fv:20181010174714p:plain

Lambda用IAMロールの作成

下記ポリシーを付与したIAMロール「lambda_role」を作成します。いずれもAWS管理ポリシーです。

  • AWSLambdaBasicExecutionRole
  • AmazonEC2ReadOnlyAccess

f:id:kurihara_fv:20181011102850p:plain

Lambda 関数の作成

以下の内容で Lambda 関数を作成します。 f:id:kurihara_fv:20181010174918p:plain

トリガー

トリガーに CloudWatch Events を選択します。 f:id:kurihara_fv:20181010174943p:plain

以下の内容でルールを作成し、[追加]を選択します。 f:id:kurihara_fv:20181010174949p:plain

これでインスタンスのステータスが running に遷移したタイミングで Lambda が起動します。

関数コード

コードは以下の通りです。
Slack に投稿するメッセージは、Attachments の機能を利用して装飾しています。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import boto3
import urllib2
import json

def lambda_handler(event, context):
    instance_id = event['detail']['instance-id']

    client = boto3.client('ec2')
    response = client.describe_instances(
        InstanceIds=[
            instance_id,
        ],
    )

    instance = response['Reservations'][0]['Instances'][0]
    fields = []

    # Name
    for tag in instance['Tags']:
        if tag['Key'] != 'Name':
            continue
        instance_name = tag['Value']
        fields.append({
            'title': 'Name',
            'value': instance_name,
            'short': True,
        })
        break

    # InstanceId
    fields.append({
        'title': 'インスタンス ID',
        'value': instance_id,
        'short': True,
    })

    # InstanceType
    fields.append({
        'title': 'インスタンスタイプ',
        'value': instance['InstanceType'],
        'short': True,
    })

    # AvailabilityZone
    fields.append({
        'title': 'アベイラビリティーゾーン',
        'value': instance['Placement']['AvailabilityZone'],
        'short': True,
    })

    # NetworkInterfaces
    for interfaces in instance['NetworkInterfaces']:
        idx = interfaces['Attachment']['DeviceIndex']
        for ip_addresses in interfaces['PrivateIpAddresses']:
            fields.append({
                'title': 'プライベート IP (eth{})'.format(idx),
                'value': ip_addresses.get('PrivateIpAddress'),
                'short': True,
            })
            fields.append({
                'title': 'パブリック IP (eth{})'.format(idx),
                'value': ip_addresses.get('Association', {}).get('PublicIp'),
                'short': True,
            })

    data = {
        'attachments': [{
            'pretext': '<!here> インスタンスが起動しました',
            'color': 'good',
            'fields': fields,
        }]
    }

    # Slack通知
    url = '<Webhook URLを入力>'
    req = urllib2.Request(url, json.dumps(data), {'Content-Type': 'application/json'})
    res = urllib2.urlopen(req)
    res.read()
    res.close

設定が完了しましたので、インスタンスを起動してみます。

Slack にメッセージが投稿されました。 f:id:kurihara_fv:20181010175016p:plain

最後に

前回に引き続き CloudWatch Events+Lambda の構成で、EC2インスタンス起動を Slack に通知する方法を紹介しました。
CloudWatch Events は、他にもさまざまなイベントをサポートしているので活用していきたいですね。