dd-dbm-rds-postgres について
dd-dbm-rds-postgres は、AWS RDS の単体 PostgreSQL で Datadog Database Monitoring を設定する手順を案内します。マネージド、Terraform による Agent 配置、既存 Agent の利用に対応し、前提条件と認証情報の安全な扱いも説明します。
主な機能
- 01マネージド Fargate Agent の設定
- 02Terraform による Agent 配置
- 03既存 Agent の設定
- 04RDS PostgreSQL の前提条件確認
- 05認証情報を安全に扱う手順
活用シーン
- 01単体 RDS PostgreSQL で DBM を有効化
- 02Agent の配置方式を選択
- 03接続可能な既存 Agent で監視を設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ datadog-labs/ agent-skills --skill dd-dbm-rds-postgresインストール後、Claude Code で/dd-dbm-rds-postgresを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/existing-agent.mdmanaged-cloudformation.mdterraform.md詳細
RDS 上の Postgres 向け Datadog Database Monitoring
AWS RDS 上の PostgreSQL データベースに Datadog Database Monitoring(DBM)を設定するユーザーを支援します。
DBM は、読み取り専用のモニタリングユーザーとして RDS エンドポイントに接続する Datadog Agent を介して、クエリメトリクス、サンプル、実行計画を収集します。この Agent の実行方法は 3 通りあり、このスキルはすべてに対応しています。
- マネージド(CloudFormation) - Datadog がアカウント内に小規模な Fargate Agent をデプロイし、インスタンスに接続して
datadogユーザーを自動で初期設定します。これは、製品内の「Quick Install」と同じ方法です。すべての手順は AWS コントロールプレーンまたは Datadog API の呼び出しなので、データベースへの接続やホストへのアクセスがなくても、このシェルから実行できます。データベースにすでに到達できる Agent がユーザーにない場合は、この方法を選んでください。 - Terraform でプロビジョニング - ユーザーの Terraform プロジェクトで、専用の Fargate または EC2 Agent をプロビジョニングするか、既存の EKS Agent デプロイに DBM クラスターチェックを追加します。ユーザーが Agent とネットワークポリシーを IaC で管理したい場合、またデータベースに到達できるホストまたは SSM 経由でデータベースの初期設定を実行できる場合に選んでください。Terraform はシークレットのコンテナと IAM を管理しますが、シークレットの 値 は Terraform のステートに含まれないよう、別途登録します。
- 既存の Agent(手動) - ユーザーがすでに実行している Agent(ホスト/ECS/Kubernetes)に
postgresチェックを追加します。データベースにネットワーク経由で到達できる Agent がすでにあり、それを再利用したい場合(Fargate サービスを追加しない場合)に選んでください。
3 通りすべてで、インスタンス上の pg_stat_statements が必要です(フェーズ 2)。マネージド方式も例外ではありません。マネージドインストーラーは RDS パラメーターグループを 設定しないためです。これは 製品統合(PINT)フローであり、既存の Datadog AWS インテグレーションが必要です。
別のスキルの実行
以下の手順の一部では、別のスキル(たとえば 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:事前確認
Datadog 認証情報。 DD_SITE/DD_API_KEY/DD_APP_KEY を環境変数から読み込み(.env.local/.env にフォールバック)、2 つのキーを個別に検証します。それぞれ別個に失敗する可能性があります。
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 が 403 | API キーが無効であるか、DD_SITE と異なるリージョンに属しています | キーがどのサイトのものか確認し、DD_SITE を修正して再確認します |
validate が 200、current_user が 403 | アプリキーが間違っているか、別のリージョンのものです。API キーではありません | <APP_BASE>/organization-settings/application-keys から取得します |
DD_SITE is not a Datadog site | DD_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 の呼び出しでは、ヘッダーを標準入力で渡します。
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は通常どおり動作します。) - API キーを AWS に渡すのは、保護された一時ファイル経由のみです。 このスキルが Secrets Manager にキーを保存する箇所(マネージドパスおよび Terraform パス)では、
umask 077を設定して作成した一時ファイルにprintfで書き込み、--secret-string file://...として渡します。argv に含めたり、-var/TF_VAR_*経由で渡したりすることはありません。そのため、Terraform の状態ファイルやプランファイルにも残りません(フェーズ 3C、C1)。
ローダーと合わせることで、両方のキーがトランスクリプト、シェル履歴、プロセス一覧に残りません。
ツール。 aws と jq は必須です。psql と terraform は任意です(Terraform パスおよび既存 Agent パスでのデータベースのブートストラップには psql、Terraform パスには terraform が必要です)。
for t in aws jq; do command -v "$t" >/dev/null 2>&1 && echo "$t: available" || echo "MISSING $t"; done
for t in psql terraform; do command -v "$t" >/dev/null 2>&1 && echo "$t: available" || echo "$t: not installed (optional)"; done
ここに記載されているスニペットは POSIX シェル用です。 PowerShell または cmd では、Windows の同等のコマンド(Get-Command、$env:VAR、2>$null、curl.exe)を使用してください。呼び出し内容と順序は同じです。
フェーズ 1:前提条件と検出
AWS 統合とリソースコレクションを確認する
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/integration/aws/accounts")
code=$(printf '%s' "$resp" | tail -1); body=$(printf '%s' "$resp" | sed '$d')
[ "$code" = "200" ] || { echo "lookup failed with HTTP $code - do not assume 'not connected':"; printf '%s\n' "$body"; exit 1; }
printf '%s\n' "$body"
AWS 統合は条件付きの前提条件です。dd-aws-integration を無条件に実行すると、組織がすでに統合済みの場合でもアカウントやリージョンの入力を求められ、Terraform が適用されるため、ここで状態を確認してください。この確認は「いずれかのアカウント」ではなく、作業対象のアカウントに対して行ってください。複数アカウントの組織では、レスポンスに他の統合済みアカウントが含まれていても、RDS インスタンスを保持するアカウントは未統合のままという場合があり、そのリソースで PINT の前提条件が満たされません。作業対象のアカウント(対象の RDS インスタンスが存在するアカウント)を取得し、統合済みアカウントの一覧と照合してください。
aws sts get-caller-identity --query Account --output text
そのアカウント ID が統合済みアカウントに含まれている場合は、続行してください。含まれていない場合は、ここで停止し、このアカウントに対して dd-aws-integration スキルを実行してから戻ってください。リソースコレクション(resources_config.extended_collection)はDBM のコア機能には不要です。クエリメトリクス、サンプル、実行計画は Agent のデータベース接続から取得されます。リソースコレクションは、インスタンスとRDS インフラストラクチャメトリクス(CPU、メモリ、ディスク)を関連付けて DBM を補足する場合にのみ利用します。これは任意です。この関連付けをユーザーが希望する場合は、値が true であることを確認し、dd-aws-integration で有効にしてください。それ以外の場合はスキップしてください。
RDS インスタンスを特定する
このスキルの対象は、スタンドアロンで書き込み可能な単一インスタンスの RDS PostgreSQL データベースです。Engine=postgres で、クラスターの一部ではなく、リードレプリカでもないものが対象です。
検出を始める前に、対象リージョンを設定してください。 RDS はリージョンごとに管理されるため、describe-db-instances で一覧表示されるのは CLI の現在のリージョンのみです。インスタンスが別のリージョンにある場合、一覧は空になり、この出力からリージョンを特定することはできません。インスタンスがあるリージョンをユーザーに確認し(RDS コンソールに表示されています)、<REGION> に設定してください。以降のリージョン指定を伴うすべての aws 呼び出しでは、--region <REGION> を明示的に渡します。多くのエージェントランタイムでは、コマンドごとに新しいシェルが起動されるため、エクスポートした AWS_REGION は後続のブロックに引き継がれず、CLI はデフォルトのリージョンにフォールバックするか、リージョンが設定されていない場合は失敗します。
ユーザーがリージョンを特定できない場合は、まずすべてのリージョンから Postgres インスタンスを探し、一致するリージョンを <REGION> に設定してから続行してください。リージョン一覧の取得自体にも、明示的なリージョン指定が必要です。商用 AWS では us-east-1、GovCloud では us-gov-west-1 を使用してください。リージョン一覧を取得できない場合、ブロックは停止します。そのため、空の結果はインスタンスがないことを意味します。
DISCOVERY_REGION='us-east-1' # us-gov-west-1 for GovCloud
REGIONS=$(aws ec2 describe-regions --region "$DISCOVERY_REGION" --query "Regions[].RegionName" --output text) \
|| { echo "Could not list regions from $DISCOVERY_REGION; ask the user for the region instead." >&2; exit 1; }
[ -n "$REGIONS" ] || { echo "Region list is empty; ask the user for the region instead." >&2; exit 1; }
printf '%s\n' "$REGIONS" | tr -s '[:space:]' '\n' | while read -r region; do
[ -n "$region" ] || continue
aws rds describe-db-instances --region "$region" \
--query "DBInstances[?Engine=='postgres'||Engine=='aurora-postgresql'].[DBInstanceIdentifier]" \
--output text </dev/null | sed "s/^/$region /"
done
対象リージョン内の候補をエンジン、クラスター、レプリカ元とともに一覧表示し、対応できないデプロイを特定して除外してください。
aws rds describe-db-instances --region <REGION> \
--query "DBInstances[?Engine=='postgres'||Engine=='aurora-postgresql'].{ID:DBInstanceIdentifier,Engine:Engine,Cluster:DBClusterIdentifier,Replica:ReadReplicaSourceDBInstanceIdentifier,Endpoint:Endpoint.Address,Port:Endpoint.Port,Version:EngineVersion,ParamGroup:DBParameterGroups[0].DBParameterGroupName,SG:VpcSecurityGroups[0].VpcSecurityGroupId,VPC:DBSubnetGroup.VpcId}" \
--output json
続行する前に、次の 2 種類のインスタンスを除外してください。
- クラスター化されたインスタンス(
Clusterが設定されているか、Engine=aurora-postgresql)。Aurora と RDS Multi-AZ DB クラスターはどちらも(Engine=postgresと報告される場合でも)クラスター化されており、このスキルがmodify-db-instanceで変更するインスタンス単位のパラメータグループではなく、DB クラスターパラメータグループ(modify-db-cluster/*-db-cluster-parameter-group)で設定されます。また、ライター/リーダーのエンドポイントが別で、再起動の動作も異なります。そのため、フェーズ 2 以降は適用されず、pg_stat_statementsも正しく有効化されません。(クラスターのサポートは別の手順です。) - リードレプリカ(
Replica/ReadReplicaSourceDBInstanceIdentifierが設定されている)。レプリカは読み取り専用であるため、どちらの手順でも書き込みを伴う設定(CREATE ROLE/CREATE EXTENSION/実行計画関数)は失敗します。ユーザーにソースのライター(Replicaの値)を案内し、代わりにそこで設定を実行してください。
どちらかに該当する場合は、行き詰まった状態でユーザーを残さず、代わりにどこへ進めばよいかを伝えて停止してください。
- リードレプリカ(
Replicaが設定されている) - このスキルはソースのライター(Replicaの値)に対して実行します。これはプライマリのインスタンス識別子です。 - Aurora / RDS Multi-AZ DB クラスター(Aurora Serverless v2 を含む)(
Clusterが設定されている、またはEngine=aurora-postgresql) - このインスタンス単位のフローではクラスターを設定できません(パラメーターグループのモデルが異なり、ライターとリーダーのエンドポイントが別々です)。Datadog の DBM Postgres セットアップドキュメント(https://docs.datadoghq.com/database_monitoring/setup_postgres/)を案内してください。クラスターのサポートは別のフローであり、ここではまだ利用できません。特に、顧客の VPC に配置されていない Aurora Serverless v2 は、マネージド CloudFormation テンプレートが想定するトポロジーではないため、ユーザーが強制的に適用してもマネージドの手順は適合しません。
Cluster と Replica がどちらも空の、スタンドアロンの Engine=postgres インスタンスの場合のみ続行してください。
選択したインスタンスから、エンドポイント、ポート(デフォルトは 5432)、リージョン、DB インスタンス識別子、Postgres のメジャーバージョン、VPC ID、VPC セキュリティグループ ID、および現在アタッチされているパラメーターグループを取得します。<MAJOR_VERSION> にはメジャー番号のみを指定します(例:15.4 の場合は 15)。EngineVersion をドットで区切った最初の要素を使用してください。そうしないと、ファミリー postgres<MAJOR_VERSION> が無効になります。
出力に不足しているフィールドがある場合、または呼び出し元に rds:DescribeDBInstances の権限がない場合は、ユーザーに確認してください(すべて RDS コンソールで確認できます)。また、モニタリングユーザーを作成するため、マスターユーザーとして一度認証する必要があります。インスタンスで RDS 管理のマスターシークレットを使用している場合は、パスワードまたはそのシークレットが必要です(マネージド手順では A1、Terraform または既存の Agent を使う手順では B3)。
マネージドまたは Terraform の Fargate 手順では、Agent に RDS DB サブネットグループのサブネットを再利用しないでください。 それらのサブネットは分離されていることが多く(NAT ゲートウェイも VPC エンドポイントもありません)、タスクはイメージを取得したり Secrets Manager / Datadog に接続したりできず、Postgres に接続する前に停止します。Agent には、アウトバウンド経路(NAT、または ECR + Secrets Manager + Datadog の VPC エンドポイント)があり、かつ RDS インスタンスへのルーティングも可能なECS 対応サブネットが必要です。
インストール方法を選択する
適切なデフォルトは、ユーザーがすでに到達可能な Agent を実行しているか、Terraform による管理を希望するか、ブートストラップ SQL を実行できる DB 接続可能な場所があるかによって異なります。
ユーザーがこの RDS インスタンスにすでに到達できる Datadog Agent を持っておらず、Agent を Terraform に管理させる必要もない場合は、デフォルトでマネージドパス(Phase 3A)を使用してください。これは、製品内のクイックインストールに最も近い方法です。すべてのステップが AWS コントロールプレーンまたは Datadog API の呼び出しであるため、データベース接続やホストアクセスなしでこのシェルから実行でき、API キーはプレーンテキストで保存するのではなく、Secrets Manager(A4)から注入されます。
ユーザーがこの RDS エンドポイントに到達できる Datadog Agent(同じ VPC 内、またはネットワークアクセス可能なホスト/EC2、ECS、Kubernetes 上の Agent)をすでに実行しているか、また Agent を Terraform に管理させたいかを確認してください。
- 既存の到達可能な Agent がなく、Terraform に管理させる必要もない → Phase 3A(マネージド) - 推奨デフォルトです。
- 既存の Agent を再利用し、Terraform に管理させる必要もない → Phase 3B(既存の Agent) - 2 つ目の Agent を新たに起動せずに済みます。
- Terraform に Agent を管理させる必要がある(現在 Agent が存在するかどうかは問いません) → **Phase 3C(Terraform でプロビジョニングする Agent)**から開始してください。C1 で空のシークレットコンテナを作成し、その後、フローは B2/B3 に進み、ステート外でシークレットを設定して SQL を実行してから、C2/C3 に戻ります。この方法では、B3 のために DB 接続可能なホスト、SSM 管理インスタンス、または直接接続するクライアントが必要です。いずれもない場合は、Terraform による管理の要件を緩和して 3A を使用するか、停止してユーザーに DB 接続可能なブートストラップ方法(SSM、ホスト、またはクライアント)を確認してください。CloudFormation に黙って切り替えてはいけません。
<APP_BASE>/databases/setup にある Terraform ジェネレーターは、Agent インフラストラクチャとネットワークの出発点として役立ちますが、DBM のブートストラップを完全に行うものではありません。生成されるモジュールは、datadog ロールとデータベースごとのオブジェクトがすでに存在することを前提とし、pg_stat_statements を設定せず、データベースや API キーの値を terraform.tfvars、ステート、ランタイム定義に含める可能性があります。このバンドルを変更せずに適用してはいけません。Phase 3C では、このフローで使用する前に満たすべきセキュリティ強化の要件を示します。
安全性/コマンド承認ポリシーの下で動作する AI エージェントへの注意事項: マネージドパスでは、スタック内で S3 からテンプレートとインストールスクリプトを curl で取得し、curl -L "$DBMInstallScriptUrl" | bash を実行し、CAPABILITY_IAM を使ってデプロイします。安全性分類器によっては、このリモートコードと広範な IAM 権限の組み合わせを全面的に拒否することがあります。分類器と無理にやり取りしないでください。成果物を取得して確認し(Phase 3A)、それでもデプロイがブロックされる場合は、実行する正確な cloudformation deploy コマンドをユーザーに提示するか、データベースのブートストラップに到達できる場合は 3B/3C を使用してください。これはハーネスの制約であり、ユーザーにマネージドパス以外を勧める理由にはなりません。
Phase 2:pg_stat_statements を有効にする(パラメータグループ)- すべての方法
ここから先の aws コマンドはすべて、インスタンスのリージョンを対象に実行してください。シークレット、セキュリティグループルール、パラメータの変更、再起動がデフォルトのリージョンを対象にしないようにするためです。以下の各コマンドにはそれぞれ --region <REGION> が指定されています。前のブロックでエクスポートしたリージョンは次のシェルには引き継がれないため、追加するコマンドにも必ず指定してください。
DBM では、shared_preload_libraries に pg_stat_statements が必要です。これは静的パラメータです。現在アタッチされているグループと、その shared_preload_libraries を確認してください。
aws rds describe-db-parameters --region <REGION> --db-parameter-group-name <CURRENT_PARAM_GROUP> \
--query "Parameters[?ParameterName=='shared_preload_libraries'].ParameterValue" --output text
現在のリストにない場合は、pg_stat_statements を追加して目標値を決定してください。たとえば、pgaudit は pgaudit,pg_stat_statements になります。リスト全体を置き換えてはいけません。置き換えると、pgaudit、auto_explain、pg_cron などの既存ライブラリが無効になります。結果を <SHARED_PRELOAD_LIBRARIES> と呼びます。
DBM では、track_activity_query_size を 4096 以上にする必要があります。ただし、すでにそれ以上のクエリテキストを取得しているインスタンスの値を下げないでください。現在の値を確認してください。
aws rds describe-db-parameters --region <REGION> --db-parameter-group-name <CURRENT_PARAM_GROUP> \
--query "Parameters[?ParameterName=='track_activity_query_size'].ParameterValue" --output text
その値と 4096 のうち大きい方を <TRACK_ACTIVITY_QUERY_SIZE> として使用します(結果が空または未設定の場合はファミリーのデフォルト値が使われます。これは4096未満なので、4096 を使用してください)。
これらの値はグループに設定されている値であり、インスタンスに読み込まれているとは限りません。前回の実行でグループを変更した後、再起動前に処理が中断された可能性があるため、インスタンスに再起動待ちのパラメータ変更が残っているかどうかも確認してください。
aws rds describe-db-instances --region <REGION> --db-instance-identifier <DB_INSTANCE_IDENTIFIER> \
--query "DBInstances[0].DBParameterGroups[0].[DBParameterGroupName,ParameterApplyStatus]" --output text
アタッチされているグループが、たった今読み取ったグループと異なる場合は、それを <CURRENT_PARAM_GROUP> として使用し、そのグループに対して上記の2つの読み取りを再実行して、何かを決定する前に両方の目標値を再計算してください。
ParameterApplyStatus が pending-reboot の場合、設定値はまだ有効になっていないため、以下の再起動なしのショートカットは適用されません。保留中の変更はDBMと無関係の可能性もあるため、設定値と要件の比較は引き続き行ってください。両方がすでに要件を満たしている(pg_stat_statements が shared_preload_libraries に含まれており、track_activity_query_size が4096以上である)場合は、パラメータ変更を省略し、このフェーズ末尾の再起動ステップに進み、同じく明示的な確認を得てください。それ以外の場合は、以下のそれ以外の場合の分岐に進み、不足している設定を適用してから再起動してください。このショートカットが適用されるのは、ステータスが in-sync の場合に限られます。
pg_stat_statements がすでに shared_preload_libraries に含まれ、track_activity_query_size がすでに4096以上で、かつ上記のステータスが in-sync の場合(PG15以降のデフォルトグループでよく見られます)、必要なパラメータはすでに満たされています。DBMはパラメータ変更や再起動なしで、切り詰められていないクエリメトリクスを収集します。残る設定は任意のチューニングのみです。pg_stat_statements.track=all(ネストされたステートメントを取得)と track_io_timing=1(説明プランでI/O時間を表示)はどちらも動的な設定です(ApplyMethod=immediate)。適用方法は現在のグループによって異なります。
- カスタムグループの場合 -
modify-db-parameter-groupを使って2つのパラメータをその場で設定します(ApplyMethod=immediate)。再起動なしで有効になります。グループが他のインスタンスと共有されている場合は、以下の共有グループに関する注意事項が適用され、変更が他のインスタンスにも反映されるため、先に確認してください。 default.*グループの場合 - デフォルト値は変更できないため、これらを有効にするにはカスタムグループを作成し、アタッチするために再起動する必要があります(値がすでに一致していても、アタッチすると静的パラメータがpending-rebootに切り替わります)。この忠実度向上に再起動する価値があるか、ユーザーに確認してください。価値がない場合は、フェーズ2の残りを省略し、選択したインストール方法(フェーズ3A、3B、または3C)に進みます。
それ以外の場合 - pg_stat_statements が読み込まれていないか、track_activity_query_size が4096未満です(デフォルト値の1024では、クエリサンプルと説明プランの入力が切り詰められます)。パラメータ変更と再起動は任意ではなく、実際に必要です。続行して、現在のグループに応じて分岐します。
インスタンスが default.postgresN グループを使用している場合(デフォルト値は変更できません)、同じファミリーでカスタムグループを作成してアタッチします。名前はインスタンスごとに付けて、他のインスタンスやファミリーと重複しないようにし、前回の実行で作成済みの場合は再利用してください。
PARAM_GROUP="datadog-dbm-<DB_INSTANCE_IDENTIFIER>-pg<MAJOR_VERSION>"
if ! CREATE_ERR=$(aws rds create-db-parameter-group --region <REGION> \
--db-parameter-group-name "$PARAM_GROUP" \
--db-parameter-group-family postgres<MAJOR_VERSION> \
--description "Datadog DBM settings" 2>&1 >/dev/null); then
case "$CREATE_ERR" in
*DBParameterGroupAlreadyExists*) echo "Reusing existing parameter group $PARAM_GROUP" ;;
*) echo "$CREATE_ERR" >&2; exit 1 ;;
esac
fi
aws rds modify-db-parameter-group --region <REGION> \
--db-parameter-group-name "$PARAM_GROUP" \
--parameters '[
{"ParameterName":"shared_preload_libraries","ParameterValue":"<SHARED_PRELOAD_LIBRARIES>","ApplyMethod":"pending-reboot"},
{"ParameterName":"track_activity_query_size","ParameterValue":"<TRACK_ACTIVITY_QUERY_SIZE>","ApplyMethod":"pending-reboot"},
{"ParameterName":"pg_stat_statements.track","ParameterValue":"all","ApplyMethod":"immediate"},
{"ParameterName":"track_io_timing","ParameterValue":"1","ApplyMethod":"immediate"}
]' >/dev/null || exit 1
SPL=$(aws rds describe-db-parameters --region <REGION> --db-parameter-group-name "$PARAM_GROUP" \
--query "Parameters[?ParameterName=='shared_preload_libraries'].ParameterValue" --output text) || exit 1
TAQS=$(aws rds describe-db-parameters --region <REGION> --db-parameter-group-name "$PARAM_GROUP" \
--query "Parameters[?ParameterName=='track_activity_query_size'].ParameterValue" --output text) || exit 1
case ",$(printf '%s' "$SPL" | tr -d ' ')," in
*,pg_stat_statements,*) ;;
*) echo "shared_preload_libraries on $PARAM_GROUP is '$SPL'; pg_stat_statements is missing." >&2; exit 1 ;;
esac
case "$TAQS" in
''|*[!0-9]*) echo "track_activity_query_size on $PARAM_GROUP is '$TAQS', not a number." >&2; exit 1 ;;
esac
[ "$TAQS" -ge 4096 ] || { echo "track_activity_query_size on $PARAM_GROUP is $TAQS, below 4096." >&2; exit 1; }
PENDING=$(aws rds describe-db-instances --region <REGION> --db-instance-identifier <DB_INSTANCE_IDENTIFIER> \
--query "DBInstances[0].PendingModifiedValues" --output json) || exit 1
printf '%s' "$PENDING" | jq -e 'length == 0' >/dev/null \
|| { echo "Pending modifications are queued and --apply-immediately would apply them now:" >&2; printf '%s\n' "$PENDING" >&2; exit 1; }
aws rds modify-db-instance --region <REGION> \
--db-instance-identifier <DB_INSTANCE_IDENTIFIER> \
--db-parameter-group-name "$PARAM_GROUP" \
--apply-immediately >/dev/null || exit 1
aws rds wait db-instance-available --region <REGION> --db-instance-identifier <DB_INSTANCE_IDENTIFIER> || exit 1
このブロックは、前回の実行で発生した想定内の DBParameterGroupAlreadyExists を除き、失敗があれば停止します。また、必要な値が設定されていることを確認してからグループをアタッチします。
--apply-immediately は、インスタンスにすでにキューされている他の変更(たとえばインスタンスクラスの変更)もすべて適用するため、以下の再起動確認を行う前に停止が発生する可能性があります。そのため、このブロックは PendingModifiedValues が空でない場合に停止します。キューに入っている変更をユーザーに提示し、明示的な承認を得て今すぐ適用するか、変更が適用または解除されるまで待ってください。
グループの切り替えは非同期で行われ、インスタンスは一時的に modifying 状態になります。このフェーズ後半での再起動には available 状態が必要なので、再起動を促す前に状態が安定するまで待ってください。
--parameters には意図的に略記ではなく JSON を渡してください。shared_preload_libraries にはカンマ区切りのリスト(例:pgaudit,pg_stat_statements)を指定できますが、CLI の Key=Value,... 形式の略記では、このカンマがフィールド区切りとして解釈され、失敗します。略記形式に戻さないでください。
Terraform で同等の設定を行うには、上記の 4 つの parameter ブロックを持つ aws_db_parameter_group "datadog_dbm"(ファミリーは postgres<MAJOR_VERSION>、衝突を避けるため、CLI の $PARAM_GROUP のようにインスタンスごとの name を指定)を用意します。shared_preload_libraries と track_activity_query_size の apply_method はどちらも "pending-reboot"(どちらも再起動が必要)に設定し、残り 2 つは immediate にします。aws_db_instance の parameter_group_name は、同じ Terraform でインスタンスを管理している場合に限り設定します。それ以外の場合は Terraform でグループを作成し、上記の aws rds modify-db-instance コマンドでアタッチします。
インスタンスがすでにカスタムグループを使用している場合は、まず、そのグループが他のインスタンスと共有されていないことを確認してください。グループをその場で変更すると、次回の再起動時に、そのグループにアタッチされているすべてのインスタンスでこれらのパラメーターが変更されます。
aws rds describe-db-instances --region <REGION> \
--query "DBInstances[?DBParameterGroups[0].DBParameterGroupName=='<CURRENT_PARAM_GROUP>'].DBInstanceIdentifier" \
--output text
対象のインスタンスのみが表示された場合は、そのグループをそのまま変更してください。グループを新規作成したり、入れ替えたりしないでください。再起動時に既存の設定が失われます。ほかのインスタンスも表示された場合は、作業を中断してユーザーに確認してください。DBM パラメーターがそれらすべてに適用されることを受け入れるか、このインスタンス専用にグループを複製するかを確認します(上記の default.* の分岐と同様に、このグループのパラメーターを引き継いだ datadog-dbm-<DB_INSTANCE_IDENTIFIER>-pg<MAJOR_VERSION> を作成し、同じ PendingModifiedValues の確認を行ってからアタッチします)。ユーザーがオンボーディング対象に選んでいないインスタンスを、黙って再設定しないでください。
aws rds modify-db-parameter-group --region <REGION> \
--db-parameter-group-name <CURRENT_PARAM_GROUP> \
--parameters '[
{"ParameterName":"shared_preload_libraries","ParameterValue":"<SHARED_PRELOAD_LIBRARIES>","ApplyMethod":"pending-reboot"},
{"ParameterName":"track_activity_query_size","ParameterValue":"<TRACK_ACTIVITY_QUERY_SIZE>","ApplyMethod":"pending-reboot"},
{"ParameterName":"pg_stat_statements.track","ParameterValue":"all","ApplyMethod":"immediate"},
{"ParameterName":"track_io_timing","ParameterValue":"1","ApplyMethod":"immediate"}
]'
(ユーザーがそのカスタムグループを Terraform で管理している場合は、既存の aws_db_parameter_group リソースにこれらのパラメーターを追加し、ほかのパラメーターはそのまま残します。)
静的パラメーターを読み込むために再起動します。再起動中は接続が一時的に切断されます。実行前にユーザーに伝え、明示的な確認を得てください。本番インスタンスの場合は、メンテナンスウィンドウの利用を提案します。ユーザーの確認を得た後にのみ、次を実行します。
aws rds reboot-db-instance --region <REGION> --db-instance-identifier <DB_INSTANCE_IDENTIFIER> || exit 1
aws rds wait db-instance-available --region <REGION> --db-instance-identifier <DB_INSTANCE_IDENTIFIER> || exit 1
STATUS=$(aws rds describe-db-instances --region <REGION> --db-instance-identifier <DB_INSTANCE_IDENTIFIER> \
--query "DBInstances[0].DBParameterGroups[0].ParameterApplyStatus" --output text)
echo "ParameterApplyStatus: $STATUS"
[ "$STATUS" = "in-sync" ] || { echo "Parameters are not applied yet; wait and re-check before continuing." >&2; exit 1; }
フェーズ 3A:マネージド Agent(CloudFormation)—「クイックインストール」に相当
references/managed-cloudformation.md(A1 RDS 管理者シークレット、A2 ネットワークアクセス、A3 マネージド ECS クラスター、A4 インスタンスごとの DBM Agent サービス)の手順に従ってください。今すぐ読み、その後 フェーズ 4 に進みます。
フェーズ 3B:セルフマネージドのデータベース初期設定と既存 Agent
references/existing-agent.md(B1 ネットワークアクセス、B2 パスワードシークレット、B3 監視ユーザーと権限、B4 既存 Agent の確認)の手順に従ってください。既存 Agent の手順では B1〜B4 をすべて実行します。Terraform の手順では、C1 から進む場合に B2 と B3 のみを実行します。その後 フェーズ 4 に進みます。
フェーズ 3C:Terraform でプロビジョニングする Agent
references/terraform.md(C1 シークレットと check-config の契約、C2 ランタイム固有の Terraform、C3 plan、approve、apply)の手順に従ってください。C1 では、フローを references/existing-agent.md の B2/B3 に進めてから C2 に戻します。その後 フェーズ 4 に進みます。
フェーズ 4:検証と報告 — すべての手順
DBM データが流れていることを確認します。ベースの接続だけではなく、DBM 固有のメトリクスを検証してください。場所に依存しない確認方法として、次の Datadog API クエリを優先してください。
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 @- -s -G "https://api.${DD_SITE}/api/v1/query" \
--data-urlencode "from=$(($(date +%s) - 900))" \
--data-urlencode "to=$(date +%s)" \
--data-urlencode "query=avg:postgresql.queries.count{dbinstanceidentifier:<DB_INSTANCE_IDENTIFIER>}"
空でない series が postgresql.queries.count に対して返されれば、DBM クエリメトリクスが流れていること(Agent が pg_stat_statements を読み取っていること)を確認できます。これはベースのチェックが接続できたことを確認するだけではありません。また、Databases ページにクエリサンプルと explain planが表示されることも確認してください。マネージドの手順では、何も表示されない場合に ECS サービスと datadog-managed-dbm の CloudWatch ログを確認します。Terraform の手順では、C3 の説明に従って Terraform 管理の ECS/EC2/EKS ランタイムとそのログを確認します。既存 Agent の手順では、Agent ホスト上で sudo datadog-agent status | grep -A 20 postgres を実行すると、pg_stat_statements/pg_stat_activity エラーがなく、チェックが正常であることを確認できます(SSM またはユーザー経由)。
完了
検証後、Datadog UIでこのフローを完了できるように、可能な範囲で完了コールバックを1回送信します。
DD_WORKFLOW_IDは、認証情報の所有者であるDatadogユーザーのUUIDです。この値を使って、UIはこのコールバックを関連付けます。値の解決と送信は1つのコマンドで行ってください。多くのエージェントランタイムではコマンドごとに新しいシェルが起動するため、先のコマンドで設定した変数はここでは空になります。
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/aws/workflow/agentic_dbm" \
-H "Content-Type: application/vnd.api+json" \
-d '{"data":{"type":"integration_setup_status","id":"'"${DD_WORKFLOW_ID}"'","attributes":{"status":"finished","step":"setup_complete"}}}'
このコールバックが失敗しても、再試行したりセットアップを妨げたりしないでください。
ユーザーに完了を伝え、セットアップ内容を簡潔にまとめてください。
- インスタンス(
<DB_INSTANCE_IDENTIFIER>、リージョン、エンドポイント)と使用したインストール方法(管理されたCloudFormation、Terraformでプロビジョニング、または既存のAgent)。 - フェーズ2でパラメーターグループに加えた変更(対象グループ、パラメーター、再起動の有無)、または変更不要だったこと。
- 作成または再利用したSecrets Managerシークレットの名前(値は絶対に記載しないでください)。
- 上記の
postgresql.queries.countチェックの結果。
続いて、以下にリンクしてください(フェーズ0のApp URLテーブルから<APP_BASE>/...の形式で組み立ててください)。
- Database Monitoring:
<APP_BASE>/databases- クエリメトリクス、サンプル、実行計画。 - Databases list:
<APP_BASE>/databases/list- データベースごとの健全性。 - インフラストラクチャメトリクスを確認するには、インスタンスがRDS integrationダッシュボードにも表示されます。
**次のステップの提案:**接続数の飽和、レプリケーション遅延、低速クエリのモニターを設定します。他のインスタンスでも同じ手順を繰り返すか、別のエンジン(MySQL、SQL Server)向けにDBMをセットアップします。
重要な注意事項
- 3つの経路に共通する前提条件があります。 管理対象の経路(Phase 3A)では、Datadog Fargate Agent をデプロイし、VPC 内で
datadogユーザーを初期設定します。既存 Agent の経路(3B)では既存の Agent を再利用します。Terraform の経路は 3C から開始し、共通の B2/B3 初期設定を実行してから、Agent/ネットワークのプロビジョニングに戻ります。どの経路でも、pg_stat_statementsの有効化(Phase 2)が必要です。 管理対象のインストーラーは RDS パラメータグループを設定しないため、このスキルで有効化します。 - 既存の DB 設定を維持してください。
shared_preload_librariesは置き換えず、pg_stat_statementsを追加します。既存のカスタムパラメータグループはそのまま変更し、default.*グループの場合に限り、新しいグループを作成してアタッチします。shared_preload_librariesとtrack_activity_query_sizeの変更には再起動が必要です。 - Terraform と既存 Agent の経路では、データベースごとに設定します。
CREATE USER/GRANT pg_monitorはクラスター全体に適用されるため、1 回だけ実行します。スキーマ、USAGE 権限、拡張機能、およびexplain_statement関数は、監視対象の各データベースで作成する必要があります。関数のSET TRANSACTION READ ONLYガードは維持してください。 - シークレット。 管理対象の経路では、VPC 内のインストーラーが
datadogユーザーの初期設定に使用する RDS の 管理者 シークレット(JSON{username,password})が必要です。インストーラーはタスクを起動するたびに再実行されるため、このシークレットは有効な状態に保ってください(ECS 実行ロールにスコープを設定し、マスターパスワードをローテーションした場合はシークレットも更新します)。これは 1 回限りの設定ではありません。DatadogUserSecretを設定せずにシークレットを削除したり、SkipInitialize=trueを設定したりすると、Agent が動作しなくなります。マスター認証情報を常時保持しないようにするには、最初からセルフマネージドのDatadogUserSecretとSkipInitialize=trueを使用してください。Terraform/既存 Agent の経路では、datadogユーザーのパスワードは、チェックを実行する Agent 上でaws.secretsバックエンドを介して JSON として読み取られ、ENC[...;password]として参照されます。その Agent のロールにsecretsmanager:GetSecretValueを許可してください。Terraform が管理するのは、空のシークレットコンテナーと IAM のみです。値は Terraform の外部で設定してください。パスワードを直接記述したり、ランタイム定義に埋め込んだり、Terraform の状態ファイルにコミットしたりしないでください。 - 管理対象/Terraform-Fargate のネットワーク。 Fargate Agent のサブネットは ECS に対応し、NAT または VPC エンドポイント経由で ECR/Secrets Manager/Datadog へ送信でき、RDS にルーティングできる必要があります。RDS DB サブネットグループの分離されたサブネットは使用しないでください。RDS セキュリティグループでは、ハードコードされた 5432 ではなく、実際の DB ポートで Agent のセキュリティグループからの接続を許可してください。
- 実行モデル。 このスキルはユーザーのシェルで実行され、そのシェルから直接アクセスできるのは Datadog と AWS コントロールプレーン API のみです。管理対象の経路はこの境界内で完結します。Terraform と既存 Agent の経路における
psqlの権限付与、およびホスト上でのconf.d/datadog-agent statusの実行は、DB に到達できるホストから行います。SSM を介したエージェントレスの方法、またはユーザー自身が実行する方法を使用し、SSH 経由では実行しないでください。ネットワーク到達性を確認できていない限り、ローカルマシンからも実行しないでください。 datadogユーザーは読み取り専用(pg_monitor)であり、データを変更することはありません。