他アカウント上の CloudWatch メトリクスを参照する CloudWatch Alarm を CloudFormation で作ってみた

CloudWatch のクロスアカウント設定をしている場合、他アカウント上のメトリクスを参照する CloudWatch Alarm を作成することができます。CloudFormation を利用して他アカウントのメトリクスを参照するアラームを作成する場合、少し記法が異なるためブログに残していきます。
2022.07.07

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

こんにちは、大前です。

最近、CloudFormation を利用して他アカウントの CloudWatch メトリクスを参照する CloudWatch Alarm を作成する機会がありました。

CloudFormation で他アカウントのメトリクスを参照する CloudWatch Alarm を作成する際には記法が少し違ったため、実際の CloudFormation テンプレートなどを残しておきたいと思います。

前提知識

CloudWatch ではクロスアカウント設定を行うことによって、他アカウント上の CloudWatch メトリクスを参照したり、他アカウント上の CloudWatch メトリクスを利用した CloudWatch ダッシュボードを作成したりすることができます。

今回実施する他アカウントの CloudWatch メトリクスを参照する CloudWatch Alarm 作成は、上記のクロスアカウント設定が済んでいる状態であることを前提としています。

全体像

先述の通り、CloudWatch のクロスアカウント連携は実施済みであるものとします。

以下の図の CloudWatch Alarm 部分を CloudFormation で作成します。CloudWatch Alarm 自体は左側のアカウント A 上に作成しますが、Alarm が参照するメトリクスは右側のアカウント B 上のメトリクスになります。

作成した CloudFormation テンプレート

早速ですが、今回作成した CloudFormation テンプレートは以下です。利用するメトリクスはなんでも良いのですが、S3 の BucketSizeBytes に対するアラームを設定するようなテンプレートになっています。アラート発生時などのアクションは定義していませんので、用途に応じて追記してご利用ください。

AWSTemplateFormatVersion: "2010-09-09"
Description: "Create CloudWatch Alarm(Cross Account)"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
  CloudWatchAlarm01:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      ActionsEnabled: true
      AlarmName: "blog-cross-account-alarm"
      AlarmDescription: "cross account alarm."
      Metrics: 
        - AccountId: "111122223333"
          Id: "id_01"
          MetricStat: 
            Metric: 
              Dimensions: 
                - Name: "StorageType"
                  Value: "StandardStorage"
                - Name: "BucketName"
                  Value: "xxxxx"
              MetricName: "BucketSizeBytes"
              Namespace: "AWS/S3"
            Period: 86400
            Stat: "Average"
          ReturnData: true
      ComparisonOperator: "GreaterThanThreshold"
      Threshold: 100
      EvaluationPeriods: 1


参照するメトリクスが存在する他アカウントの ID は Metrics > AccountId にて指定します。

(中略)
      Metrics: 
        - AccountId: "111122223333"
(中略)


指定するメトリクスに関する詳細は Metrics > MetricStat > Metric 配下に指定します。

(中略)
      Metrics: 
        - AccountId: "111122223333"
          Id: "id_01"
          MetricStat: 
            Metric: 
              Dimensions: 
                - Name: "StorageType"
                  Value: "StandardStorage"
                - Name: "BucketName"
                  Value: "xxxxx"
              MetricName: "BucketSizeBytes"
              Namespace: "AWS/S3"
            Period: 86400
            Stat: "Average"
          ReturnData: true
(中略)


上記テンプレートを実行すると、下記の様な CloudWatch Alarm が作成されます。他アカウントのメトリクスを参照している場合、「アカウント ID」で参照先の他アカウントの ID が表示されているのが特徴的です。

(おまけ)アカウント ID を指定せず他アカウントのメトリクスを指定するとデータ不足になる

下記の様に、Metrics > MetricStat > Metric 配下ではなく、Properties 直下の MetricName パラメータなどを利用して、他アカウントのメトリクスを指定してみます。当然、上に記した記法をしないと他アカウントの ID を指定する箇所がないのでおかしなことになるのは予想できるかと思いますが、これで CloudFormation スタックを作成してみます。

CloudWatchAlarm02:
	Type: "AWS::CloudWatch::Alarm"
	Properties:
		ActionsEnabled: true
		AlarmName: "blog-cross-account-alarm 02"
		AlarmDescription: "cross account alarm."
		MetricName: "BucketSizeBytes"
		Namespace: "AWS/S3"
		Dimensions:
			- Name: "StorageType"
				Value: "StandardStorage"
			- Name: "BucketName"
				Value: "xxxxx"
		Statistic: "Average"
		ComparisonOperator: "GreaterThanThreshold"
		Threshold: 100
		Period: 86400
		EvaluationPeriods: 1


CloudFormation 自体の実行は成功し CloudWatch Alarm は作成されますが、"データ不足" の状態になりました。他アカウントの ID を指定していないのでローカルのアカウント上に対してメトリクスを探すが、当然他アカウント上のメトリクスを指定しているのでメトリクスが見つからず、"データ不足" 状態になっているのだと思われます。

おわりに

CloudWatch のクロスアカウント連携を設定している状態で、他アカウント上のメトリクスを参照する CloudWatch Alarm を CloudFormation で作成してみました。クロスアカウント連携をしている場合は他アカウントのメトリクスを参照する CloudWatch Alarm を作成したいケースもあるかと思います。

ブログにしてしまうとなんてことはない内容ですが、CloudWatch Alarm に関する CloudFormation ドキュメントを深掘っていかないと気づき辛い記法だと感じました。

以上、AWS 事業本部の大前でした。

参考