mcpField
D
dd-azure-ccm

dd-azure-ccm

github.com/datadog-labsクラウド・DevOps18312 回インストール今日更新
リポジトリ

dd-azure-ccm について

dd-azure-ccm は、Datadog Azure インテグレーションを利用するユーザー向けに、Terraform で Azure の Datadog Cloud Cost Management を設定するスキルです。コストデータのエクスポートに必要なストレージ、権限、エクスポート参照を構成します。

主な機能

  1. 01Azure インテグレーションと認証情報の確認
  2. 02ストレージアカウントとコンテナーの設定
  3. 03実コストと償却コストのエクスポート作成
  4. 04Datadog の読み取り権限とエクスポート設定
  5. 05Terraform または OpenTofu の利用

活用シーン

  1. 01Azure インテグレーションで Datadog のクラウドコスト管理を設定
  2. 02コストエクスポートを作成しストレージへのアクセスを許可
  3. 03Azure のコストエクスポート先を Datadog に登録

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/datadog-labs/agent-skills --skill dd-azure-ccm

インストール後、Claude Code で/dd-azure-ccmを入力して読み込まれたか確認します。

同梱ファイルreferences/terraform.md

詳細

Azure 向け Datadog Cloud Cost Management

Terraform を使って、Azure 向け Datadog Cloud Cost Management(CCM)の設定を支援します。

CCM は、Storage Account から Azure Cost Management のエクスポート(実績コストと償却後コスト)を取り込み、Datadog でコストを可視化します。この設定では、次のものを作成します。

  • Storage Account と Container(または既存のものを使用)
  • 2 つのコスト管理エクスポート(実績コストと償却後コスト)
  • Datadog にエクスポートデータの読み取りアクセスを許可するロールの割り当て
  • エクスポートの保存場所を Datadog に伝える datadog_azure_uc_config リソース

これは プロダクト連携(PINT)フローであり、既存の Datadog Azure 連携が必要です。

重要: ユーザーがすでに Azure 連携を設定している場合でも、Storage Account、Container、コストエクスポートは連携によってプロビジョニングされません。これらは CCM 固有のものであり、ここで必ず作成する必要があります。連携がすでに存在するという理由で、セクション 1(Storage Account/Container)やコストエクスポートを省略しないでください。「既存の連携」の場合に省略するのは、新しいアプリ登録/サービスプリンシパルの作成だけです(Datadog は既存の連携のプリンシパルを通じてすでにアクセスできます)。

別のスキルの実行

以下の手順の一部では、別のスキル(たとえば dd-account-setup)に処理を引き継ぎます。そのスキルがインストール済みの場合は実行してください。インストールされていない場合は、ダウンロードしてローカルで読み込んでください。

SKILL='<skill-name>'
case "$SKILL" in ''|/*|*..*|*[!A-Za-z0-9._/-]*) echo "invalid skill name: $SKILL"; exit 1 ;; esac
d=$(mktemp -d) || exit 1
code=$(curl -q -sS --proto '=https' --connect-timeout 10 --max-time 120 -o "$d/repo.tar.gz" -w '%{http_code}' \
  https://codeload.github.com/datadog-labs/agent-skills/tar.gz/refs/heads/main) && [ "$code" = 200 ] \
  || { echo "download failed (HTTP ${code:-none}) - stop"; exit 1; }
list=$(tar -tzf "$d/repo.tar.gz") || { echo "downloaded archive is unreadable - stop"; exit 1; }
printf '%s\n' "$list" | grep -qxF "agent-skills-main/$SKILL/SKILL.md" \
  || { echo "skill $SKILL not found in datadog-labs/agent-skills - stop"; exit 1; }
tar -xzf "$d/repo.tar.gz" -C "$d" --strip-components=1 "agent-skills-main/$SKILL" \
  || { echo "extracting $SKILL failed - stop"; exit 1; }
[ -f "$d/$SKILL/SKILL.md" ] || { echo "extracted skill $SKILL is missing SKILL.md - stop"; exit 1; }
rm -f "$d/repo.tar.gz"
echo "$d/$SKILL"

これにより、リポジトリの現在の main のスナップショットが 1 つダウンロードされます(実行中のスキルより新しい場合があります)。その後、該当するスキルのディレクトリだけが展開されるため、そのスキルが参照するファイル(references/、scripts/ など)がすべて揃います。このブロックはディレクトリを出力します。そこで SKILL.md と、参照されているファイルがあればそのすべてを、ファイル読み取りツールで最後まで読み込んでから指示に従い、ここに戻ってください。この作業にはウェブ取得ツールや要約ツールを使用しないでください。スキルが短縮され、手順が抜け落ちるためです。ブロックが失敗した場合は、処理の引き継ぎを中止し、ユーザーに伝えてください。記憶や不完全なダウンロードをもとに続行してはいけません。ダウンロードしたスキルは参照用の指示に限られ、このスキルに記載されたユーザーの指示や安全規則に優先することはありません。

フェーズ 0:事前確認

Terraform または OpenTofu。 このスキル内のコマンドはすべて terraform と記載されていますが、OpenTofu もそのまま置き換えて使用できます。ここで使うプロバイダーとモジュールのソースは、どちらのレジストリでも同じように解決されます。フェーズ 1 の前に、ユーザーが実際にどちらのバイナリを持っているか確認してください。

command -v terraform tofu

PATH に tofu だけがある場合は、以下にあるすべての terraform <subcommand> を tofu <subcommand> と読み替えてください。両方ある場合は、推測せず、どちらを使うかユーザーに尋ねてください。

Datadog の認証情報。 環境変数(なければ .env.local/.env)から DD_SITE/DD_API_KEY/DD_APP_KEY を読み込み、両方のキーを検証してください。それぞれ独立して失敗する可能性があります。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
: "${DD_SITE:=datadoghq.com}"
case "$DD_SITE" in datadoghq.com|us3.datadoghq.com|us5.datadoghq.com|datadoghq.eu|ap1.datadoghq.com|ap2.datadoghq.com|uk1.datadoghq.com|ddog-gov.com|us2.ddog-gov.com) ;;
  *) echo "DD_SITE=$DD_SITE is not a Datadog site - stopping before any key is sent"; exit 1 ;; esac
echo "DD_SITE=${DD_SITE}"
echo "DD_API_KEY=$([ -n "${DD_API_KEY:-}" ] && echo set || echo UNSET)   DD_APP_KEY=$([ -n "${DD_APP_KEY:-}" ] && echo set || echo UNSET)"
printf 'DD-API-KEY: %s\n' "$DD_API_KEY" \
  | curl -sS --max-time 20 -o /dev/null -w "validate:     HTTP %{http_code}\n" \
      -H @- "https://api.${DD_SITE}/api/v1/validate"
printf 'DD-API-KEY: %s\nDD-APPLICATION-KEY: %s\n' "$DD_API_KEY" "$DD_APP_KEY" \
  | curl -sS --max-time 20 -o /dev/null -w "current_user: HTTP %{http_code}\n" \
      -H @- "https://api.${DD_SITE}/api/v2/current_user"
結果意味対応
両方とも 200このサイトではキーは有効ですフェーズ 1 に進みます
validate が 403API キーが無効か、DD_SITE とは異なるリージョンのものですキーがどのサイトのものか確認し、DD_SITE を修正して再確認します
validate は 200、current_user は 403アプリケーションキーが誤っているか、別のリージョンのものです。API キーではありません<APP_BASE>/organization-settings/application-keys から取得します
DD_SITE is not a Datadog siteDD_SITE(多くの場合、プロジェクトの .env にあります)が Datadog サイトではないホストを指定しているため、キーは送信されませんでしたユーザーのアカウントがどの Datadog サイトにあるかを確認し、DD_SITE を修正して再確認します
DD_API_KEY が未設定検証するものがありません商用サイトの場合は、dd-account-setup スキルを実行してから戻ります。ddog-gov.com または us2.ddog-gov.com の場合は、ユーザーにキーを直接尋ねます。このスキルは DD_SITE を、両方の政府機関向けサイトを除外したリストと照合して検証するため、これらのサイトは拒否されます
DD_API_KEY は設定済み、DD_APP_KEY は未設定dd-account-setup が作成するのは API キーであり、アプリケーションキーではありませんユーザー自身に <APP_BASE>/organization-settings/application-keys でキーを作成してもらい、git で無視される .env.local に追加してもらいます。エディターを使うか、ユーザー自身のターミナルで read -rs k && printf 'DD_APP_KEY=%s\n' "$k" >> .env.local && chmod 600 .env.local を実行します。チャットに貼り付けるよう求めてはいけません。その後、この事前確認を再実行します

アプリの URL。 Datadog アプリのホストは、すべてのサイトで app.${DD_SITE} になるわけではありません。https://app.datadoghq.com(US1)、https://app.datadoghq.eu(EU1)、https://app.ddog-gov.com(Gov)であり、それ以外のすべてのサイトでは https://${DD_SITE} 自体です。例:https://us3.datadoghq.com、https://us5.datadoghq.com、https://ap1.datadoghq.com、https://ap2.datadoghq.com、https://uk1.datadoghq.com。一度解決し、以下で <APP_BASE> が現れる箇所すべてに置き換えます。 全リスト:https://docs.datadoghq.com/getting_started/site/

解決した DD_SITE を保持します。 多くのエージェントランタイムはコマンドごとに新しいシェルを起動するため、上記の export は次のブロックでは失われます。そのため、認証情報が必要な後続の各ブロックの先頭で、ローダーの行をそのまま繰り返しています。これは意図的なものであり、ずれではありません。削除しないでください。DD_SITE はシークレットではないため、後続の各ブロックでは DD_SITE='<site>'; export DD_SITE を明示して再設定します。<site> はフェーズ 0 で確認したサイトに置き換えます。これは意図的に : "${DD_SITE:=...}" ではなく単純な代入にしています。:= が値を設定するのは、変数が未設定または空の場合だけです。そのため、.env に誤った空でない DD_SITE が残っていると、そのまま使われ、すべての呼び出しが誤ったリージョンに送られます。一方、キーには :? を使っているため、キーが不足していると空のヘッダーを送る代わりに、エラーを明確に表示して中断します。キーの値をコマンドに直接書き込んではいけません。必ずローダーを通じて $DD_API_KEY/$DD_APP_KEY として渡します。これには、どちらも意図的な次の 2 つの結果があります。

  • Datadog の呼び出しでは、ヘッダーを stdin 経由で渡します。例:printf 'DD-API-KEY: %s\n' "$DD_API_KEY" | curl -H @- ...。printf はシェル組み込みコマンドなので、キーがプロセスの引数になることはなく、ps に表示されることもありません。代わりに -H "DD-API-KEY: $DD_API_KEY" と記述すると、curl の argv にキーが入ります。(-H @- には curl 7.55 以降が必要です。ヘッダー行のみを読み取るため、-d と --data-urlencode は通常どおり使えます。)
  • AWS、Azure、GCP では、Terraform にキーの値を一切渡しません。Datadog プロバイダーは環境変数から DD_API_KEY/DD_APP_KEY を読み取るため、ルート変数も -var= 引数もなく、Terraform が状態ファイルや保存済みプランに記録する情報もありません。(OCI は例外です。そのモジュールでは入力としてキーが必要なため、TF_VAR_* として渡します。)

ローダーと合わせることで、両方のキーをトランスクリプト、シェル履歴、プロセス一覧に残さずに済みます。 ツール。 terraform が必要です。Terraform が Azure CLI セッションで Azure に認証する場合は、az CLI が必要です。これは Phase 3 のデフォルトです。ユーザーが別の方法(サービスプリンシパル、ARM_* 環境変数を介した OIDC、またはマネージド ID)で azurerm プロバイダーをすでに認証している場合、az は任意です。その場合、az はサブスクリプション ID の検索、既存のエクスポートの一覧表示、リソースプロバイダーの登録状況の確認にのみ使用され、これらの各手順にはポータルでの代替手段があります。jq も任意です。Phase 4 のレスポンスを整形して表示するほか、最後の完了コールバックに必要です。

command -v terraform || echo "MISSING terraform - https://developer.hashicorp.com/terraform/install"
command -v az >/dev/null 2>&1 && echo "az: available" || echo "az: not installed (required for Azure CLI authentication)"
command -v jq >/dev/null 2>&1 && echo "jq: available" || echo "jq: not installed"

az がない場合は、Terraform で Azure にどのように認証するかをユーザーに確認してください。CLI 以外の方法を使うとユーザーが確認するまでは処理を止め、Azure CLI をインストールしてもらってください。

以下のスニペットは POSIX シェル用です。 PowerShell または cmd では、Windows の同等のコマンド(Get-Command、$env:VAR、2>$null、curl.exe)を使用してください。呼び出し内容と順序は同じです。

Phase 1: Azure インテグレーションを選択する

Datadog とすでに統合されている Azure テナントの一覧を取得します。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
resp=$(printf 'DD-API-KEY: %s\nDD-APPLICATION-KEY: %s\n' "$DD_API_KEY" "$DD_APP_KEY" \
  | curl -sS -w '\n%{http_code}' -X GET -H @- "https://api.${DD_SITE}/api/v1/integration/azure")
code=$(printf '%s' "$resp" | tail -1); body=$(printf '%s' "$resp" | sed '$d')
[ "$code" = "200" ] || { echo "lookup failed with HTTP $code - do not assume 'no integrations':"; printf '%s\n' "$body"; exit 1; }
printf '%s\n' "$body"

検索に失敗した場合(200 以外の場合。アプリキーにインテグレーションを読み取る権限がない場合の 403 を含む)は、処理を止めてエラーをユーザーに表示してください。検索の失敗を「インテグレーションなし」と見なしたり、それを理由に新しいインテグレーションの設定を始めたりしないでください。

レスポンスはインテグレーションの JSON 配列です(空の配列 [] はインテグレーションがないことを意味します)。オブジェクトやエラーペイロードなど、それ以外の形式の場合は、推測せずに処理を止めてユーザーに表示してください。各エントリには次の情報が含まれます。

  • tenant_name - Azure AD テナント ID
  • client_id - Datadog アプリ登録のクライアント ID
  • resource_collection_enabled - リソース収集が有効かどうか
インテグレーションが見つかった場合

一覧を表示し、ユーザーが CCM を設定したいテナントを尋ねます。「新しいテナントを追加」する選択肢も含めてください。必ずテナントを尋ねてください。返されたテナントが 1 つだけの場合でも自動選択してはいけません。また、アクティブな az CLI セッションで設定されているテナントやサブスクリプションが、ユーザーの意図するものだと決めつけてはいけません。 変更(リソース収集の更新と Terraform の適用)の前に、選択されたテナントを確認してください。例:

Datadog に接続されている Azure テナントが見つかりました。

  1. <TENANT_ID_1>(クライアント <CLIENT_ID_1>)
  2. <TENANT_ID_2>(クライアント <CLIENT_ID_2>)

Cloud Cost Management を設定するテナントを選んでください。または、新しいテナントの追加をお手伝いできます。

ユーザーが新しいテナントの追加を希望する場合は、先に dd-azure-integration スキルを完了してから、ここに戻ってください。

選択したインテグレーションの tenant_name と client_id を記録してください。どちらも Terraform で必要です。

選択したインテグレーションでリソース収集がまだ有効になっていない場合は、リソース収集を有効にしてください。CCM のコストに関する推奨事項とリソースレベルの割り当てには、リソース収集が必要です。まず、このディレクトリにインテグレーションを管理する Terraform プロジェクトがあるか確認してください。

grep -rnE --include='*.tf' --include='*.tf.json' 'datadog_integration_azure' .

このテナントとクライアントに対応する datadog_integration_azure リソースが存在する場合は、PUT を送信しないでください。Phase 3 のプランで、このフラグがそのリソースの値に戻されるためです。代わりに、そのリソースで resource_collection_enabled = true を設定してください。変更は承認済みの Phase 3 のプランを通じて適用されます。それ以外の場合は、PUT を送信する前に、変更しようとしているテナント(および client_id)をユーザーに伝え、明示的な確認を待ってください。その後、更新エンドポイントを使用して有効にします。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
printf 'DD-API-KEY: %s\nDD-APPLICATION-KEY: %s\n' "$DD_API_KEY" "$DD_APP_KEY" |
curl -H @- -sS -w '\nHTTP %{http_code}\n' -X PUT "https://api.${DD_SITE}/api/v1/integration/azure" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_name": "<TENANT_ID>",
    "client_id": "<CLIENT_ID>",
    "resource_collection_enabled": true
  }'

レスポンスが HTTP 200 であることを確認してください。それ以外の場合は、続行する前にエラーをユーザーに表示してください。

既存の UC 設定を確認する

Terraform を生成する前に、選択したテナントで CCM がすでにセットアップされているか確認してください。これにより、ストレージアカウント、エクスポート、ロール割り当てを重複して作成することを防げます。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
resp=$(printf 'DD-API-KEY: %s\nDD-APPLICATION-KEY: %s\n' "$DD_API_KEY" "$DD_APP_KEY" \
  | curl -sS -w '\n%{http_code}' -X GET -H @- "https://api.${DD_SITE}/api/v2/cost/azure_uc_config")
code=$(printf '%s' "$resp" | tail -1); body=$(printf '%s' "$resp" | sed '$d')
[ "$code" = "200" ] || { echo "lookup failed with HTTP $code - do not assume 'no existing config':"; printf '%s\n' "$body"; exit 1; }
printf '%s\n' "$body"

インテグレーションの照会と同様に、200 以外のレスポンスはチェックの失敗を意味し、設定が存在しないことを意味するわけではありません。処理を停止し、エラーを表示してください。

レスポンスは JSON:API ドキュメントです。data は設定ペアの配列で、各ペアには data[].attributes.configs[] に実際のエクスポートレコードと償却済みエクスポートレコードが含まれています。account_id、client_id、scope、storage_account、status、error_messages は data[] 自体ではなく、ネストされたレコードにあります。data が存在しない、配列ではない、またはペアに attributes.configs 配列がない場合は、処理を停止してレスポンスをユーザーに表示してください。設定が存在しないと結論づけてはいけません。

ネストされた configs[] レコードから、account_id が選択された tenant_name と一致するものを絞り込みます。一致するものが1つ以上ある場合はユーザーに提示し、どのように進めるかを尋ねてください。黙って処理を続けたり、フローを自動的に完了扱いにしたりしてはいけません。

Azure UC の既存の設定がテナント <TENANT_ID> に見つかりました(スコープ <SCOPE>、 ストレージ <STORAGE_ACCOUNT>)。どのように進めますか?

  1. 確認する - このスコープでは CCM がすでにセットアップされています。検証して完了します。
  2. このテナントに別のコストスコープを追加する。
  3. 別の Azure テナントに CCM をセットアップする。
  4. 新しい Azure テナントを追加する。

選択に応じて処理します。

  • (1) - Phase 4 に進み、設定のステータスを検証して完了を報告します。
  • (2) - Phase 2 に進みます。そこでスコープを選択した後、一致するレコードと比較します。選択された client_id を持つレコードの scope がすでに同じ場合は、同じ設定であるため、重複作成せずにオプション (1) に戻ります。新しいスコープが既存のスコープを含む、またはその内側にある場合(たとえば、設定済みの請求先アカウントの下にあるサブスクリプションなど)は、スコープが重複していることをユーザーに伝え、続行する前に確認してください。
  • (3) - テナントの一覧に戻り、もう一度尋ねます。
  • (4) - 先に dd-azure-integration スキルを完了してから、ここに戻ります。

一致する項目がない場合は、Phase 2 に進みます。

インテグレーションが見つからない場合

先に Azure インテグレーションをセットアップする必要があることをユーザーに伝えてください。セットアップする場合は、先に dd-azure-integration スキルを完了してから、ここに戻ります。

Phase 2:スコープの選択と設定情報の収集

1. スコープの種類

コストを追跡するスコープをユーザーに尋ねます。

スコープ説明
請求先アカウント請求先アカウント配下のすべてのサブスクリプション - 最も広い範囲
サブスクリプション1つの Azure サブスクリプション
リソースグループサブスクリプション内の特定のリソースグループ

判断がつかない場合は、サブスクリプションをデフォルトにします。

2. スコープの詳細

スコープの種類に応じて、次の情報を収集します。

請求先アカウントのスコープ:

  • 請求先アカウント ID。Azure の請求先アカウント ID は契約の種類(Enterprise Agreement、Microsoft Customer Agreement など)によって形式が異なるため、照合できる単一の形式はありません。値をユーザーに伝え、続行する前に確認してもらいます。

サブスクリプションのスコープ:

  • サブスクリプション ID。command -v az >/dev/null 2>&1 が成功した場合は、az account show --query id -o tsv で取得します。これは az CLI で現在設定されているサブスクリプションを返します。ユーザーが指定したものか必ず確認し(決して決めつけず)、違う場合は切り替えてもらうか、正しい ID を提示してもらいます。それ以外の場合は、portal.azure.com → サブスクリプションからコピーするようユーザーに依頼します。

リソースグループのスコープ:

  • サブスクリプション ID
  • リソースグループ名
3. ストレージとエクスポート

該当する組み合わせをユーザーに確認します。組み合わせによっては有効でないため、これは重要です (既存のエクスポートにはストレージコンテナーが設定に組み込まれているため、新しいストレージアカウントと 組み合わせることはできません)。

シナリオストレージエクスポートサポート
新規セットアップ新規作成新規作成はい
独自のストレージを使用既存を使用新規作成はい
すべて既存のものを使用既存を使用既存を使用はい
新しいストレージ+既存のエクスポート新規作成既存を使用不可

初めて利用するユーザーには、デフォルトで新規セットアップを選択します。選択内容を記録します。Phase 3 で生成する Terraform のセクションが決まります。

4. ストレージ構成
フィールド説明デフォルト
リソースグループストレージアカウント用のリソースグループ(リソースグループのコストスコープとは異なる場合があります)(存在している必要があります)
ストレージのサブスクリプション IDストレージアカウントのリソースグループを保持するサブスクリプション。azurerm プロバイダーはこれにバインドされますスコープのサブスクリプション(Billing Account スコープでは必須)
場所Azure リージョンeastus
ストレージアカウント名ストレージアカウントの名前ddstorage
コンテナー名エクスポート用の Blob コンテナーdd-exports

既存のストレージを使用する場合は、アカウント名、コンテナー名、リソースグループをユーザーに確認します(Terraform では新しいリソースではなく、データソース参照になります)。

5. エクスポート構成

新しいエクスポートを作成する場合にのみ必要です。既存のエクスポートを使用する場合は、Azure ポータル(コスト管理 → エクスポート)で名前とパスを取得するか、command -v az >/dev/null 2>&1 が成功する場合は、 az costmanagement export list --scope "<SCOPE_VALUE>" を使用します(スコープの形式は references/terraform.md の Section 5 に記載されています。例:/subscriptions/<SUBSCRIPTION_ID>)。どちらの場合も、取得した内容を記録します。

フィールド説明デフォルト
実コストエクスポート名実コストエクスポートの名前actual-export
実コストエクスポートパスコンテナー内のパスプレフィックスdd-actual-exports
償却コストエクスポート名償却コストエクスポートの名前amortized-export
償却コストエクスポートパスコンテナー内のパスプレフィックスdd-amortized-exports

Phase 3:Terraform の生成と適用

既存の Terraform を確認する
find . -maxdepth 1 -type f \( -name '*.tf' -o -name '*.tf.json' -o -name 'terraform.tfstate' \) -print

既存のプロバイダーが見つかった場合は再利用します。ただし、選択したテナント、ストレージのサブスクリプション、および Phase 0 の Datadog サイトを対象としていることを確認してからにしてください。新しい CCM リソースのみを追加します。

Terraform HCL の生成

以下の各セクションの HCL 全文は references/terraform.md にあります。今すぐ読み、該当するセクションをプレースホルダーに値を入れて出力してください。生成するセクションは、Phase 2 で記録されたストレージとエクスポートのシナリオに基づいて決まります。

セクション含める条件
セクション 1:ストレージアカウントとコンテナー新しいストレージを作成する場合のみ
セクション 2:既存のストレージ参照既存のストレージを使用する場合のみ
セクション 3:コストエクスポート新しいエクスポートを作成する場合のみ。実際のコスト用と償却済みコスト用の両方を必ず含める
セクション 4:ロール割り当て必ず含める。datadog_cost_reader は サブスクリプション と リソースグループ のスコープにのみ追加し、Billing Account のスコープには追加しない
セクション 5:Datadog Azure UC 設定必ず含める。以下の表から該当するバリアントを 1 つ選ぶ

ユーザーが進んでいるパスに合ったセクション 5 のバリアントを選んでください。client_id、storage_account、storage_container フィールドは、リソース参照の場合(引用符なし)とリテラルの場合(引用符あり)で記述方法が異なります。混同しないでください。

パスバリアントclient_idstorage_accountstorage_container
新しいストレージ(セクション 1)で、azuread_application.datadog_app がこの Terraform ルートモジュール内で宣言されているAHCL 参照、引用符なしHCL 参照、引用符なしHCL 参照、引用符なし
新しいストレージ(セクション 1)で、アプリの登録がこのルートモジュール内で宣言されていない(既存のインテグレーション、または別のディレクトリで作成されたもの)B既存の client_id のリテラル、引用符ありHCL 参照、引用符なしHCL 参照、引用符なし
既存のストレージ(セクション 2)C既存の client_id のリテラル、引用符ありデータソースの .name、引用符なしコンテナー名のリテラル、引用符あり

バリアント A は、現在のディレクトリにある .tf ファイル内に resource "azuread_application" "datadog_app" が存在すること、かつそれが Phase 1 で選択したインテグレーションのアプリ登録であることを確認した場合にのみ使用してください。そのクライアント ID は、terraform state show -no-color azuread_application.datadog_app | grep -E '^ *client_id ' の結果が、選択した client_id と一致する必要があります。リソースがまだ state にない場合は、不一致として扱ってください。dd-azure-integration を完了しても、どちらも保証されません。リソースが存在しない場合、またはクライアント ID が一致しない場合は、選択したインテグレーションのリテラルの client_id を使用し、バリアント B または C を選んでください。

<CONTAINER_ID_REF> は次のように置き換えてください。

  • 新しいストレージを作成する場合は local.ccm_storage_container_id(セクション 1 で定義)
  • 既存のストレージを使用する場合は local.storage_container_id

<CURRENT_DATE_MIDNIGHT_UTC> は、今日の日付を YYYY-MM-DDT00:00:00Z 形式にして置き換えてください。

Terraform を 2 段階で適用する

datadog_azure_uc_config リソース(セクション 5)は、エクスポートに到達でき、データが生成されていることを Datadog 側で検証します。ファイルのパーティション分割を有効にする前、かつエクスポートが一度実行される前に適用すると、適用は失敗します。適用を 2 段階に分けてください。

ファイルの配置が重要です。 セクション 1〜4 は 1 つのファイル(例:azure-ccm.tf)に、セクション 5 は別のファイル(例:datadog-ccm-config.tf)に記述してください。第 1 段階では、セクション 5 をディレクトリ内に置かないでください。ファイルを残したまま -target だけで対象を絞ろうとしてはいけません。-target を指定した plan の後に通常の terraform apply を実行すると、対象を絞らない完全なプランが再生成され、セクション 5 も適用されようとします。ファイルを物理的に分ける方法が、段階分けを確実に行う最も安全な方法です。

最初の適用 — インフラストラクチャ(セクション 1〜4)
  1. セクション1~4をazure-ccm.tfに記述します。新しいセクション5のリソースはまだ記述しないでください。.tf ファイルに、Terraformのステートにあるdatadog_azure_uc_config(terraform state list 2>/dev/null | grep datadog_azure_uc_config)がすでに 記述されている場合は、そのまま残してください。そのブロックを削除すると、プランでその設定が破棄されます。まだ 適用されていないセクション5のリソースのみを保留してください。新しいリソースを適用済みのリソースと同じファイルに置く必要がある場合は、代わりに以下の保存済みターゲットプランを使用してください。

  2. すべてのプレースホルダーを収集した値に置き換えます。

  3. azurermとazureadのプロバイダーが設定されていることを確認します。プロバイダーがまだ 設定されていない場合:

    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = ">= 4.9.0, < 6.0.0"
        }
        azuread = {
          source = "hashicorp/azuread"
        }
        datadog = {
          source = "DataDog/datadog"
        }
      }
    }
    
    provider "azurerm" {
      features {}
      subscription_id = "<STORAGE_SUBSCRIPTION_ID>"
      tenant_id       = "<TENANT_ID>"
    }
    
    provider "azuread" {
      tenant_id = "<TENANT_ID>"
    }
    
    provider "datadog" {
      api_url = "https://api.<DD_SITE>/"
    }
    

    テンプレートにはAzureRM 4.9.0以降が必要です(コンテナーのstorage_account_idを使用するため)。また、storage_account_nameとresource_manager_idが削除された5.xでも動作するように記述されています。ユーザーのプロジェクトですでにazurermが4.9.0未満に固定されている場合は、その旨を伝え、固定バージョンを変更する前に確認してください。 azurermにはfeatures {}が必要です。また、両方のAzureプロバイダーを選択したテナントと ストレージサブスクリプションに関連付けることで、Terraformが現在のazセッションの設定先に作用するのを防げます。 デフォルトではプロバイダーはAzure CLIセッションで認証するため、az account show --query tenantId -o tsvが選択したテナントを返さない場合は、まずユーザーに az login --tenant <TENANT_ID>を実行してもらいます。フェーズ0でユーザーがCLI以外の方法を確認している場合は、その方法を維持し、代わりにそのARM_TENANT_ID(または同等の設定)が選択したテナントであることを確認します。DatadogプロバイダーはDD_SITEを読み取りません。api_url(またはDD_HOST)がない場合はUS1がデフォルトになるため、<DD_SITE>をフェーズ0で確認したサイトに置き換えます。キーはプロバイダーブロックに記述しないでください。DD_API_KEY/DD_APP_KEYを環境変数から読み込みます。

    **プランファイルとステートファイルは非公開にしてください。**保存済みプランとステートには、ストレージアカウントのアクセスキーや接続文字列が含まれることがあります。以下のプランコマンドではumask 077を設定しています。*.tfplan(ここで保存するプランはすべて.tfplanで終わります)と*.tfstate*が.gitignoreに含まれていることを確認し、絶対にコミットしないでください。また、ストレージアカウントのterraform state showなどでステートの内容を会話に出力しないでください。ユーザーがプランを拒否した場合は、プランファイルを削除してください。

    **テンプレートに必要なリソースプロバイダーを登録してください。**AzureRM 5.xではデフォルトでリソースプロバイダーが登録されません(4.xでは多数が自動登録されていました)。そのため、まだ登録されていないサブスクリプションでは、適用時にストレージアカウントまたはエクスポートの作成に失敗します。テンプレートでは、<STORAGE_SUBSCRIPTION_ID>でMicrosoft.StorageとMicrosoft.CostManagementExportsが登録されている必要があります。 az CLIで確認します。

    for ns in Microsoft.Storage Microsoft.CostManagementExports; do
      printf '%s: ' "$ns"; az provider show --namespace "$ns" --subscription '<STORAGE_SUBSCRIPTION_ID>' --query registrationState -o tsv || echo "lookup failed"
    done
    

    両方がRegisteredなら続行します。それ以外の場合は、未登録のものと、登録によってサブスクリプションが変更され、*/register/action権限が必要であることをユーザーに伝え、登録前に承認を待ちます。

    namespaces='<UNREGISTERED_NAMESPACES>'   # space-separated, from the check above
    for ns in $namespaces; do
      az provider register --namespace "$ns" --subscription '<STORAGE_SUBSCRIPTION_ID>' --wait || { echo "registering $ns FAILED"; exit 1; }
    done
    

    az CLIがない場合は、Azureポータルのサブスクリプション > リソースプロバイダーを開いて、未登録のプロバイダーを確認し、登録するようユーザーに依頼してください。または、承認を得たうえで、azurermプロバイダーブロックに resource_providers_to_register = ["Microsoft.Storage", "Microsoft.CostManagementExports"]を追加します。Terraformはプロバイダーの設定時に登録を行います。これはプラン作成時にも適用時にも実行されるため、以下のプランを作成する前に承認を得てください。

  4. terraform initを実行してから、プランを保存します。

    for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
    DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
    # Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
    : "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
    umask 077
    terraform plan -out=ccm.tfplan \
      || { echo "terraform plan FAILED - do NOT apply"; exit 1; }
    

    プランをユーザーに提示し、明示的な承認を待ちます。既存リソース(特にdatadog_azure_uc_config)を破棄または置換する場合や、datadog_integration_azureのresource_collection_enabledをfalseに設定する場合は適用しないでください。設定を修正してプランを作り直します。その後に限り、別のコマンドでその保存済みプランを適用します。

    for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
    DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
    # Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
    : "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
    trap 'rm -f ccm.tfplan' EXIT HUP INT TERM
    terraform apply ccm.tfplan \
      || { echo "terraform apply FAILED - do NOT continue to file partitioning"; exit 1; }
    

    セクション5がディレクトリにないため、このプランと適用の対象はインフラストラクチャリソースのみです。 何らかの理由でセクション 5 をディレクトリの外に移動できない場合は、保存済みの対象指定プランに切り替えます。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
umask 077
terraform plan -target=azurerm_storage_account.ccm_storage_account \
               -target=azurerm_storage_container.ccm_storage_container \
               -target=azurerm_<SCOPE>_cost_management_export.actual_cost \
               -target=azurerm_<SCOPE>_cost_management_export.amortized_cost \
               -target=azurerm_role_assignment.datadog_storage_reader \
               -target=azurerm_role_assignment.datadog_cost_reader \
               -out=phase1.tfplan \
  || { echo "terraform plan FAILED - do NOT apply"; exit 1; }

プランをユーザーに提示し、明示的な承認を待ってから、別のコマンドで適用します。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
trap 'rm -f phase1.tfplan' EXIT HUP INT TERM
terraform apply phase1.tfplan \
  || { echo "terraform apply FAILED - do NOT continue to file partitioning"; exit 1; }

ここでは、保存済みのプランファイルを使わずに terraform apply を実行しないでください。通常の apply(または通常の apply -target)でもプランが再生成され、Terraform のグラフにセクション 5 が含まれている場合は、state の状況によってセクション 5 が取り込まれる可能性があります。

適用後:ファイルのパーティション分割を有効化する(手動、2 回目の適用前に必須)

ユーザーは、Azure ポータルで両方のエクスポートについて手動でファイルのパーティション分割を有効化する必要があります。これは Terraform では実行できず、2 回目の適用前に行う必要があります。ユーザーに次の手順を案内してください。

  1. Azure ポータル → コスト管理 → エクスポートに移動します
  2. 各エクスポート(actual と amortized)について、以下を行います。
    • エクスポート名をクリックします
    • 「File Partitioning」を有効にします
    • 保存します
  3. 両方のエクスポートを手動で 1 回ずつ実行し、完了するまで待ちます
2 回目の適用 - Datadog CCM 設定(セクション 5)

ファイルのパーティション分割を有効にし、両方のエクスポートを正常に 1 回実行したら、セクション 5 を追加します。

  1. セクション 5 を含む datadog-ccm-config.tf を作成します(または、外に移動していた場合は元に戻します)。

  2. プランを保存してユーザーに提示し、明示的な承認を得てからそのファイルだけを適用します。インフラストラクチャはすでに state に存在するため、プランには新しい datadog_azure_uc_config リソースのみが含まれているはずです。保存済みのファイルを適用することで、ユーザーが承認したプランを確実に適用できます。

    for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
    DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
    # Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
    : "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
    umask 077
    terraform plan -out=ccm.tfplan \
      || { echo "terraform plan FAILED - do NOT apply"; exit 1; }
    

ユーザーがプランを承認したら、別のコマンドで適用します。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
trap 'rm -f ccm.tfplan' EXIT HUP INT TERM
terraform apply ccm.tfplan \
  || { echo "terraform apply FAILED - do NOT verify or report success"; exit 1; }

2 回目の適用で datadog_azure_uc_config がエラーになる場合、よくある原因は次のとおりです。

  • 片方または両方のエクスポートでファイルのパーティション分割が有効になっていない
  • エクスポートがまだ実行されていない(または完了していない)
  • セクション 4 のロール割り当てがまだ反映されていない(数分かかる場合があります)

フェーズ 4:設定の確認

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
resp=$(printf 'DD-API-KEY: %s\nDD-APPLICATION-KEY: %s\n' "$DD_API_KEY" "$DD_APP_KEY" \
  | curl -sS -w '\n%{http_code}' -X GET -H @- "https://api.${DD_SITE}/api/v2/cost/azure_uc_config")
code=$(printf '%s' "$resp" | tail -1); body=$(printf '%s' "$resp" | sed '$d')
[ "$code" = "200" ] || { echo "lookup failed with HTTP $code - do not assume 'not registered':"; printf '%s\n' "$body"; exit 1; }
printf '%s\n' "$body" | jq . 2>/dev/null || printf '%s\n' "$body"

フェーズ 1 と同じ形式チェックを適用し、data または configs が存在しない場合、あるいは配列でない場合は停止します。選択したテナント、クライアント、スコープに一致する account_id、client_id、scope を持つ、ネストされた configs[] レコードを特定します(フェーズ 1 の既存設定パスでは、ユーザーが確認した設定のスコープとエクスポートを使用します)。期待される export_name と storage_account を持つ actual と amortized のレコードが両方存在することを確認します。次に、各レコードの status と error_messages を確認します。

  • 両方が active でエラーメッセージがない場合:設定は成功です。コストデータが表示されるまで時間がかかることがあります。すでにコストが流入していると断言せず、その旨を伝えてください。
  • warn または error の場合、あるいは error_messages がある場合:メッセージをユーザーに提示してください。成功を報告したり、完了コールバックを送信したりしないでください。原因の修正を支援し(上記のよくある原因を参照)、再度確認してください。
  • disabled の場合、レコードが見つからない場合、またはスコープやエクスポートの識別情報が一致しない場合:設定は完了していません。ユーザーに伝え、コールバックを送信しないでください。
まとめ

検証後、Datadog UI がこのフローを完了できるよう、ベストエフォートで完了コールバックを 1 回実行します。

DD_WORKFLOW_ID は、認証情報の所有者である Datadog ユーザーの UUID です。UI はこの値を使ってコールバックを関連付けます。多くのエージェントランタイムではコマンドごとに新しいシェルが起動されるため、前のコマンドで設定した変数はここでは空になります。1 つのコマンド内で値を解決して POST してください。

current_user の応答は絶対に出力しないでください。この応答には、ユーザーの名前、ハンドル、メールアドレスも含まれています。JSON パーサーが利用できない場合は、インストールしたりセットアップをブロックしたりせず、このコールバックをスキップしてください。

for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done
DD_SITE='datadoghq.com'; export DD_SITE   # <- replace with the site confirmed in Phase 0.
# Explicit assignment, not ':=': a wrong non-empty DD_SITE in .env would otherwise survive.
: "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"; : "${DD_APP_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}"
dd_headers() { printf 'DD-API-KEY: %s\nDD-APPLICATION-KEY: %s\n' "$DD_API_KEY" "$DD_APP_KEY"; }
DD_WORKFLOW_ID="$(dd_headers | curl -H @- -fsS --connect-timeout 5 --max-time 20 \
  "https://api.${DD_SITE}/api/v2/current_user" | jq -er '.data.id')" \
  && dd_headers | curl -H @- -sS --connect-timeout 5 --max-time 20 -X POST \
  "https://api.${DD_SITE}/api/unstable/integration/azure/workflow/agentic_ccm" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"data":{"type":"integration_setup_status","id":"'"${DD_WORKFLOW_ID}"'","attributes":{"status":"finished","step":"setup_complete"}}}'

このコールバックが失敗しても、再試行したりセットアップをブロックしたりしないでください。

最後に、ユーザー向けの簡潔な概要を示してください。Cloud Cost Management にデータを送る Azure テナントとコストスコープ、使用中のストレージアカウントとコンテナー(新規作成または既存のものを再利用)、実績および償却済みのエクスポート名(新規作成または既存のものを再利用)、リソース収集を Phase 1 で有効にしたか、すでに有効だったかを含めてください。

以下の点をユーザーに伝えてください。

  • 最初のエクスポート実行後、コストデータが表示されるまで通常 24-48 時間かかります。
  • Azure はエクスポートを毎日実行するため、最初のデータは数時間以内に届く場合があります。

リンクを提示してください。

  • Cloud Cost Management:<APP_BASE>/cost
  • Cost Analytics:<APP_BASE>/cost/analytics

重要な注意事項

  • Azure のコストエクスポートを作成できるのは、Billing Account または Subscription レベルの権限を持つユーザーのみです。
  • ファイルのパーティション分割は Azure ポータルで手動で有効にする必要があります。Terraform ではサポートされていません。
  • lifecycle { ignore_changes = all } ブロックは、Terraform が Azure ポータルでの手動変更を上書きしないようにします。
  • サービスプリンシパルのデータソースには azuread プロバイダーが必要です。
  • ユーザーにプランを提示する前に、terraform apply を実行してはいけません。

コメント