naoketa.net

CloudWatch Metric Streamsを使ってSaaS監視ツールのメトリクス遅延に対処する

February 12, 2023

はじめに

AWSのCloudWatchのメトリクスを、DatadogやNew Relic、Mackerelなどの監視のSaaSに連携する方法について、各種SaaSツールで提供されているAWS Integration系の機能を利用しているとメトリクス連携の遅延やCloudWatchのAPI利用のコストが課題になることがあります。今回はメトリクス遅延の発生する原因と、CloudWatch Metric Streamsを使った対策の一例を紹介します。

各種監視系SaaSのAWS Integration機能の遅延&コスト課題

監視内容によってAWSの情報を前述のような監視系SaaSツールに連携する方法は様々ですが、AWS上の各リソース状況をCloudWatchメトリクス経由でSaaSに連携する場合、SaaSツール側で提供されるAWS Integrationなどの機能を有効化して連携するケースが多いかと思います。このAWS Integration機能では、大半がSaaSツール側から監視対象のAWSアカウントのCloudWatch APIを一定間隔でポーリング実行してメトリクスを取得する方式になっています。

例えばDatadogのAWS Integrationでは、10分ごとにCloudWatchのGetMetricDataなど複数のAPIをポーリングして連携を行っています。

Datadog の AWS インテグレーションは、どのように CloudWatch を使用していますか?
Datadog は CloudWatch モニタリング API を使用して、AWS リソースを監視しています。これらの API の主な使用方法は、GetMetricData エンドポイントを通じて生のメトリクスデータを収集することです。

その他の API は、メトリクスデータを充実させるために使用されます。いくつかの例を挙げます。

- メトリクスに追加するカスタムメトリクスタグを収集する

- 自動ミュートなど、リソースのステータスや 健全性に関する情報を収集する

- ログストリームを収集する
API リクエストの回数と、CloudWatch の使用量はどのように把握できますか?

Datadog は、インストールした各 AWS サブインテグレーションについて、利用可能なメトリクスを 10 分ごとに収集します。特定のサブインテグレーション (SQS、ELB、DynamoDB、AWS カスタムメトリクス) に対して多数の AWS リソースを持っている場合、AWS CloudWatch の請求に影響を与える可能性があります。

上記の公式ページのFAQにも記載がありますが、上記のような方式のため以下の課題があります。

  • メトリクス連携の遅延
    • 一定間隔でのAPIポーリングする方式のため、対象のSaaSツール上に実際のメトリクスが連携されるまで、AW上の対象リソースからCloudWatchに連携される時間に加えてAPIポーリング間隔分の時間が遅延する。
  • CloudWatchのコスト増加
    • 複数リソースに対して定期的にCloudWatchの各種APIを実行するため、CloudWatchの請求額が増加

特にメトリクス連携の遅延は、監視対象のメトリクスによっては検知アラートや対応が遅れてしまうことに繋がるため、対処したいケースが多いかと思います。

CloudWatch Metric StreamsとKinesis Data Firehose経由でメトリクスを連携する

上記のような課題への対処方法として、SaaS側からCloudWatch APIをポーリングする方法ではなく、AWS側からSaaS側にストリームで流し込む方式により改善が見込めます。具体的には以下のようにCloudWatchのメトリクスをCloudWatch Metric Streams及びKinesis Data Firehoseを使ってStreamでSaaS側のHTTPエンドポイントに流し込むようなイメージとなります。

システム構成

Datadogではこの構成のスタックを作成するCloudFormationを提供しています。今回はDatadogやAWSの各種リソースをすでにTerraformで管理しているケースを想定して、Terraformでの実装イメージを紹介します。なお事前にTerraform上でのAWS Providerの設定ができていることを想定しています。

まずCloudWatch Metric Streamsについては、以下のようなイメージになります。include_filterはmetric filterを使う場合namespaceを必要に応じて設定してください。

resource "aws_cloudwatch_metric_stream" "datadog" {
  name          = "datadog-stream"
  role_arn      = aws_iam_role.metric_stream_to_firehose.arn
  firehose_arn  = aws_kinesis_firehose_delivery_stream.datadog_stream.arn
  output_format = "opentelemetry0.7"

  # 必要があれば設定
  include_filter {
    namespace = "AWS/EC2"
  }
}

# https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-metric-streams-trustpolicy.html
data "aws_iam_policy_document" "metric_stream_to_firehose" {
  statement {
    effect = "Allow"

    actions = [
      "firehose:PutRecord",
      "firehose:PutRecordBatch",
    ]

    resources = [aws_kinesis_firehose_delivery_stream.datadog_stream.arn]
  }
}

destinationにはhttp_endpointを設定して、Datadogの設定を行います。

resource "aws_kinesis_firehose_delivery_stream" "datadog_stream" {
  name        = "cw-to-datadog-stream"
  destination = "http_endpoint"

  http_endpoint_configuration {
    name       = "Datadog"
    access_key = var.datadog_api_key // Datadog APIキーを発行して設定
    role_arn   = aws_iam_role.datadog_firehose.arn
    url        = var.datadog_firehose_endpoint // Datadog側から確認して設定
    request_configuration {
      content_encoding = "GZIP"
    }
  }
}

さいごに

今回はCloudWatch Metric StreamsとKineis data Firehoseを使ってSaaS監視ツールのメトリクス遅延に対処する方法をTerraformのコード例とともに紹介しました。今回のStreamで流し込むことで、Datadogで10-15分程度の遅延が発生していたCloudWatchメトリクスの連携が、ほぼリアルタイムでDatadog側に連携することができました。


© 2024, Built with Gatsby by Naoki Tazawa