CloudWatchEvents で Trusted Advisor のError,WARNのチェック結果をSlack通知する

2019.07.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

おはようございます、もきゅりんです。

今回の動機は、Trusted AdvisorとCloudWatchEventsを連携してホゲホゲできるということを今更ながら知りまして、自身の後学のために何か作ってみようと思った次第です。

Trusted Advisorには通知設定もあるのですが、Trusted Advisorのチェックにて、Investigation recommended(黄色)とAction recommended(赤色)があるとSlackに流すというCFnテンプレートを作成しました。

ただ、残念ながら手動で修正しないといけない箇所があります。(後述)

ということで、設定には10数分かかるかと思います。

さて、Trusted Advisorがどのようなチェックをするのかは、下記にまとまっています。

Trusted Advisor ベストプラクティス (チェック)

チェック項目の割合として大きいのは、サービス上限チェックのため、その他のチェック項目を一度確認しても限られた時間ですし、有意義だと考えます。

また、Trusted Advisorの概要は、過去弊社ブログでかなり詳しく解説されてもいます。

ご興味ある方は是非ご参照下さい。

AWS再入門 AWS Trusted Advisor編

目次

前提

  • AWS CLIを利用できること

やること

  1. CFnテンプレートでスタックを作成
  2. 手動でCloudWatchEventsの設定を修正する
  3. APIでTrustedAdvisorにリフレッシュかけてみる
  4. 弊社コマーシャル

1. CFnテンプレートでスタックを作成

Trusted Advisor チェック結果を Amazon CloudWatch Events でモニタリングする で記載されているように、CloudWatchEventsルールは米国東部(バージニア北部) リージョンで作成する必要があります。

ということで、リージョン設定を一時的に変更しましょう。

$ export AWS_DEFAULT_REGION=us-east-1

# 確認
$ aws configure list

      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                   moqrin           manual    --profile
    region                us-east-1              env    AWS_DEFAULT_REGION

そしたら、CFnテンプレートでスタックを作成しましょう。

$ aws cloudformation deploy --stack-name ta-slack-lambda --template-file cwe_lambda.yml \
  --parameter-overrides \
  ChannelName=#YOUR_CHANNEL (チャンネルは#から始めて下さいネ)  \
  WebHookUrl=YOUR_SLACK_WEBHOOK \
  --capabilities CAPABILITY_NAMED_IAM
AWSTemplateFormatVersion: 2010-09-09
Description: TrustedAdvisor Calls CloudWatchEvents To Send Slack

# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
  WebHookUrl:
    Description: Slack Webhook Url
    Type: String
  ChannelName:
    Description: Slack Channel
    Type: String

# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
  # Lambdaに適用するIAMRole
  LambdaIAMRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

  CloudWatchEventRule:
    Type: AWS::Events::Rule
    Properties:
      Description: 'TrustedAdvisor Alerts Status WARN and ERROR Events'
      EventPattern:
        source:
          - aws.trustedadvisor
        detail-type:
          - Trusted Advisor Check Item Refresh Notification
        detail:
          state:
            - WARN
            - ERROR
      Targets:
        - Arn:
            Fn::GetAtt:
              - SendSlackLambdaFunction
              - Arn
          Id: TASendSlack
      State: ENABLED

  # LambdaFunction
  SendSlackLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        ZipFile: |
          # -- coding: utf-8 --
          import os
          import json
          import logging

          from urllib.request import Request, urlopen
          from urllib.error import URLError, HTTPError

          HOOK_URL = os.environ['webHook']
          SLACK_CHANNEL = os.environ['slackChannel']

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)


          def lambda_handler(event, context):

              slack_title = event['detail']['check-name']
              slack_message = event['detail']['check-item-detail']
              check_status = event['detail']['check-item-detail']['Status']

              slack_title = str(slack_title)
              slack_message = str(slack_message)

              if check_status != 'Red':

                  send_data = {
                      "channel": SLACK_CHANNEL,
                      "username": "Trusted Advisor: " + slack_title,
                      "icon_emoji": ":warning:",
                      "text": slack_message,
                  }
              else:
                  send_data = {
                      "channel": SLACK_CHANNEL,
                      "username": "Trusted Advisor: " + slack_title,
                      "icon_emoji": ":fire:",
                      "text": slack_message,
                  }

              req = Request(HOOK_URL, json.dumps(send_data).encode('utf-8'))
              try:
                  response = urlopen(req)
                  response.read()
              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)
      Description: 'Send Slack By response to Trused Advisor'
      Environment:
        Variables:
          slackChannel: !Ref ChannelName
          webHook: !Ref WebHookUrl
      Handler: 'index.lambda_handler'
      Role:
        Fn::GetAtt:
          - LambdaIAMRole
          - Arn
      Runtime: python3.7
      Timeout: 5
  LambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref SendSlackLambdaFunction
      Action: 'lambda:InvokeFunction'
      Principal: 'events.amazonaws.com'
      SourceArn:
        Fn::GetAtt:
          - 'CloudWatchEventRule'
          - 'Arn'

2. 手動でCloudWatchEventsの設定を修正する

作成が完了したら、CloudWatchEventsを手動で修正します。

自分の過失の可能性もあるのですが、なぜかイベントパターンがうまく作成できないため、手動で修正をします。

  • 想定する設定

setup

  • 作成される設定

setup2

お分かり頂けただろうか...?

なお、公式のテンプレートで作成してもうまくいきませんでした。

https://github.com/aws/Trusted-Advisor-Tools/blob/master/LowUtilizationEC2Instances/TAStopLowUtilizationEC2Instances.template

error_setup

では、CLoudWatchEventsのルール右上のタブから編集します。

update_setup

何か注意されますが、無視して進みます。

update_setup2

先ほどの想定する設定と同様に手動で入力していきます。

setup

ターゲットは特に変更せず、設定の詳細からルールを更新します。

rule update

3. APIでTrustedAdvisorにリフレッシュかけてみる

Trusted Advisor の結果はどれぐらい頻繁にリフレッシュできますか?

には、このように書かれています。

チェックは、前回リフレッシュしてから 5 分後にリフレッシュできます。個々のチェックをリフレッシュすることも、または、[summary] ダッシュボードの右上隅にある [Refresh All] を選択してすべてのチェックを一括でリフレッシュすることもできます。 Trusted Advisor ダッシュボードにアクセスすると、直近の 24 時間以内に更新されなかったチェックは、自動的に更新されます。これには、数分かかる場合があります。チェックタイトルの右側に最新の更新日時が表示されます。 さらに、ビジネスまたはエンタープライズサポートのお客様の場合、Trusted Advisor データは毎週自動で更新されます。

「ビジネス」もしくは「エンタープライズ」じゃない人は、ダッシュボード見に行く必要がありそうだな、と。ダッシュボード見に行くんだったら、あんま意味ないな、と。

ということで、「ビジネス」もしくは「エンタープライズ」じゃない人のために、(自分の学習のため)APIで全チェックを更新するスクリプトを用意してみました。

$ cat trusted_advisor_refresh.sh
#!/bin/bash

aws support describe-trusted-advisor-checks --region us-east-1 --language en | jq -rc ".checks[].id" > ta_checks.txt

while read line
do
   aws support refresh-trusted-advisor-check --region us-east-1 --check-id "$line"
   
done <ta_checks.txt

なお、APIについては、こちらの記事を参考としています。

AWS-CLIでTrusted Advisorのステータスを見たい

そしたらー

わざと東京リージョンで22番ポートを全世界に開放したEC2インスタンスを起動させちゃいます。

demo-instance start

そして、先ほどのシェルスクリプトを叩いちゃいます。

$ ./trusted_advisor_refresh.sh

こんな感じでSlackに通知されました。

Slack posted

いかがでしたでしょうか。

他にもいろいろ飛んでくると思います。要チェックです。

4. 弊社コマーシャル

さて、弊社クラスメソッドメンバーズにご契約頂くと、無料で上記のようなチェックはおろか(もちろん、はるかに充実したチェック機能で簡単に設定できます)、バックアップ機能などをご利用頂ける、

insightwatch

というサービスがあります。

是非ご利用下さい!!

以上、どなたかのお役に立てば幸いです。

参考

Trusted Advisor チェック結果を Amazon CloudWatch Events でモニタリングする

20180711 AWS Black Belt Online Seminar AWS Trusted Advisor

AWS再入門 AWS Trusted Advisor編

AWS-CLIでTrusted Advisorのステータスを見たい

The sample functions provided help to automate AWS Trusted Advisor best practices using Amazon Cloudwatch events and AWS Lambda.

https://docs.aws.amazon.com/ja_jp/awssupport/latest/APIReference/API_Operations.html