AWS

CloudWatchのクロスアカウントオブザーバビリティをCDKで実装する

yun

AWSでシステムを構築する際、複数のアカウントを組み合わせて利用するケースはよくあります。
このような場合、監視のダッシュボードや通知を一つのアカウントに集約したいというニーズがあると思います。
CloudWatchの監視をアカウント間で共有するための機能がいくつか用意されていますが、今回はクロスアカウントオブザーバビリティをCDKで実装していきます。

クロスアカウントオブザーバビリティとは

AWSドキュメントのCloudWatch のクロスアカウントオブザーバビリティに詳しい説明がありますが、CloudWatchの機能の一つで、設定することで以下の監視情報を監視アカウントに集約することができます。

  • Amazon CloudWatch のメトリクス
  • Amazon CloudWatch Logs のロググループ
  • AWS X-Ray のトレース
  • Amazon CloudWatch Application Insights のアプリケーション
  • CloudWatch Internet Monitor でのモニタリング

集約する監視アカウントを「モニタリングアカウント」、集約されるアカウントを「ソースアカウント」といい、モニタリングアカウントには最大で100,000個のアカウントを集約でき、ソースアカウント側は最大5個のアカウントにデータを共有できます。

アカウントをリンクする方法として、指定したOrganizationsに所属するアカウントをリンクする方法と、任意のアカウントで設定する方法の大きく2つが存在します。

Organizationsを利用する方法では、モニタリングアカウントアカウントの設定のみで完了できます。
今回は任意のアカウントをリンクする方法を取り上げます。

コンソール上で設定してみる

モニタリングアカウント


CDKで実装する前にコンソールでの操作を見ていきます。
まずはモニタリングアカウントからです。

CloudWatch > 設定を開きます。

「モニタリングアカウント設定」の「設定」をクリック。

モニタリングアカウントアカウント設定画面。
すべて入力必須です。

「データを選択」で共有させたいデータを選択することができます。
この後のソースアカウントの設定でも同様の選択設定があるので、「全体としては全部集約したいけど、このソースアカウントAについてはメトリクスだけ共有したい」みたいな設定も可能です。

「ソースアカウントを一覧表示」に設定するソースアカウントの情報をカンマ区切りで入力します。
今回は任意のアカウントをリンクさせたいため、アカウントIDを入力します。

「アカウントラベル」では、モニタリングアカウント上で各ソースアカウントにつけるラベルを設定できます。
アカウント名、グローバルに一意のEメールアドレス、ドメインなしのEメール、カスタムラベルから選択ができます。
カスタムラベルを選択する場合、ラベル値の設定も追加で必要になります。
今回はアカウント名を使用します。

最後に表示されている通り、CloudWatchはリージョン毎のサービスになるため、複数リージョンで実施したい場合は別途設定が必要です。

すべての設定が完了したら「設定」をクリックします。

設定画面に戻ってくるので、続けて「アカウントをリンクするためのリソース」をクリックします。

今回は任意のアカウントを設定します。
リンクの方法として2つ提示されています。どちらを利用しても構いません。
CloudFormationテンプレートを利用した場合は、リンクアカウントでダウンロードしたファイルをテンプレートファイルとしてアップロードして進めます。
今回はURLを使った方法を見ていきます。

リンクアカウント

リンクアカウントとしたいアカウントにログインし、コピーしたURLに移動します。

モニタリングアカウントの設定で見た画面と似たような画面が表示されます。
提供されたリンクを使用した場合、必要な情報はデフォルトで入力されています。

「データを選択」で改めて共有するデータをソースアカウント側で指定します。

「シンクARN」はモニタリングアカウントで提供されたURLを使った場合は自動で入力されています。
「アカウントラベル」はモニタリングアカウントで設定したものと同様です。

設定を確認したら「リンク」をクリックします。
アクセス許可の確認画面が出てきますので、問題なければ「確認」と入力して続行します。
CloudWatchの設定画面に戻ってきたらリンクアカウントの設定は完了です。モニタリングアカウントに戻って確認してみましょう。

リンクを確認する

モニタリングアカウントのCloudWatch > 設定に移動し、「モニタリングアカウントを管理」をクリックします。

ソースアカウントに設定したアカウントが表示されている。

実際にデータが共有されているかも確認します。
EC2のメトリクスを確認してみます。

別アカウントのインスタンス名は取得できないため、ソースアカウントのインスタンス名は「名前が指定されていません」と表示されますが、ソースアカウントのメトリクスもモニタリングアカウントと同様に表示されるようになりました。

CDKで実装する

クロスアカウントオブザーバビリティの概要が分かったところで、CDKで実装してみます。

CDKではaws_oamモジュールにありますが、L2コンストラクトがまだ用意されていないので、L1で実装することになります。
モニタリングアカウント側はCfnSink、リンクアカウント側はCfnLinkを実装します。

モニタリングアカウント

CfnSinkのpropsはnamepolicy?tags?のみです。
つまりモニタリングアカウントの設定はIAMポリシードキュメントとして実装することになります。

実は、コンソールで設定したときにもポリシーが作成されています。「モニタリングアカウントを管理」 > 「設定ポリシー」 から確認することができます。
上で行った設定では以下のポリシーが作成されていました。

{
  "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
       "Principal": {"AWS": "<em>アカウントID</em>"},
            "Action": ["oam:CreateLink", "oam:UpdateLink"],
            "Resource": "*",
            "Condition": {
                "ForAllValues:StringEquals": {
                    "oam:ResourceTypes": [
                        "AWS::Logs::LogGroup",
                        "AWS::CloudWatch::Metric",
                        "AWS::XRay::Trace",
                        "AWS::ApplicationInsights::Application",
                        "AWS::InternetMonitor::Monitor"
                    ]
                }
            }
        }
    ]
}

AWS CloudFormationのドキュメントにサンプルがありますので、これを元に実装します。
なお、今回はTypeScriptで実装しています。

const crossAccountObservabilitySink = new oam.CfnSink(
  this,
  "CrossAccountObservabilitySink",      
  {
    name: "cross-account-observability-sink",
    policy: {
      Version: "2012-10-17",
      Statement: [
        {
          Effect: "Allow",
          Resource: "*",
          Action: "oam:*",
          Principal: {
            AWS: [
              "1111111111111",
              "2222222222222",
              "3333333333333",
            ],
          },
          Condition: {
            "ForAllValues:StringEquals": {
              "oam:ResourceTypes": [
                "AWS::CloudWatch::Metric",
                "AWS::Logs::LogGroup",
                "AWS::XRay::Trace",
                "AWS::ApplicationInsights::Application",
                "AWS::InternetMonitor::Monitor",
              ],
            },
          },
        },
      ],
    },
  }
);

// ARNを出力
new cdk.CfnOutput(this, "SinkArn", {
  value: crossAccountObservabilitySink.attrArn,
  description: "Sink Arn",
});

ARNはCfnLinkで必要になるので出力していますが、クロススタック参照でcrossAccountObservabilitySinkを参照できるのであれば不要です。CDKの構成に合わせて対応してください。

リンクアカウント

CfnLinkのpropsはresourceTypessinkIdentifierlabelTemplate?linkConfiguration?tags? です。
linkConfigurationはメトリクスやロググループの一部のみを共有したい場合に設定できるフィルターとなるので、必要に応じて設定してください。

こちらもサンプルがあるので、参考に実装します。

new oam.CfnLink(
  this,
  "CrossAccountObservabilityLink",
  {
    resourceTypes: [
      "AWS::CloudWatch::Metric",
      "AWS::Logs::LogGroup",
      "AWS::XRay::Trace",
      "AWS::ApplicationInsights::Application",
      "AWS::InternetMonitor::Monitor",
    ],
    sinkIdentifier: "arn:aws:oam:ap-northeast-1:999999999999:sink/EXAMPLE-206d-4daf-9b42-1e17d5f145ef",
    labelTemplate: "$AccountName",
  }
);

モニタリングアカウントで作成したcrossAccountObservabilitySink を参照できる場合はsinkIdentifiercrossAccountObservabilitySink.attrArnを指定します。

デプロイ後、モニタリングアカウントのコンソール上でリンクアカウントのデータが確認できれば完了です。お疲れ様でした。

参考

AUTHOR
yun
yun
記事URLをコピーしました