본문 바로가기

Mornitoring/CloudWatch

Cloudwatch 경보 설정 - 2. SNS, SNS SMS, SES 보내기

먼저 SNS가 발생하면 람다에 SNS가 발생한 내역을 전달하고,

이 내용에서 필요한 부분들만 수집하여서 메일을 보내도록 구성해보겠습니다.

 

람다 함수를 만들기전, ec2 describe와 ses 전송, sns publish에 관한 권한이 있어야 하기 때문에 Lambda Role을 하나 만들어주겠습니다.

 

이제 위의 롤과 아래 코드가 작성 된 람다 함수를 만들어주겠습니다.

메일은 SES를 통해 보내주고, 메세지는 SNS의 SMS를 통해 보내주겠습니다.

(SES나 SMS는 기본적으로 보낼 수 있는 한도 제한이 작아 꼭 리밋을 체크하시기 바립니다.)

혹은 다른 주제를 만들어서, Email 전송이 있는 구독들을 만든 후 SNS Publish를 하셔도 됩니다.

def send_email_sns(sub, content) :
	client = boto3.client('sns')
	response = client.publish(
	    TopicArn={sns-arn},
	    Message=content,
	    Subject=sub,
	    MessageStructure='raw',
	)

 

현재 SMS는 https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sns-supported-regions-countries.html

서울리전에서 사용이 안 되기 때문에 저는 도쿄리전으로 SES는 버지니아 북부로 리전을 선택해주겠습니다.

 

logger.py

import logging.handlers

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

formatter = logging.Formatter('[%(levelname)s:%(asctime)s] (%(filename)s:%(lineno)d) > %(message)s')
streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)

logger.addHandler(streamHandler)

lambda_function.py

import json
import boto3
from logger import logger
from botocore.exceptions import ClientError

def get_tagName(instance_id):
    client = boto3.client('ec2')
    response = client.describe_instances(InstanceIds=[instance_id])
    for ec2 in response['Reservations']:
        for instance in ec2['Instances']:
            for tags in instance['Tags']:
                if tags['Key'] == 'Name':
                    return tags['Value']


def send_sms(subject, message, phone):
    client = boto3.client('sns')
    try:
        response = client.publish(
            PhoneNumber=phone,
            Message=message,
            Subject=subject,
        )
        logger.debug(response)
        logger.debug("Success Send SMS")
    except Exception as e:
        logger.error(e)
        logger.error("Send SMS Error")
        raise e

def send_ses(RECIPIENT, SUBJECT, body) :
    SENDER = "sender <sender@google.com>"
    AWS_REGION = "us-east-1"
    BODY_TEXT = (body)
    BODY_HTML = """<html>
    <head></head>
    <body>
      <h1>"""+SUBJECT+"""</h1>
      <p>
        """+body+"""
      </p>
    </body>
    </html>"""            
    
    CHARSET = "UTF-8"
    
    client = boto3.client('ses', region_name='us-east-1')
    try:
        response = client.send_email(
            Destination={
                'ToAddresses': [
                    RECIPIENT
                ],
            },
            Message={
                'Body': {
                    'Html': {
                        'Charset': CHARSET,
                        'Data': BODY_HTML,
                    },
                    'Text': {
                        'Charset': CHARSET,
                        'Data': BODY_TEXT,
                    },
                },
                'Subject': {
                    'Charset': CHARSET,
                    'Data': SUBJECT,
                },
            },
            Source=SENDER
        )
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        print("Email sent! Message ID:"),
        print(response['ResponseMetadata']['RequestId'])

def lambda_handler(event, context):
    try:
        info = event['Records'][0]['Sns']
        message = json.loads(info['Message'])
        sns_arn = info['TopicArn']
        subject = message['AlarmName']
        reason = message['NewStateReason']
        start_time = message['StateChangeTime']
        ec2_name = get_tagName(message['Trigger']['Dimensions'][0]['value'])
    
        body = "Subject : " + subject + \
        "\nReason : " + reason + \
        "\nStart Time : " + start_time + \
        "\nEC2 Instance : " + ec2_name
        logger.debug(body)
        
        send_sms(subject, body, '+821000000000')
        send_ses("sender@google.com", subject, body)
        return ('Sent a message to an Amazon SNS topic.')
    except Exception as e:
        logger.error(e)
        
    

 

SNS에서 구독을 람다로 만들어서 위에서 만든 람다를 매핑시켜주시면 됩니다.

 

 

자, 이제 다시 서버에 스트레스를 줘서 테스트해보도록 하겠습니다.

먼저 SMS를 통한 문자메세지는 아래와 같이오며,

 

이메일의 경우 제목이 인코딩 타입 때문인지, 무엇인지 조금 이상하긴 하지만

내용이 정상적으로 제가 커스텀하게 만든 상태로 전달되는 것을 볼 수 있습니다.

 

경보 설정 및 알림에 대한 설정을 알아봤습니다.