CloudWatchアラートを重要度で色分けしてSlackへ通知する

CloudWatchアラートを重要度で色分けしてSlackへ通知する:


なぜ、アラートの重要度で色分けが必要なのか

現状、CloudWatchメトリクスでしきい値を超えるとSlackへアラートが飛ぶようになっています。

しかし、新たにSlackチャンネルへ入ってきた人は、通知を見ても何が重大なのかわからないのが実際のところです。

さらに、通知が来るたびにダッシュボードに確認しに行くのも手間です。

そもそも、必要ない通知があることも、、、

そこで、通知の精査と重要度分けが必要だなということで色分けすることにしました。


なにを使っているのか

以下、構成

CloudWatchメトリクス → Simple Notification Service (SNS) → AWS Lambda Function (Lambda) → Slack通知 


どうやって構築するか



スクリーンショット 2018-12-08 23.28.03.png


SNSを重要度別に複数作成し、LambdaでどのSNSかを判定し、色分けしてSlackへ通知というのがミソになります


Slack通知用のLambdaを作成

Slack通知に関しては基本的に以下を参考にしています。

通知用のLambdaで実行するpythonコードです。

※ ちなみに、以下のコードではKMSを使っていません。

lambda_function.py
from __future__ import print_function 
 
import boto3 
import json 
import logging 
import os 
 
from base64 import b64decode 
from urllib2 import Request, urlopen, URLError, HTTPError 
 
 
HOOK_URL = os.environ['HookUrl'] 
SLACK_CHANNEL = os.environ['slackChannel'] 
 
logger = logging.getLogger() 
logger.setLevel(logging.INFO) 
 
AWS_REGION = os.environ['AWS_REGION'] 
 
def lambda_handler(event, context): 
    logger.info("Event: " + str(event)) 
    message = json.loads(event['Records'][0]['Sns']['Message']) 
    topicArn = str(event['Records'][0]['Sns']['TopicArn']) 
    logger.info("Message: " + str(message)) 
 
    alarm_name = message['AlarmName'] 
    new_state = message['NewStateValue'] 
    reason = message['NewStateReason'] 
 
    # topicArnをeventからパースして、WarningかCriticalが含まれているかを判定しています 
    if ("slack-alert-warning" in topicArn): 
        color = "warning" 
    elif ("slack-alert-critical" in topicArn): 
        color = "danger" 
 
    if (new_state == "ALARM"): 
        new_state = ":exclamation: " + new_state 
    elif (new_state == "OK"): 
        new_state = ":white_check_mark: " + new_state 
        color = "good" 
 
    url = "<https://" + AWS_REGION + ".console.aws.amazon.com/cloudwatch/home?region=" + AWS_REGION + "#cw:dashboard=Home|Link to cloudwatch>" 
 
    # attachmentsを使えばcolorで色付けできます 
    slack_message = { 
        'channel': SLACK_CHANNEL, 
        'attachments': [{ "color": color, "text": "%s \n alarm_name: `%s` \n state is now %s: ```%s```" % (url, alarm_name, new_state, reason) }] 
    } 
 
    req = Request(HOOK_URL, json.dumps(slack_message)) 
    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) 
 
LambdaをCloudFormationで作る場合は以下を参考にしてください。

上記のURL通りに、手で作るのもOKです!

alert-lambda.yaml
  LambdaFunction: 
    Type: "AWS::Lambda::Function" 
    Properties:  
      Code: 
        S3Bucket: << ソースを置いているバケット名 >> 
        S3Key: << バケットからソースへの相対パス >> 
      FunctionName: Alert-message-to-slack 
      Handler: lambda_function.lambda_handler 
      MemorySize: 128 
      Role: lambda_basic_execution 
      Runtime: python3.6 
      Environment: 
        Variables: 
          HookUrl: << IncomingWebのURL >> 
          slackChannel: << アラートを流すSlackのChannel名 >> 


CloudFormationでSNSを作成

sns-topic.yaml
--- 
AWSTemplateFormatVersion: '2010-09-09' 
 
  Parameters: 
    LambdaFunction: 
      Type: String 
      Default: << lambda fuction の ARN >> 
 
  Resources: 
# SNS Topic 
    WarningLevelAlert: 
      Type: AWS::SNS::Topic 
      Properties: 
        DisplayName: slack alert 
        TopicName: slack-alert-warning 
        Subscription: 
          - Endpoint: ! Ref LambdaFunction 
            Protocol: lambda 
    CriticalLevelAlert: 
      Type: AWS::SNS::Topic 
      Properties: 
        DisplayName: slack alert 
        TopicName: slack-alert-critical 
        Subscription: 
          - Endpoint:  ! Ref LambdaFunction 
            Protocol: lambda 
# Lambda Permission 
    WarningLevelAlertPermission: 
      Type: AWS::Lambda::Permission 
      Properties: 
        Action: lambda:InvokeFunction 
        FunctionName: !GetAtt LambdaFunction.Arn 
        Principal: sns.amazonaws.com 
        SourceArn: !Ref WarningLevelAlert 
    CriticalLevelAlertPermission: 
      Type: AWS::Lambda::Permission 
      Properties: 
        Action: lambda:InvokeFunction 
        FunctionName: !GetAtt LambdaFunction.Arn 
        Principal: sns.amazonaws.com 
        SourceArn: !Ref CriticalLevelAlert 
 
  Outputs: 
    WarningLevelAlertSNSTopic: 
      Description: SNS Topic Name 
      Value: !Ref WarningLevelAlert 
      Export:  
        Name: WarningLevelAlertSNSTopic 
    CriticalLevelAlertSNSTopic: 
      Description: SNS Topic Name 
      Value: !Ref CriticalLevelAlert 
      Export:  
        Name: CriticalLevelAlertSNSTopic 


試しに、lambda function作成時にアラームを設定

LambdaのメトリクスにSNSを登録する部分は共通部分になるので、1つのyamlに分けS3へアップロードしておく。

cloudwatch-lambda-alert.yaml
--- 
AWSTemplateFormatVersion: '2010-09-09' 
Description: Lambda Cloudwatch 
Parameters: 
  FunctionName: 
    Type: String 
    Default: << lambda function の名前 >> 
  Errors: 
    Type: Number 
    Default: 1 
 
Resources: 
  ErrorsAlarm: 
    Type: AWS::CloudWatch::Alarm 
    Properties: 
      AlarmName: 
        Fn::Join: 
          - '' 
          - - !Ref FunctionName 
            - '/Lambda/Errors' 
      AlarmDescription: 
        Fn::Join: 
          - '' 
          - - 'Lambda/Errors/' 
            - !Ref FunctionName 
            - '/' 
            - !Ref Errors 
            - 'over' 
      AlarmActions: 
        - !ImportValue CriticalLevelAlertSNSTopic 
      MetricName: Errors 
      Namespace: AWS/Lambda 
      Statistic: Sum 
      Period: '60' 
      EvaluationPeriods: '1' 
      Threshold: !Ref Errors 
      ComparisonOperator: GreaterThanOrEqualToThreshold 
      Dimensions: 
        - Name: FunctionName 
          Value: !Ref FunctionName 
 
Lambda作成時に、LambdaのメトリクスにSNSを登録する

lambda.yaml
# 省略 
 
  LambdaFunction: 
    Type: "AWS::Lambda::Function" 
 
# 省略 
 
  CloudWatch: 
    Type: AWS::CloudFormation::Stack 
    Properties: 
      TemplateURL: 
        Fn::Join: 
          - '' 
          - - 'https://s3.amazonaws.com/' 
            - << S3 バケット名 >> 
            - '/cloudwatch-lambda-alert.yaml' 
      Parameters: 
        FunctionName: !Ref LambdaFunction 
 


結果

Slackのアラート通知がわかりやすくなった、、かな

Linkの名前が変わっているのはご愛嬌ということでw

Warningのアラート


スクリーンショット 2018-12-08 23.23.45.png


Criticalのアラート


スクリーンショット 2018-12-08 23.25.58.png


コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)