Open7
LambdaでEC2のステータス変化をSlack通知
EC2のステータス(起動,停止)をSlack通知したくなったなり実装したのでその際のメモ.
EC2のステータス変化を取得するトリガーはCloudWatch Eventsと記憶していたが, 今はAmazon Event Bridgeというものの一部になっていた.
lambdaでpythonランタイムで実装する際, 標準パッケージでないものをzip化してレイヤーとしてアップロードするのは調べればすぐ出てくるものだが, それでもなぜかimportできなくて少々ハマった.
原因としては, zip化したローカル環境ではpython3.7
に対してlambdaのラインタイムがpython3.8
でバージョン相違によるimportできないというところだった. 3系なら読み込めるだろうと言う謎の思い込みのせいでハマった.
python -V
mkdir -p tmp && cd ./tmp
pip install requests boto3 -t .
chmod -R 755 ./*
zip -r upload.zip *
lambda関数コード
下記記事を参考にさせて頂きながら実装.
起動と停止の二つの変化をトリガーにしている.
インスタンス状態をマネコンでみるためのボタンも追加.
import json
import boto3
import requests
def post_slack_h(data):
# SlackでIncoming Webhooksを有効にして取得したWebhook URLを記載
post_url = 'https://hooks.slack.com/services/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'
requests.post(post_url, data=json.dumps(data))
def lambda_handler(event, context):
print('Event')
print(json.dumps(event, indent=2))
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,
})
instance_state = event['detail']['state']
stopped_or_runnnig_message = "起動" if instance_state == "running" else "停止"
ec2_instances_url = "https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#Instances:"
ec2_instance_detail_url = "https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#InstanceDetails:instanceId="+instance_id
data = {
'attachments': [{
'pretext': '<!here> EC2インスタンスが *'+ stopped_or_runnnig_message +'* しました',
'color': 'good',
'fields': fields,
"actions": [
{
"type": "button",
"text": "Open Instance List",
"url": ec2_instances_url
},
{
"type": "button",
"text": "Open Instance Detail",
"url": ec2_instance_detail_url
}
]
}]
}
# Slack通知
post_slack_h(data)