tech.guitarrapc.cóm

Technical updates

AWS CloudWatch Metric Streamを使ったDatadogメトリクス送信とPulumiやTerraformからのCloudFormation Stack呼び出し

DatadogはAWSのCloudWatchメトリクスの取り込みをPull方式とPush方式の両方サポートしています。いわゆるDatadog AWS IntegrationはPull方式でCloudWatchメトリクスを10分程度のレイテンシーで取り込みます。一方で、AWS CloudWatch Metric StreamはPush方式でCloudWatchメトリクスをDatadogに3-5分程度のレイテンシーで取り込みます。

CloudWatch Metric Streamを使ったDatadogへのメトリクス送信について、Datadogが提供するCloudFormation StackをPulumiやTerraformから呼び出すメモです。

2025/03/28 追記

運用後の評価を書きました。

CloudWatch Metric Streamを使ってDatadogにメトリクスを送信するとは

DatadogはCloudWatch Metric Streamを使ったPush方式の記事を出しています。読むとモチベーションや構成が理解できます。記事中の図に加筆した「赤で囲んだ経路がPull方式」「青で囲んだ経路がPush方式」です。

image

Pull方式は、DatadogのAWSアカウントからクローラーでCloudWatch APIをたたく手法です。IAM RoleでDatadog AWSアカウントを許可しつつ権限を渡せば勝手に取り込んでくれる手放し感が便利かつ、DatadogのAWS Integrationから取り込むサービスを絞り込むことができます。AWSコストはCloudWatchの取得にかかり、Cost ExplorerでCW:GMD-Metrics1として表示されます。Datadog自体はAWS Integrationで追加されるメトリクスにコストがかからないのですが、取り込むリージョンやサービスが多ければ多いほどAWS側のCloudWatchコストが増えます。リージョンやサービスは使っているものだけに絞ってコストを減らしましょう。

Push方式は、ユーザーがCloudWatch Metric StreamからFirehoseを経由してHTTP EndpointとしてDatadogにメトリクスを投げ込む手法です。複数のAWSサービスを設定しないといけずユーザーの手間が大きく、DatdogはCloudFormation Stackを提供しています。AWSコストはFirehoseとCloudWatchのメトリクスストリームにかかり、Cost ExplorerでCW:MetricStreamUsageFirehose:AWS-Out-Bytesとして表示されます。Pull方式と違ってメトリクスの平均値だけでなく、「最小、最大、サンプル数、合計」とより多くのメトリクスを収集します。このためリクエスト料金だけ見るとCW:MetricStreamUsageCW:GMD-Metricsの3/10ですが、コストは1.5倍程度を見込むことになります。CWメトリクスストリームで全サービスを対象するのではなく、対象サービスを絞ってコストを減らしましょう。

以上をザクっと表にまとめます。

項目 Pull方式 Push方式 備考
ユーザーが設定するもの IAM Role CloudWatch Metric Stream
Firehose
IAM Role
CloudWatch Logs
S3
公式提供の構築方法 CloudFormation提供 CloudFormation Stack提供
AWSコストのUsageType CloudWatch GMD-Metrics CloudWatch MetricStreamUsage
Firehose AWS-Out-Bytes
サービスやリージョンを絞ることでコストを抑えるとベター
メトリクスの反映遅延 10-15min 3-5min

おおむね理解したところで、CloudWatch Metric Streamを使った仕組みを構築してみましょう。

CloudFormation Stackを使う

先に示した通りPull方式ではIAM Roleでしたが、Push方式は複数のAWSサービスを必要とします。このためDatadogが提供するCloudFormation Stackを使って構築するのが簡単かつ安定です。先に示したCloudWatch Metric Streamを使ったPush方式の記事にCloudFormationで展開する方法が書かれています。

Webから構築するならDatadogコンソール > Integration > AWS > 適当なアカウントを選択 > Metric Collectionの下部を見るとAutomatically Using CloudFormationボタンがあります。

image

リンクをクリックするとCloudFormation Stackの作成画面が開くのでApiKeyRegionsを入力すれば作成できます。

image

IaCからCloudFormation Stackを呼び出す

CloudFormationはいいサービスですが、すでにPulumiやTerraformを使っている場合は「IaCからCloudFormation Stackを呼び出す」とコード管理が一貫性を保てて好ましいでしょう。Pulumi/TerraformはCloudFormation Stackを簡単に呼び出せます。

Pulumi

CloudFormation Stackを呼び出すコードです。ここでは東京リージョン(ap-northeast-1)と米国東部リージョン(us-east-1)からメトリクスを送信する例です。割と素直なので、CloudFormation Stackは普段使っていないなら、IaCとCloudFormationを併用するより運用負荷は小さく感じます。

var config = new Config();
var datadogApiKey = config.RequireSecret("DatadogのAPIKey用のコンフィグキー");

var opt = new CustomResourceOptions();
_ = new Pulumi.Aws.CloudFormation.Stack($"datadog-metricstream-stack", new()
{
    Name = "DatadogMetricStreams"
    TemplateUrl = "https://datadog-cloudformation-stream-template.s3.amazonaws.com/aws/streams_main.yaml",
    Capabilities = ["CAPABILITY_NAMED_IAM"],
    // CloudFormationの定義に合わせて指定する
    Parameters = new InputMap<string>
    {
        { "ApiKey", datadogApiKey },
        { "DdSite", "datadoghq.com" }, // US1
        { "Regions", ["ap-northeast-1", "us-east-1"] },
    }
}, opt);

Terraform

Terraformの場合はaws_cloudformation_stackリソースで定義します。同じAPIで書けます。

resource "aws_cloudformation_stack" "datadog_metricstream_stack" {
  name = "DatadogMetricStreams"
  template_url = "https://datadog-cloudformation-stream-template.s3.amazonaws.com/aws/streams_main.yaml"
  capabilities = ["CAPABILITY_NAMED_IAM"]
  parameters = {
    ApiKey = var.datadog_api_key
    DdSite = "datadoghq.com"
    Regions = ["ap-northeast-1", "us-east-1"]
  }
}

IaCを使ったCloudFormation Stackの注意

CloudFormation Stackを使うのはシンプル、かつほとんどのケースで十分でしょう。ただCloudFormation Stack起因の制約に3点引っ掛かることがあるので注意しましょう。

  • IAM Roleの権限不足
  • テンプレートのメトリクスストリームのInclude/Excludeの設定数上限
  • ParameterのDatadogApiKeyが毎回変更差分と検出

IAM Roleの権限不足

通常は問題ないのですが、エッジケースで確認できています。

テンプレートから生成されるIAM Role DatadogMetricStreamRolelogs:ListTagLogRoupアクションがないため、リソースのタグ変更があったときに、CloudFormationでエラーが起こります。タグ回りで変更があったりすると引っかかり、ロールバックで解消できないため、テンプレートを書き換えるかスタックを作り直すしか回避策がないので注意です。

また、Issueではs3:PutBucketTaggingcloudwatch:TagResourceが足りないケースも報告されています。

ちなみにCloudFormation StackはGitHubで公開されているのでOSS開発っぽくなっています。問題を見つけたならここに修正PRを出せばいいのですが、1年近く取り込みが放置されており、Issueも放置気味なのでちょっと出すのを躊躇しています。

テンプレートのメトリクスストリームのInclude/Excludeの設定数上限

コストを抑えるためにNamespaceを絞ることが難しいです。

Metric Streamのコスト対策は「単純に取り込むNamespaceを絞ること」が第一選択肢ですが、CloudFormationのYAML定義はフィルターを3つしか渡せない作りです。3つ以上設定するには、CloudFormation Stackのテンプレートを手元で管理に切り替えて修正する必要があります。幸いテンプレートは公開されているので、頑張るのもいいでしょう。

ParameterのDatadogApiKeyが毎回変更差分と検出

TerraformのバグがPulumiにも影響を及ぼしています。

Pulumiのバグかと思いきやTerraform由来のバグでした。ワークアラウンドとしてIgnoreChangesするように案内されていますが、IgnoreChangesをこういう用途で使うと「DatadogApiKeyを更新したいときに更新できない状況が起こり、また気づきにくい」です。

問題にならない限りはそれでもいいのですが、忘れたころにやる操作でハマることをが約束されているのはいただけません。困ったものですが、CloudFormation StackをIaCから呼び出すなら運用回避になることを割り切りましょう。

まとめ

Datadogが想定している動作を把握するのは大事なので、CloudFormationから作成してみて動作確認するのはいいことです。ただ、トラブルも確認できているのでCloudFormation定義を丸っとPulumiにポートする記事も別途書きます。

参考


  1. UsageTypeでCloudWatch Serviceを絞り込んでください。GMD-Metrics=Bulk Get Metric Dataを指します。