🐡
RDSのエラーログをslackに通知する仕組みを作成してみる
今回作成する構成
cloud watchのエラーログを検知するとslackにエラーが発生したことを通知する仕組みを作成する
とりあえず今回の本筋でないELB-ECS-RDSはcloudformationで作成する
下記リポジトリーからコードをダウンロードして、cloudformationで起動してみてください!
cloud watchログに移動して, RDSのエラーログにlambdaにログを送信するサブスクリプションを作成する
-
cloud watch RDSエラーログの部分でサブスクリプションを作成する
-
lambdaを作成しておく
-
lambdaの発火条件としてrdsのエラーログをlambdaの発火条件にする
-
cloudwatch rdsのエラーログのサブスクリプションにlambdaが追加されたことを確認(ここから追加しても良い)
lambdaを実装する
-
slackのhook urlをWEB_HOOK_URLの環境変数をセットする
-
slackにpostするコードを実装する
import boto3
import json
import logging
import os
from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
SLACK_CHANNEL = os.environ['SLACK_CHANEL']
HOOK_URL = os.environ['WEB_HOOK_URL']
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
slack_message = {
'channel': SLACK_CHANNEL,
'attachments': [{
'title': 'DBでエラーが発生しました',
'text': 'DBでエラーが発生しました'
}]
}
req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
try:
response = urlopen(req)
response.read()
logger.info("Message posted to %s", slack_message['channel'])
except HTTPError as e:
logger.error("Request failed: %d %s", e.code, e.reason)
except URLError as e:
logger.error("Server connection failed: %s", e.reason)
実行してみる
見事実行されました!
WEB_HOOK_URLを暗号化
- kmsでカスタムキーを作成
kmsにlambdaからのアクセスを許可するために、lambdaのロールにアクセス許可を追加
-
lambdaの環境変数を暗号化
暗号化されたことを確認する
-
lambdaの実装変更
import boto3
import json
import logging
import os
from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
SLACK_CHANNEL = os.environ['SLACK_CHANEL']
ENCRYPTED_WEB_HOOK_URL = os.environ['WEB_HOOK_URL']
# 下記の行で複合化する
HOOK_URL = boto3.client('kms').decrypt(
CiphertextBlob=b64decode(ENCRYPTED_WEB_HOOK_URL),
EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']}
)['Plaintext'].decode('utf-8')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
print('DECRYPTED : {}'.format(HOOK_URL))
slack_message = {
'channel': SLACK_CHANNEL,
'attachments': [{
'title': 'DBでエラーが発生しました',
'text': 'DBでエラーが発生しました'
}]
}
req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
try:
response = urlopen(req)
response.read()
logger.info("Message posted to %s", slack_message['channel'])
except HTTPError as e:
logger.error("Request failed: %d %s", e.code, e.reason)
except URLError as e:
logger.error("Server connection failed: %s", e.reason)
- 通知できました!!!
Discussion