Amazon CloudWatch Logsの異常検出をCloudFormationで設定してみた #AWSreInvent

追加料金が不要なので、とりあえず導入してみたいと思います。
2023.12.01

CloudWatch Logsにログの異常検出が追加されました。

ドキュメントのFAQによると、次のような現象があると、検出するようです。

  • ロググループで以前に見られなかったパターンのログイベントがある
  • 既知のパターンに対する大きな変化がある
  • 通常は一定の値セットを持つ動的トークンの新しい値がある
  • 動的トークンの値の出現数に大きな変化がある

また、こちらの記事によると、追加料金が不要で利用できるようです。

というわけで、本記事では、CloudWatch Logsの異常検出をCloudFormationで設定してみました。

おすすめの方

  • CloudWatch Logsの異常検出をCloudFormationで設定したい方
  • CloudWatch Logsの異常検出の様子を知りたい方

実験用のLambdaを作成する

Lambdaのコード

app.py

import json
import logging

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


def lambda_handler(event, context):
    logger.info('hello')
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

15分毎に実行させる

このLambdaを15分ごとに実行させます。

01_eventbridge_rate15

CloudWatch Logsの異常検出をCloudFormationで設定する

CloudFormationテンプレート

さきほど作成したLambdaのロググループと適当なロググループの異常ディテクターを作成します。 ロググループのARNをベタ書きしています。必要に応じてRef参照するなどしてください。

cloudwatchlog.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: CloudWatch Logs Anomaly Detector

Resources:
  Lambda1LogAnomalyDetector:
    Type: AWS::Logs::LogAnomalyDetector
    Properties:
      DetectorName: lambda-1-log-anomaly-detector-sample
      AnomalyVisibilityTime: 21   # デフォルト値
      EvaluationFrequency: FIFTEEN_MIN
      LogGroupArnList:
        - "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/lambda/lambda-log-test"

なお、WebコンソールからロググループのARNを取得した場合、末尾の「:*」は不要です。

02_cloudwatch_logs_arn

デプロイする

aws cloudformation deploy \
    --template-file cloudwatchlog.yaml \
    --stack-name CloudWatch-Logs-Anomaly-Detector-Stack \
    --capabilities CAPABILITY_NAMED_IAM \
    --no-fail-on-empty-changeset

アクティブになったようです。

11_cloudwatch_anomaly

ロググループに異常検出の情報があった

ロググループに異常検出の情報が追加されていました(トレーニング中)。

12_cloudwatch_log_anomaly

異常ディテクターの一覧を取得する

CloudWatch LogsのWeb画面では、異常ディテクターの一覧表示を探せませんでした(あるかもしれない)。 そのため、AWS CLIで一覧を取得してみます。

$ aws logs list-log-anomaly-detectors

{
    "anomalyDetectors": [
        {
            "anomalyDetectorArn": "arn:aws:logs:ap-northeast-1:123456789012:anomaly-detector:3d0a169e-4bb6-43c3-82b6-671f5129c132",
            "detectorName": "lambda-1-log-anomaly-detector-sample",
            "logGroupArnList": [
                "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/lambda/lambda-log-test"
            ],
            "evaluationFrequency": "FIFTEEN_MIN",
            "anomalyDetectorStatus": "TRAINING",
            "creationTimeStamp": 1701164982343,
            "lastModifiedTimeStamp": 1701164982653,
            "anomalyVisibilityTime": 21
        }
    ]
}

24時間ほど待つ

異常検出がオンになりました。

21_cloudwatch_log_anomaly_on

Lambdaの動作を変更して様子を見る

Lambdaのコードを変更する

危険なワードのERRORログを出力させてみます。

app.py

import json
import logging

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


def lambda_handler(event, context):
    logger.error('ERROR!!!!')
    logger.error('emergency!!!!')
    logger.error('I am very hangry!!!!')
    logger.error('We found unexpected user information.')
    logger.error('There is an inconsistency in the device data.')
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

Lambdaを1分ごとに実行させる

Lambdaの定期実行を15分から1分に変更します。

22_eventbridge_rate1

15分ほど待つと、異常検出に反応がありました!

「予期せぬパターンが重要度ERRORで検出された」的なメッセージが書いてあります。 さきほど追加したERRORログと一致していますね。

31_cloudwatch_anomaly

CloudWatch Logsのログは次のようになっており、ログパターンの「<> <>」が日時とRequestIdを表しているようです。

[ERROR]	2023-11-30T10:38:35.362Z	d0a75715-2b19-4b3d-89ca-436c13821b00	ERROR!!!!
[ERROR]	2023-11-30T10:38:35.362Z	d0a75715-2b19-4b3d-89ca-436c13821b00	emergency!!!!
[ERROR]	2023-11-30T10:38:35.362Z	d0a75715-2b19-4b3d-89ca-436c13821b00	I am very hangry!!!!
[ERROR]	2023-11-30T10:38:35.362Z	d0a75715-2b19-4b3d-89ca-436c13821b00	We found unexpected user information.
[ERROR]	2023-11-30T10:38:35.362Z	d0a75715-2b19-4b3d-89ca-436c13821b00	There is an inconsistency in the device data.

検出された異常を選択すると、パターン検査が表示される

ログのサンプルや、トークンの値が見れました。

32_cloudwatch_anomaly

33_cloudwatch_anomaly

今回、トークンは日時とRequestIdですが、実際の利用を考えると、ユーザIDやデバイスIDといった情報を見れそうです。 怪しいIDなどが閲覧できるのはかなり助かりそうです。

正確か?は、ネガティブ・ポジティブを押して、AWSへのフィードバックだった

41_cloudwatch_anomaly

42_cloudwatch_anomaly

43_cloudwatch_anomaly

押して見ると、フィードバックが送信されました。これはAWSに対するフィードバックでした。

44_cloudwatch_anomaly

さらに「その他のフィードバック」を押すと、次のようによく見るフィードバック画面が表示されました。

45_cloudwatch_anomaly

異常を抑制してみる

アクションでは、異常を抑制できました。

51_cloudwatch_anomaly

52_cloudwatch_anomaly

抑制した異常は、「抑制済み」のタブに移動しました。

53_cloudwatch_anomaly

さいごに

CloudWatch Logsの異常検出をCloudFormationで設定してみました。 ロググループのARNをコピーしてそのまま使うとデプロイ失敗する件でハマりましたが、無事にできました。 追加料金無しで導入できるので、とりあえず有効にして様子を見てみようと思います。

参考