コンテンツにスキップ

AWS Cost Anomaly Detection (コスト異常検出)

概要

平常時のコストを常時モニタリングし、それまでより消費量が増えた場合に検出・通知をおこなう。アラートは SNS へ通知または定期的なレポートをメールで送信する。アラートは AWS Chatbot と連携することで、整形したメッセージを Slack に通知することができる。

概要

監視単位は以下から選択が可能。

  • AWS のサービス
  • 連結アカウント: AWS Organizations で複数アカウントを管理している場合、アカウント単位で監視
  • コストカテゴリ: AWS Cost Categories を使用して分類している場合、特定のコストカテゴリを指定して監視
  • コスト配分タグ: AWS コスト配分タグ を使用して分類している場合、特定のコスト配分タグを指定して監視

設定

概要

監視対象を「モニター」、通知条件や通知先を「アラートサブスクリプション」として作成し、関連付ける。

設定イメージ (例)

設定イメージ (例)

モニターの作成

  • 管理コンソール > AWS Cost Explorer > コスト異常検出
  • 「コストモニター」タブ
  • 「モニターを作成」
    • モニタータイプ: (監視単位を選択)
    • ※モニタータイプに応じた監視対象の詳細を指定
    • モニター名: (任意)

アラートサブスクリプションの作成

  • 管理コンソール > AWS Cost Explorer > コスト異常検出
  • 「アラートサブスクリプション」タブ
  • 「サブスクリプションの作成」
  • 以下を入力して「サブスクリプションの作成」
    • サブスクリプション名: (任意)
    • アラート頻度: 「個々のアラート」/「日次の要約」/「週次の要約」から選択
    • Amazon SNS ARN の入力: 通知を送信する SNS トピックの ARN (アラート頻度に「個々のアラート」を選択した場合)
    • アラート受信者: 要約メールを送信するあて先のメールアドレス (アラート頻度に「日次の要約」または「週次の要約」を選択した場合)
    • しきい値: 期待されるコストより実際の料金がどの程度大きかった場合に通知するか、金額(USD)または割合(%)で指定 (0 から指定可)
    • コストモニター: 通知対象とするモニターを選択

SNS 通知メッセージ

アラートの通知先とする SNS トピックは予め作成し、Cost Anomaly Detection からの Publish を受信できるよう、トピックのアクセスポリシーに以下を追加しておく。(参考: Creating an Amazon SNS topic for anomaly notifications)

{
  "Statement": [
    ...
    {
      "Sid": "AWSAnomalyDetectionSNSPublishingPermissions",
      "Effect": "Allow",
      "Principal": {
        "Service": "costalerts.amazonaws.com"
      },
      "Action": "SNS:Publish",
      "Resource": "(トピック ARN)",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "(アカウント ID)"
        }
      }
    }
  ]
}

整形したメッセージを Slack に通知したい場合は、AWS Chatbot からこの SNS トピックを Subscribe するのが簡単。

AWS CDK による設定

AWS CDK では以下のように記述できます。

import * as iam from "aws-cdk-lib/aws-iam";
import * as ce from "aws-cdk-lib/aws-ce";

export class CostStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: cdk.StackProps) {
        super(scope, id, props);

        // AlertTopic
        const alertTopic = new sns.Topic(this, "AlertTopic");
        costAlarmTopic.addToResourcePolicy(new iam.PolicyStatement({
            actions: ["sns:Publish"],
            effect: iam.Effect.ALLOW,
            principals: [new iam.ServicePrincipal("costalerts.amazonaws.com")],
            resources: [costAlarmTopic.topicArn],
        }));

        // Cost Anomaly Detection
        const cfnAnomalyMonitor = new ce.CfnAnomalyMonitor(this, "AnomalyMonitor", {
            monitorName: "AWS Services",
            monitorType: "DIMENSIONAL",
            monitorDimension: "SERVICE",

        });
        // 個々のアラート
        new ce.CfnAnomalySubscription(this, "ImmediateSubscription", {
            frequency: "IMMEDIATE",
            monitorArnList: [cfnAnomalyMonitor.attrMonitorArn],
            subscribers: [{
                address: alertTopic.topicArn,
                type: "SNS",
            }],
            subscriptionName: "Anomaly Alert",
            threshold: 0,
        });
        // 日次の要約
        new ce.CfnAnomalySubscription(this, "DailySubscription", {
            frequency: "DAILY",
            monitorArnList: [cfnAnomalyMonitor.attrMonitorArn],
            subscribers: [{
                address: "(あて先メールアドレス)",
                type: "EMAIL",
            }],
            subscriptionName: "Daily Summary",
            threshold: 0,
        });
    }
}