Datadog-Monitorを検知してEventBridgeからRunCommandを実行
概要
docker on EC2で起動しているコンテナが unthealthy 状態に陥った時に、datadog-agentで検知し、AWS RunCommandから再起動コマンドを実施するようなシステムを考えます。
※docker on EC2でdocker-agentをインストールする方法についてはこの記事では記載しません。予めインストールしていることが前提となっています。
このシステムに至った経緯
EC2上で、docker-composeでコンテナを起動させています。
このdocker-composeにはアプリケーションのほかにdatadog-agentも定義しており、コンテナがハングったときにアラートを出してくれるという仕組みをもともと作っていました。
しかし、検知するだけでコンテナの再作成は手動で行わないといけないという運用になっていました。
docker-compose(もしくはDockerfile)にはHealthcheckという仕組みがありますが、これはunthealthyを検知はしてくれるものの、勝手に再起動はしてくれません。
個人的にhealthcheckという仕組みはdocker-composeの起動順を制御するために使う仕組みだと思っています。
ではどのようにして、unthealthyに陥ったコンテナを再起動するか?
私が調べた限り、これはwatchdog的なコンテナを横に立て、unthealthyになったら再起動する。という仕組みを作るしかないという結論でした。
ちょうどdatadog-agentを横に立てていたので、これを使おうということになりました。
システム概要

- DatadogのMonitorに
@awseventbridge-xxxと設定し、Eventbridgeをトリガーするようになっている - アラームの発報をトリガーとしてEventBusから各Eventbridgeルールへとイベントが送信される
- instance-Aが停止した場合は、instance-Aのルールが起動し、
key:{tag:Name}, value: instance-Aのタグを持つインスタンスにコマンドを送信する
EventBus
EventBusは「Monitorに対し1つ」作成する設計になっています。いろいろ検証した結果それが一番丸いという結論になりました。
イベントパターンについて
Eventルールを作成するときにフィルター項目として、「イベントパターン」というものを設定する必要があります。
最終的に、instance-AのEventRuleに記載するイベントパターンは以下のようになっています。
{ "source": [{ "prefix": "aws.partner/datadog.com" }], "detail-type": [{"prefix":"Datadog Alert Notification"}], "detail": { "alert_type": [{"prefix":"error"}], "meta": { "result": { "group": [{ "suffix": "instance-A" }] } } } }
初期値
AWSのコンソール上からEventRuleを作成しようとするとAWS側がイベントパターンを勝手に入力してくれます。しかし、もともとはsourceしかなく、「instance-Aがダウンしたとき」という条件を追加するために、上記のようなイベントパターンになりました。

json構造を調べる
このjson構造は、Datadog、AWS側どちらのドキュメントにも記載がなく、実際に一度EventBridgeからLambdaに飛ばすなどし、スキーマの中身を取得してみるしかなかったです。
def lambda_handler(event, context): print(event) return 0
実際にlambdaから確認できたjson(例)は以下のような感じでした。
{ "version": "0", "id": "xxxxxxxx-xxxx-xxxxxxxxx-xxxxxxxxxxxxx", "detail-type": "Datadog Alert Notification", "source": "aws.partner/datadog.com/xxxxxxxxxxxxxx", "account": "xxxxxxxxxxxxx", "time": "2025-03-11T03:18:34Z", "region": "ap-northeast-1", "resources": [], "detail": { ~~~<省略>~~~ "meta": { "monitor": { "id": xxxxxxxxxx, "org_id": xxxxxxxxxxx, "type": "service check", "name": "[TEST] Container Status Check", "message": "{{#is_alert}}\n@awseventbridge-xxxxxxxxxxxxx \n{{host.name}} のContainerが起動していません\n{{/is_alert}} \n", "tags": [], "query": "\"tomcat.can_connect\".over(\"*\").by(\"host\").last(3).count_by_status()", ~~~<省略>~~~ "result": { "result_id": 0, "result_ts": 1741663112, "evaluation_ts": 0, "scheduled_ts": 0, "group": "host:instance-A", "group_key": "host", "state_id": 1, "avalanche": "False", "num_groups": 1, "groups": { "host:instance-A": { "status": 1 } }, ~~~<省略>~~~
EventBridgeにスキーマレジストリ > スキーマというメニューがあり、そこから取得することもできるが取得した内容がlambdaに送ったjsonと若干違いがありました。
⇒スキーマレジストリに関しては、スキーマの階層構造を示したものを出力していそうで、lambdaで取得したjsonは実際に送信されたデータを示しているという違いがありました。
構築手順
基本的にはCloudFormationだが、EventBusの作成のみDatadog側で実施する必要があります。
EventBusを作成後、cloudFormation内のEventBusの記述を更新し、適用します
cloudformationは最後に記載します
Datadog Monitor
DatadogのMonitorは以下のように設定します。
※ @awseventbridge-xxxxに関して、今回作成したイベントパターンに"alert_type": "error"を含んでいるため、Monitor内の一番上に記載して問題ないが、可読性のために{{#is_alert}}内に記述することにする。
@slack-datadog-alert
{{#is_alert}}
{{host.name}} のContainerが起動していません
EventBridgeへイベントを送信し再起動コマンドを実行します
@awseventbridge-xxxxxxxxxxxxxxxxx //⇐ここがトリガーになる
{{/is_alert}}
{{#is_alert_recovery}}
{{host.name}} のContainerが起動しました
{{/is_alert_recovery}}
cloudformation
AWSTemplateFormatVersion: '2010-09-09' Description: CloudFormation template for EventBridge Parameters: EventBusName: Type: String Default: 'aws.partner/datadog.com/xxxxxxxxxxxxxxxx' Resources: # ------------------------------------------------------------# # IAM Role for EventRule # ------------------------------------------------------------# IAMRoleEventRule: Type: AWS::IAM::Role Properties: RoleName: Amazon_EventBridge_Rule_Target_Recrete-Container AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: events.amazonaws.com Action: sts:AssumeRole MaxSessionDuration: 3600 Tags: [] PolicyEventRule: Type: AWS::IAM::RolePolicy Properties: PolicyName: Amazon_EventBridge_Invoke_Run_Command_Recreate-Container RoleName: !Ref IAMRoleEventRule PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: ssm:SendCommand Resource: - !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/* - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-RunShellScript # ------------------------------------------------------------# # EventRule # ------------------------------------------------------------# ERRecreateContainerInstanceA: Type: AWS::Events::Rule DependsOn: - IAMRoleEventRule - PolicyEventRule Properties: Name: Recreate-Container-InstanceA EventPattern: >- { "source":[{"prefix":"aws.partner/datadog.com"}], "detail-type": [{"prefix":"Datadog Alert Notification"}], "detail":{ "alert_type":[{"prefix":"error"}], "meta":{ "result":{ "group":[{"suffix":"Instance-A"}] } } } } State: ENABLED EventBusName: !Ref EventBusName Targets: - Id: "SSMRunCommandTarget" Arn: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-RunShellScript RoleArn: !GetAtt IAMRoleEventRule.Arn Input: >- { "executionTimeout":["300"], "commands":[ "sudo docker compose -f /root/docker-compose.yml down && sudo docker compose -f /root/docker-compose.yml up -d" ] } RunCommandParameters: RunCommandTargets: - Key: tag:Name Values: - Instance-A ERRecreateContainerInstanceB: ERRecreateContainerInstanceC: # <省略>
Datadog-synthetics-内部ローカルの監視(ECS Fargate)
概要
syntheticsのURL監視において内部ローカルの監視を行う
内部ローカルの監視には内部IPにアクセスできる場所にdatadogの提供するコンテナを立てて監視を行う
ドキュメント
https://docs.datadoghq.com/ja/synthetics/private_locations/?tab=docker
VPCに所属しているECSなので、イントラサイトの名前解決は、Route53のプライベートホストゾーンから行っている。
作業手順
1. jsonファイルの作成
datdogの[Digital Experience] > [Synthetic Monitoring&Testing] > [Setting]からPrivate Locationを追加する
画面の通りに設定していくと、Bash Scriptが提供されるので内容をメモしておく
View Installation Instructionsを押下し次の画面に移る
先ほどメモしたBashScriptをそのままコマンドで実行する
keyファイルがjsonで生成されるのでそのファイルを確認
2. ECS タスク定義の作成
下記のような感じでタスク定義を作成する。
command内には1で作成したjsonの中身を代入していく
{
"family": "datadog-synthetics-private-location",
"containerDefinitions": [
{
"name": "datadog-synthetics-private-location",
"image": "public.ecr.aws/datadog/synthetics-private-location-worker:latest",
"cpu": 0,
"portMappings": [],
"essential": true,
"environment": [],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "<cloudwatch-log-group>",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"command": [
"--site='datadoghq.com'",
"--accessKey='...'",
"--datadogApiKey='...'",
"--secretAccessKey='...'",
"--privateKey='-----BEGIN RSA PRIVATE KEY-----XXXXXXXX-----END RSA PRIVATE KEY-----'",
"--publicKey.pem='-----BEGIN PUBLIC KEY-----XXXXXXXX-----END PUBLIC KEY-----'",
"--publicKey.fingerprint='...'"
]
}
],
"executionRoleArn": "arn:aws:iam::<aws-account>:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
}
}
3. cloudwatchロググループの作成
タスク定義に設定したロググループを作成する。
4. クラスタとサービスの作成
ECSクラスタとサービスを作成する。
通常通り作成する。SGはアウトバウンドが全許可になっていればいい。
※インバウントはしっかりと検証していないのでもしかしたら必要なポートがあるかもしれない。


5. Datadogコンソールからsyntheticsテストを作成する
syntheticsテストを作成するときに新しく作成したprivate-locationを選択する。

Datadog-URL監視
概要
URL監視を設定する手順を記載する
URL監視(synthetics)は、1回あたりで値段がかかるため、契約に応じて何分に一回にするか決める
作業手順
通常のURLテスト
左側メニュー[UX Monitoring]より、[New Test] > [API Test]を選択する
1. Choose request type
[HTTP]を選択
- Define request
[GET]を選択し、監視するURLを記述する
[Test URL]をクリックし、実際に監視できるかを確認する、ステータスコードで300番台が返ってきた場合は、リダイレクト設定があるため、[Advanced Options]でFollow redirectsにチェックを入れる(最大10個までリダイレクトさせることができる)
必要であれば、Tagを付加する
3. Define assertions
どうなったらOKかを定義する、現状は下記のような設定になっている
When [status code] [is] [200]
4. Select locations
監視する場所を選択する、2か所選択するとsynthetics2回分になってしまうので、必要最低限の1か所を選択する(ここではTokyo)
また、プライベートロケーション(内部IP or Hosts定義URL)の監視にはPrivate Locationを選択する
5. Define retry conditions
失敗した場合の挙動を設定する、現状は下記の設定
Retry test [3] times after [5000] ms in case of failure
※失敗したら、5秒おきに3回リトライする
6. Define scheduling and alert conditions
何分間隔で監視を行うかを定義する、現状は2分間隔
また、下記の設定を行うことで[5.]で失敗した後どのくらいfailだったらアラートを発報するか定義できる
An alert is triggered if your test fails for [3] minutes from any [1] of 1 location
※5で指定した回数リトライしてすべて失敗した場合、3分間ずっとfailだった場合はアラートが発報される
2分間に1回の監視のため、もう一度URL監視が行われそれでもすべて失敗した場合はアラートが発報される
Configure the monitor for this test
タイトル:[URL Monitor]URL
内容:@slack-datadog-alert
{{#is_alert}}
下記URLが参照できません。
https://example.com/
{{/is_alert}}{{#is_alert_recovery}}
下記URLが参照できるようになりました。
https://example.com/
{{/is_alert_recovery}}Set permissions
このAPI Testを編集できる権限を選択する

Datadog-CPU使用率を監視する
概要
cpu使用率を監視するMonitor設定を作成する
事前に各サーバにdatadog-agentをインストールしておく必要あり
作業手順
左側メニューより、[Monitors]を選択する

[Metric]を選択する

- [Threshold Alert]を選択
[
Multi Alert] Trigger a separate alert for each [host] reporting your metricを選択a : [
system.cpu.system] from [!dev] avg by [host]
b : [system.cpu.user] from [!dev] avg by [host]
→ [a + b]
※[!dev]でdevというtagのついているホストを除外している(! : NOT)

Alert thresh old : 85
Warning threshold : 75Notifi your team
タイトル:[Server Monitor] CPU load is very high
内容:@slack-datadog-alert
{{#is_alert}}
{{host.name}}のCPU使用率が85%を超えました
{{/is_alert}}
{{#is_alert_recovery}}
{{host.name}}のCPU使用率が85%を下回りました
{{/is_alert_recovery}}{{#is_warning}}
{{host.name}}のCPU使用率が75%を超えました
{{/is_warning}}
{{#is_warning_recovery}}
{{host.name}}のCPU使用率が75%を下回りました
{{/is_warning_recovery}}

Datadog-Slackへの通知を行う
概要
Monitorでslackへ通知を飛ばすためのセットアップ(slack Integration)と、実際に通知を飛ばす方法を解説する
作業手順
slack Integration
Integrationからslackを選択する
一番最初は、[connect slack account]からアカウントを追加する
それ以後は、[Add Channel]から通知を飛ばすチャンネルを追加する

Monitor内の記述方法
Monitorのアラートの内容を記述する部分に通知を飛ばしたいチャンネルを記載する
@slack-<channel名>
※例:slack-datadog-alert
メンバーへのメンション
また、メンションも飛ばすことができ下記のように記述する
<!here>
<!channel>
<!everyone>
<@userID>
グループメンションをするときは、グループIDを取得する必要がある。2年くらい前まではブラウザのHTMLを読んだりしないといけなかったが、今は普通に取得できるようになっていた。
slackを開く > [・・・(その他)] > [メンバーディレクトリ] > [ユーザグループ] > 対象のグループを選択 > [・・・] > [グループIDをコピーする]
<!subteam^グループID | グループ名>

参考文献
https://cross-black777.hatenablog.com/entry/2018/01/15/124355
AWS Athenaクエリの備忘録
概要
自分用にAthenaで使えるクエリを備忘として残します。
DBの作成
CREATE DATABASE `DB_name`
ALBのアクセスログのテーブルを作成(1日分)
テーブル作成
CREATE EXTERNAL TABLE IF NOT EXISTS `DB_name`.`table_name` ( `type` string, `time` string, `elb` string, `client_port` string, `target_port` string, `request_processing_time` string, `target_processing_time` string, `response_processing_time` string, `elb_status_code` string, `target_status_code` string, `received_bytes` string, `sent_bytes` string, `request` string, `user_agent` string, `ssl_cipher` string, `ssl_protocol` string, `target_group_arn` string, `trace_id` string, `domain_name` string, `chosen_cert_arn` string, `matched_rule_priority` string, `request_creation_time` string, `actions_executed` string, `redirect_url` string, `error_reason` string, `target_port_list` string, `target_status_code_list` string, `classification` string, `classification_reason` string ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES ( 'separatorChar' = ' ', 'quoteChar' = '\"', 'escapeChar' = '\\' ) STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://path/to/elb/log/YYYY/MM/DD/'
テーブル表示
SELECT * FROM "DB_name"."table_name"; -- フィルターなど SELECT elb,client_port,request FROM "alb_log"."accesslog_20240131" WHERE elb LIKE '%app/ALB-PRD-WEB%'; SELECT * FROM "alb_log"."accesslog_20240128" WHERE elb LIKE '%app/ALB-PRD-WEB%';
DB/Tableの削除
DROP DATABASE `DB_name`; # DBを削除 DROP TABLE `table_name`; # Tableを削除
NLBのクロスゾーン負荷分散はオンにしとけ、という話
概要
NLBのクロスゾーン負荷分散をオフにしていたために結構ダルめの障害調査をしないといけなくなった時の話を備忘としてまとめます。
構成
自社のサイトで、ALB⇒ECS Fargate(Nginx)⇒NLB⇒ECS Fargate(Django)のような構成を取っているサイトがあります。
※NLBのクロスゾーン負荷分散はデフォルトではオフのため、その重要性をよく知らないままオフにしていました。

障害と事象の詳細
ある日からこちらのサイトが200と504を行ったり来たりするようになりました。
事象を詳細に調べていくと、NLBをnslookupしたときにIPが1つしか返ってこないことがわかりました。
> nslookup <NLB DNS名> サーバー: xxxxxxxx.jp Address: xx.xx.xx.xx 権限のない回答: 名前: <NLB DNS名> Address: 10.xx.xx.xx #⇐ap-northeast-1c側のNLB-IP
NLBは1aと1cにいますから、本来であればIPを2つ返してくれるはずなんですが、、、
さらに調べていくと、ap-northeast-1aとap-northeast-1cでそれぞれ1つずつ起動していたはずのECSタスクがap-northeast-1cで2つ起動しているということがわかりました。
NLBがIPを片方しか返さなかったのは、単純に1cにしかタスクがないからでした。
「え、、、?Fargateのタスクって均等に分散配置してくれるんじゃないの?」
調べたら、絶対にそうというわけではなく、ベストエフォートで対応してくれるみたいです。
Fargate は、アクセス可能なアベイラビリティーゾーンにタスクを分散するよう最善を尽くします。
サイトが200と504を繰り返していた理由
そして、なぜサイトが200と504のステータスを行ったり来たりしていたのかというと、
Nginxはconf内に記載しているドメインの名前解決を起動時にしか行ってくれないためでした。
こちらの記事を参考にしました。
qiita.com
自社の環境のnginxはdjangoへ通信を送るためにNLBのDNS名をnginx.confに記載しています。(詳細にはECSのタスク定義側で環境変数として渡しています)
起動時にはNLBの名前解決で、1aと1cの両方が返ってきていたのでこの2つを保持していたみたいです。
そのため、Nginxさんは1aのタスクがなくなったことにも気づかず健気に1aのNLBへリクエストを送っていたため、サイトが200と504を繰り返してしまったというわけです。
対応
まず、障害になったとき一番初めに、nginx被疑としてnginxのECSサービスのタスクを再デプロイしました。
その段階で、障害は直りました。nginxが再起動したためにNLBのIPが1cしか読み込まれなくなったため1aにリクエストを送らなくなり、障害は直ったということです。
しかし、もちろんこれでは正しく復旧できたと言えません。
なので、今後もdjangoのタスクが1cや1aに偏っても、nginx側が対応できるように「クロスゾーン負荷分散をオン」にして、再発を防ぎます。
クロスゾーン負荷分散がオンになっていると、タスクが片方のリージョンに偏ってもNLB自体はゾーンを跨いでリクエストをECS側へ送ってくれます。

一応、その後nginxやdjangoのサービスは再起動(タスクを再デプロイ)しておいた方が無難でしょう。
datadog-agentで認識しているInstance IDについて
概要
datadogのコンソール画面でAWSと連携をさせたときに、ホスト名が正しく認識されず、AWSの情報とAgentの情報が正しく同期されない問題があった
本記事では、問題の原因と対策について記載する
新しくインスタンスを立てたとき、または、既存のインスタンスにAgentを新たにインストールしたときに正しい情報を取得できるのかを判断する
画像:ホスト名とAWSから見えるホスト名が一致していない事象

問題の原因
問題の原因は、datadog-agent(EC2)側にあった。
そのためAWS IntegrationをしたときのAWS側に原因があるわけではない。
datadog-agentはそのインスタンスのインスタンスIDとホスト名を識別するために以下のコマンドの結果を見ている
curl http://169.254.169.254/latest/meta-data/instance-id curl http://169.254.169.254/latest/meta-data/hostname
しかし、このコマンドの結果が意図しないものになっていたことにより、Agentで認識するインスタンスIDが別のものになる事象が発生していた。
今後の対策
本事象はルーティング設定に問題があった。 そのためルーティングに以下の設定を追加することで事象を解決することができた
ip route add 169.254.169.254 dev eth0
しかし、上記設定は一時的なものにすぎないため恒久化するために以下の操作が必要になる
vi /etc/sysconfig/network-scripts/route-eth0 # ===下記を追記する=== 169.254.169.254 dev eth0 service network restart # (または、# systemctl restart network)
Datadog-プロセスチェック
概要
Datadogで任意のプロセスを監視するためにこの設定を行う。
psコマンドの結果をGrepしてプロセスが生きているかどうかを判定しているっぽい。
まああくまでそのプロセスを監視する手段がdatadog側に用意されてなかったときの最終手段的な監視方法なので多用することはなさそう。
CentOS5系とかめっちゃ古いサーバでdatadogの標準監視が使用できないみたいなときに使った
sshd, ntpd, crondなど一般的なプロセスの監視と、そのサーバ固有のプロセス(httpdやtomcat)などの監視設定を行う。
作業手順
Agent-7
ファイルを作成する
vi /etc/datadog-agent/conf.d/process.d/conf.yaml
search_string内の記述は、psコマンド結果に記載されている内容をメモして記述する
tomcatやapacheのプロセスチェックはサーバによって必要なら記載する
init_config: instances: - name: sshd search_string: ['sshd', 'ssh'] exact_match: False - name: chronyd search_string: ['chronyd'] exact_match: False - name: crond search_string: ['crond', 'cron'] exact_match: False - name: rsyslogd search_string: ['rsyslogd'] exact_match: False # 任意のプロセスを記載 # - name: dockerd # search_string: ['dockerd', 'docker'] # exact_match: False # - name: postfix # search_string: ['postfix'] # exact_match: False
chown dd-agent:dd-agent /etc/datadog-agent/conf.d/process.d/conf.yaml
agentを再起動する
systemctl restart datadog-agent datadog-agent status
Agent-5
ファイルを作成する
vi /etc/dd-agent/conf.d/process.yaml
search_string内の記述は、psコマンド結果に記載されている内容をメモして記述する
tomcatやapacheのプロセスチェックはサーバによって必要なら記載する
init_config: instances: - name: sshd search_string: ['sshd', 'ssh'] exact_match: False - name: ntpd search_string: ['ntpd'] exact_match: False - name: crond search_string: ['crond', 'cron'] exact_match: False - name: snmpd search_string: ['snmpd'] exact_match: False - name: syslogd search_string: ['syslogd'] exact_match: False # 任意のプロセスを記載 # - name: httpd # search_string: ['httpd'] # exact_match: False # - name: tomcat # search_string: ['tomcat'] # exact_match: False
chown dd-agent:root /etc/dd-agent/conf.d/process.yaml
agentを再起動する
service datadog-agent restart service datadog-agent info
datadog側でMonitorを作成
DatadogのMonitor作成画面でProcess Checkを選ぶと先ほど作成したプロセスを選択できるので好きなようにMonitorを作成する。

参考文献
Datadog-カスタムAgentチェック
概要
Datadogに標準装備されていないメトリクスをサーバから送りたいときにこの機能を使用する
例えば、サーバ内で実行したコマンドの実行結果をint型などで送信したい場合に使用する
作業手順
Agent7
今回はwebサーバにおけるtomcatへのセッション数を取得するカスタムAgentCheckを想定する(webサーバのdatadog-agentに設定)
/etc/dd-agent/conf.d/tomcat_session.d/conf.yaml
init_config: min_collection_interval: 30 instances: [{}]
/etc/dd-agent/checks.d/tomcat_session.py
import subprocess from datadog_checks.base import AgentCheck __version__ = "1.0.0" class TomcatSesstion(AgentCheck): def check(self, instance): key = "TomcatSession.<hostname>" cmd = "ss -n | grep \"<host IP address>:8009\" | grep ESTAB | wc -l" value = int(subprocess.check_output(cmd, shell=True)) self.gauge(key, value)
上記2ファイルを作成したら、datadog-agentを再起動する
チェックコマンド
sudo -u dd-agent -- datadog-agent check java_heap datadog-agent status
datadog上で確認
Metrics Explorerで実際にメトリクスが取得できているか確認する

Agent5
今回はjava heapを取得するカスタムAgentCheckを想定する
バグか仕様かわからないが、Agent5のカスタムメトリクスでは、subprocess関数でsudoが使えない
(Agent7では使用可能)
そのため、sudoを使うメトリクスの場合、Agentをrootで起動する
/etc/dd-agent/supervisor.conf 20 行目と 30 行目
cp -p /etc/dd-agent/supervisor.conf /etc/dd-agent/supervisor.conf.org vi /etc/dd-agent/supervisor.conf #---変更--- #user=dd-agent user=root
/etc/dd-agent/conf.d/java_heap.yaml
init_config: min_collection_interval: 30 instances: [{}]
/etc/dd-agent/checks.d/java_heap.py
import subprocess from checks import AgentCheck __version__ = "1.0.0" class JavaHeap(AgentCheck): def check(self, instance): key = "java_heap.Bootstrap_OU" cmd = "/usr/java/jdk/bin/jstat -gc -t `/usr/java/jdk/bin/jps | grep \"Bootstrap\" | awk '{print $1}'` | tail -n 1 | awk '{print $9}'" value = float(subprocess.check_output(cmd, shell=True)) self.gauge(key, value)
上記2ファイルを作成したら、datadog-agentを再起動する
service datadog-agent restart
チェックコマンド
dd-agent check java_heap service datadog-agent info
agent-7と同様にMetrics Explorer上で確認を行う
参考リンク
カスタム Agent チェック
https://docs.datadoghq.com/ja/developers/write_agent_check/?tab=agentv6v7
メトリクスの送信: カスタム Agent チェック
https://docs.datadoghq.com/ja/metrics/custom_metrics/agent_metrics_submission/?tab=gauge
Datadog-Tomcat Integration
概要
datadogのコンソール画面にtomcatの使用状況を表示する
また、このインテグレーションを実施すると同時にJVMのインテグレーションも行われる
環境
- datadog-agent: 5.9
- os: centOS5
- java: jdk1.6
centOS5/java1.6に対してのインテグレーションは検証済み
java1.5に対してのインテグレーションは、datadog-agent5.9側のjmx fetchのバージョンがjava1.5に対応していないため、エラーを吐いてしまう。
java1.5へはインテグレーション不可のため、取得したいメトリクスはカスタムAgentチェックで取得する
(カスタムAgentチェックの記事を参照すること)
CentOS5系へのAgentインストールはこちらの記事参照
ken-memo.hatenablog.com
もちろん最新OS、agent-7でのIntegrationは問題なく行える
作業手順
1. JMXリモートの有効化
JVMを外部監視するためにJMVを有効化する必要がある
また、Tomcatの再起動が必要
1.1 setenv.shにオプションを追加
tomcatの起動オプションにjmxリモートを有効化するオプションを追加する
tomcatは起動をスクリプト化しており、オプションに関してはsetenv.shに記述してある
cd /usr/local/tomcat/bin cp -p setenv.sh setenv.sh.`date "+%Y%m%d"` vi setenv.sh #CATALINA_OPTSを作成、すでにある場合は追記 CATALINA_OPTS=" -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.port=9012 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
1.2 Tomcat再起動
Tomcatの再起動を行う
2. Datadog側 コンフィグファイルの作成
2.1 コンフィグファイルの作成
Tomcat用のコンフィグファイルを作成する
中身を見るとポート番号を指定する箇所があるため1.1でport=9012を指定している
cd /etc/dd-agent/conf.d cp -p tomcat.yaml.example tomcat.yaml vi tomcat.yaml # --- 変更 --- java_bin_path: /usr/java/jdk/bin/java
2.2 Datadog再起動
service datadog-agent restart
CentOS5であれば、下記コマンドでtomcatインテグが機能しているか確認することができる
service datadog-agent info
また、しばらくするとtomcatの情報がdatadogコンソール画面に表示される
課題
この設定を入れたtomcatをshutdown.shのスクリプトで停止しようとすると下記のようなエラーが出て、停止できない
エラー: エージェントが例外をスローしました。 : java.rmi.server.ExportException: Port already in use: 9012; nested exception is:
java.net.BindException: Address already in use
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor72]
現在はkillコマンドでプロセスを強制終了させている
追記
下記にあるようにJAVA_OPTSではなく、CATALINA_OPTSで指定するとうまくいく
(記事内手順は更新済みです)
https://ameblo.jp/yukozutakeshizu/entry-12510068834.html
Datadog-Apache Integration
概要
datadog-agentでapacheの情報を取得する方法の手順
ブラウザのdatadogメニュー > [Integrations] > [apache] に書いてある方法を解説したものである
設定手順
apache側の設定
IPアクセス許可設定にlocalhost(127.0.0.1)が設定されている確認する
Location /配下のAllow fromにIPが入っていればよい
入っていない場合は、バックアップを取り追加する
cat /usr/local/apache/conf/vhosts/localhost.conf Allow from 127.0.0.1 ←確認 or 追加
apacheのステータスを見れるページが存在しているか確認する
ここがないと設定しても404 Client Error: Not Found for url...と言われてしまう
またstatus情報を取ることはできない
※./httpd.conf内の./extra/httpd-info.confがコメントアウトされていたため、404になっていたことがある
curl http://localhost/server-status?auto
該当のモジュールがオンになっているか確認する
なっていない場合はバックアップを取りコメントアウトを外す
cat /usr/local/apache/conf/httpd.conf | grep modules/mod_status.so
万が一モジュールの記述が見つからない場合は下記のコマンド status_module があるか確認する
httpd -M # もしくは、 /usr/local/apache/bin/httpd -M
Extended statusがOnになっているか確認する
なっていない場合はバックアップを取りコメントアウトを外す
また、Allow from 127.0.0.1 が入っているか確認する
cat /usr/local/apache/conf/extra/httpd-info.conf
apacheを再起動する
reloadでもrestartでもstop/startでもgracefulでも好きな方法で実施する
datadog側の設定
Metricsを取得するための設定
apacheの設定yamlファイルを作成する(exampleがあるか確認)
内容についてはそのままでよい
# agent-7 ll /etc/datadog-agent/conf.d/apache.d/ cp -p /etc/datadog-agent/conf.d/apache.d/conf.yaml.example /etc/datadog-agent/conf.d/apache.d/conf.yaml ll /etc/datadog-agent/conf.d/apache.d/ # agent-5 ll /etc/dd-agent/conf.d/apache.yaml* cp -p /etc/dd-agent/conf.d/apache.yaml.example /etc/dd-agent/conf.d/apache.yaml ll /etc/dd-agent/conf.d/apache.yaml*
logを取得するための設定(agetn-7のみサポート)
logの取得は結構な課金になるため契約していない場合はやめておいた方が無難。
datadog.yamlの設定
# agent-7 cp -p /etc/datadog-agent/datadog.yaml /etc/datadog-agent/datadog.yaml.org vi /etc/datadog-agent/datadog.yaml # 下記の設定を加える # 変更前 --- # logs_enabled: false # 変更後 # ※インデントに注意, 一番左でスペースなし --- # logs_enabled: false logs_enabled: true
apacheコンフィグファイルの設定(Metricsで作成したもの)
ファイルの一番下にコメントアウトしてあるlogの項目があるのでコメントアウトを外して編集する
※インデントに注意, logs:は一番左でスペースなし
pathに取得したいドメインのaccess_log, error_logを記載することでdatadog上で見れるようになる
複数指定するときは、-type: fileを複数指定する?sourcecategoryを一意にする必要があるかも(要検証)
vi /etc/datadog-agent/conf.d/apache.d/conf.yaml
# 編集
---
logs:
- type: file
path: /home/www/localhost/logs/apache/access_log
source: apache
service: apache
sourcecategory: http_web_access
- type: file
path: /home/www/localhost/logs/apache/error_log
source: apache
service: apache
sourcecategory: http_web_error
保存してdiffを取る
diff /etc/datadog-agent/conf.d/apache.d/conf.yaml /etc/datadog-agent/conf.d/apache.d/conf.yaml.example
datadog-agentの再起動
ブラウザで確認
datadogのページで設定が反映されているか確認する
設定の反映には10分程度かかることがある
Datadog-SNMP Integration
概要
Datadog-agentを用いてSNMP Integrationの方法を説明する。
デフォルトのSNMP Integrationでは基本的なSNMPのメトリクス(CPU使用率など)しか取得できないので、追加でOIDなどを指定したいときは製品のMIB情報をAgentに含める必要がある。
また、SNMP Trapにも対応している。
作業手順
基本設定
1. conf.d/は以下ファイルの作成
datadog-agentに新たに配置するconfig.yamlを作成する
今回の場合、conf.d/snmp.d/config.yamlファイルを作成する
例として、cisco2960Xを監視することを考える
init_config: loader: core use_device_id_as_hostname: true instances: - ip_address: xx.xx.xx.xx snmp_version: 2 community_string: 'test-string' tags: - hostname:switch-1 - devicename:cisco2960X - ip_address: xx.xx.xx.yy snmp_version: 2 community_string: 'test-string' tags: - hostname:switch-2 - devicename:cisco2960X ・・・
カスタムOIDの設定方法
推奨形式
標準のOID以外でSW独自のOIDを設定したい場合は下記のように設定する。
OIDの確認方法はSWのMIBを入手し確認する。詳細については省略する。
MIBをインポートしての設定はAgent7.27移行はサポートされなくなっている。
(python形式を指定して設定すること自体は可能、次項の手順参照。ただDeviceがダッシュボードに表示されなくなるなどの不具合が見つかっているため推奨しない。)
今回BIG-IPのカスタムOIDを取得する場合を例に説明する。
init_config: loader: core use_device_id_as_hostname: true min_collection_interval: 5 instances: # BIG-IP - ip_address: xx.xx.xx.xx snmp_version: 2 community_string: 'test-string' metrics: - symbol: OID: 1.3.6.1.4.1.3375.2.1.14.1.1 name: sysCmSyncStatusId - symbol: OID: 1.3.6.1.4.1.3375.2.1.14.3.1 name: sysCmFailoverStatusId tags: - hostname:big-ip-1 - devicename:F5BIG-IP
Python形式(従来)
Agent7.27以降では上記のやり方(loader:core)での設定が推奨されている。
下記手順は従来のPythonを利用した方法である。
python形式に変換したMIBファイルを読み込ませて大量のOIDを設定することができるが、Deviceがダッシュボードに表示されなくなるなどの不具合が見つかっているため推奨しない。
Python ベースのチェックから SNMP Core チェック (Go) への移行
手順1と2はローカル上で実施してよい
1. MIBファイルの取得
BIG-IPであればダッシュボードの下の方から取得できる。
-r--r--r-- 1 502 users 132284 Apr 8 2021 F5-BIGIP-APM-MIB.txt -r--r--r-- 1 502 users 68399 Apr 8 2021 F5-BIGIP-COMMON-MIB.txt -r--r--r-- 1 502 users 302105 Apr 8 2021 F5-BIGIP-GLOBAL-MIB.txt -r--r--r-- 1 502 users 1404972 Apr 8 2021 F5-BIGIP-LOCAL-MIB.txt -r--r--r-- 1 502 users 823583 Apr 8 2021 F5-BIGIP-SYSTEM-MIB.txt -r--r--r-- 1 502 users 17385 Apr 8 2021 F5-BIGIP-WAM-MIB.txt
また、依存関係のあるMIBを取得しないといけないので、それをインターネットから拾ってくる
-rw-r--r-- 1 root root 17602 Jun 15 2022 INET-ADDRESS-MIB.mib -rw-r--r-- 1 root root 4064 Jun 15 2022 RFC1155-SMI.mib -rw-r--r-- 1 root root 547 Jun 15 2022 SNMPv2-CONF.mib -rw-r--r-- 1 root root 32810 Jun 15 2022 SNMPv2-MIB.mib -rw-r--r-- 1 root root 9268 Jun 15 2022 SNMPv2-SMI.mib -rw-r--r-- 1 root root 35914 Jun 15 2022 SNMPv2-TC.mib
2. Python形式への変換
$ sudo pip install pysnmp pysnmp-mibs $ mibdump.py <MIBファイルを格納しているディレクトリ>/*
出力例
[2024-02-21 17:17:57.372] root@xxxx:/etc/datadog-agent/conf.d/snmp.d/mibs# mibdump.py ./* [2024-02-21 17:18:41.868] Source MIB repositories: /etc/datadog-agent/conf.d/snmp.d/mibs, file:///usr/share/snmp/mibs, http://mibs.snmplabs.com/asn1/@mib@ [2024-02-21 17:18:41.875] Borrow missing/failed MIBs from: http://mibs.snmplabs.com/pysnmp/notexts/@mib@ [2024-02-21 17:18:41.875] Existing/compiled MIB locations: pysnmp.smi.mibs, pysnmp_mibs [2024-02-21 17:18:41.875] Compiled MIBs destination directory: /etc/datadog-agent/conf.d/snmp.d/mibs_py [2024-02-21 17:18:41.875] MIBs excluded from code generation: INET-ADDRESS-MIB, PYSNMP-USM-MIB, RFC-1212, RFC-1215, RFC1065-SMI, RFC1155-SMI, RFC1158-MIB, RFC1213-MIB, SNMP-FRAMEWORK-MIB, SNMP-TARGET-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC, SNMPv2-TM, TRANSPORT-ADDRESS-MIB [2024-02-21 17:18:41.875] MIBs to compile: F5-BIGIP-APM-MIB, F5-BIGIP-COMMON-MIB, F5-BIGIP-GLOBAL-MIB, F5-BIGIP-LOCAL-MIB, F5-BIGIP-SYSTEM-MIB, F5-BIGIP-WAM-MIB, INET-ADDRESS-MIB, RFC1155-SMI, SNMPv2-CONF, SNMPv2-MIB, SNMPv2-SMI, SNMPv2-TC [2024-02-21 17:18:41.875] Destination format: pysnmp [2024-02-21 17:18:41.875] Parser grammar cache directory: not used [2024-02-21 17:18:41.875] Also compile all relevant MIBs: yes [2024-02-21 17:18:41.875] Rebuild MIBs regardless of age: no [2024-02-21 17:18:41.875] Dry run mode: no [2024-02-21 17:18:41.875] Create/update MIBs: yes [2024-02-21 17:18:41.896] Byte-compile Python modules: yes (optimization level no) [2024-02-21 17:18:41.896] Ignore compilation errors: no [2024-02-21 17:18:41.896] Generate OID->MIB index: no [2024-02-21 17:18:41.896] Generate texts in MIBs: no [2024-02-21 17:18:41.896] Keep original texts layout: no [2024-02-21 17:18:41.896] Try various file names while searching for MIB module: yes [2024-02-21 17:18:44.773] Created/updated MIBs: F5-BIGIP-APM-MIB, F5-BIGIP-COMMON-MIB, F5-BIGIP-GLOBAL-MIB, F5-BIGIP-LOCAL-MIB, F5-BIGIP-SYSTEM-MIB, F5-BIGIP-WAM-MIB [2024-02-21 17:18:44.778] Pre-compiled MIBs borrowed: [2024-02-21 17:18:44.778] Up to date MIBs: INET-ADDRESS-MIB, RFC1155-SMI, SNMPv2-CONF, SNMPv2-MIB, SNMPv2-SMI, SNMPv2-TC [2024-02-21 17:18:44.778] Missing source MIBs: [2024-02-21 17:18:44.778] Ignored MIBs: [2024-02-21 17:18:44.778] Failed MIBs:
依存関係のあるMIBが不足している場合は、Missing source MIBs:に記載のMIBファイルが足りていなのでネットから拾ってきて配置する
3. config.yamlの更新
python形式のMIBファイルが格納されているフォルダのパスと、Metrics化したい値を記載する。
フォルダに格納したMIBファイルの値すべてがMetrics化されるわけではないので注意
conf.d/snmp.d/config.yaml
init_config: loader: python use_device_id_as_hostname: true min_collection_interval: 15 mibs_folder: /etc/datadog-agent/conf.d/snmp.d/mibs_py instances: - ip_address: xx.xx.xx.xx snmp_version: 2 community_string: 'test-string' metrics: - MIB: F5-BIGIP-SYSTEM-MIB symbol: sysCmSyncStatusId tags: - hostname:dclb01 - devicename:F5BIG-IP
SNMP Trap
datadog.yamlの設定
/etc/datadog-agent/datadog.yamlに下記を記載する community_stringについては、適切なものを記入する
network_devices: snmp_traps: enabled: true port: 9162 community_strings: - test-string bind_host: 0.0.0.0
SNMPエージェント機器側のTrap設定
機器にSNMP Trapの設定を行う
ECS化
EC2を1台立てて管理するのも割に合わないのでコンテナ化してECSで管理することを考える
上記作成したconfigファイルを用いてDockerfileを作成する。
FROM gcr.io/datadoghq/agent:latest ADD conf.d/snmp.d/conf.yaml /etc/datadog-agent/conf.d/snmp.d/conf.yaml
ECRへプッシュ
ECRリポジトリがない場合は先に作成してください
ECR login
aws ecr get-login-password --profile <profile> --region ap-northeast-1 | docker login --username AWS --password-stdin <account-id>.dkr.ecr.ap-northeast-1.amazonaws.com
Container build
docker build -t <account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/datadog-standalone-custom-agent:latest .
Image push to ECR
docker push <account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/datadog-standalone-custom-agent:latest
タスク定義の作成
※cloudwatch log groupは先に作成しておいてください。起動できません。
{ "family": "datadog-standalone-custom-agent", "containerDefinitions": [ { "name": "datadog-agent", "image": "<repository uri>:<tag(latestなど)>", "cpu": 0, "portMappings": [ { "containerPort": 8126, "hostPort": 8126, "protocol": "tcp" } ], "essential": true, "environment": [ { "name": "ECS_FARGATE", "value": "true" }, { "name": "DD_API_KEY", "value": "xxxxxxxxxxxxxxxxxxxxxx" }, { "name": "DD_HOSTNAME", "value": "prd-ecs-custom-agent-01" }, { "name": "DD_DOGSTATSD_NON_LOCAL_TRAFFIC", "value": "true" }, { "name": "DD_PROCESS_AGENT_ENABLED", "value": "true" } ], "mountPoints": [], "volumesFrom": [], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/datadog/fargate", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "datadog-standalone-custom-agent" } } } ], "taskRoleArn": "<taskRoleArn>", "executionRoleArn": "<TaskExecutionRoleArn>", "networkMode": "awsvpc", "volumes": [], "placementConstraints": [], "requiresCompatibilities": [ "FARGATE" ], "cpu": "256", "memory": "512", "runtimePlatform": { "cpuArchitecture": "X86_64", "operatingSystemFamily": "LINUX" } }
ECSクラスタの作成とECSサービスの作成
ECSクラスタを作成、先ほどのタスク定義を使用したECSサービスを作成します。
今回の場合、インバウンドのセキュリティグループには特に必要な項目はありません*。アウトバウンドは0.0.0.0/0で全許可しておいてください。(デフォルト)
*:SNMPはこちらから機器に取りに行くのでアウトバウンドが開いていれば取得できます。(セキュリティグループはステートフルなため)
Datadog側で確認
[Infrastructure] > [Network Devices]へアクセスし、ネットワーク機器が表示されていればOKです。
CentOS5にDatadog-agentをインストールする
概要
基本的にDatadog-agentのインストールは公式サイトやGUIのIntegrationタブから手順を確認できるが、CentOS5などめちゃくちゃ古いOSについては記載がない。
社内での対応でCentOS5にAgent-5をインストールする必要があり手順について検証したので備忘として残しておく。(agent-7についてはいろいろ試したがインストールできなかった。)
令和のこの時代にCentOS5を使用するセキュリティリスクについては重々承知かと思うが、datadog-agent5についても公式からは推奨されていないはずなのでその辺は自己責任で。
作業手順
datadog-agent 5のインストール
httpsは通らないので仕方なくhttpで実行
cd /tmp wget http://yum.datadoghq.com/rpm/i386/datadog-agent-5.9.1-1.i386.rpm rpm -ivh /tmp/datadog-agent-5.9.1-1.i386.rpm
最後のrpmコマンドはdatadog.confがないため起動に失敗する。次の手順でdatadog.confを作成するため想定通り
# rpm -ivh datadog-agent-5.9.1-1.i386.rpm 警告: datadog-agent-5.9.1-1.i386.rpm: ヘッダ V3 DSA signature: NOKEY, key ID 4172a230 準備中... ########################################### [100%] find: /opt/datadog-agent: そのようなファイルやディレクトリはありません 1:datadog-agent ########################################### [100%] Stopping Datadog Agent (using killproc on supervisord): [失敗] /etc/dd-agent/datadog.conf not found. Exiting.
設定ファイルの作成
cd /etc/dd-agent cp -p datadog.conf.example datadog.conf sed -i -e 's/^api_key:/api_key: <api_key>/g' datadog.conf cat datadog.conf | grep -v -e '^#' -e '^ *#' -e '^$'
CERTIFICATE_VERIFY_FAILED エラーへの対応
datadog.confを設定してもまだエラーが出るため以下対応を行う
datadog-cert.pemを削除する(削除ではなくmvで対応)
mv /opt/datadog-agent/agent/datadog-cert.pem /opt/datadog-agent/agent/datadog-cert.pem.org
datadog-agentの起動
service datadog-agent start #ちなみに、stop, status, restartも実行できる
うまく取り込めない場合
/var/log/datadog/forwarder.log内のエラーを確認
Route53でIPベースルーティングを活用する
概要
「社内からは新しい環境のサイト、その他世界中からは現運用されているサイト、という感じで、DNSの問い合わせ結果をIPアドレスによって制御したい。」
というときにRoute53のIPベースルーティング設定を行うことで実現できる
作業手順
1. CIDR コレクションの作成(初回のみ)
CIDRコレクションを作成する
ここに適切な名前と、CIDRブロックを入力する
CIDRブロックには基本的に自分が持っているグローバルIPを入力するが、組織の環境だとIP確認サイトなどで確認できるIPとDNSへ問い合わせを行っているIPが違うこともあるので下記の記事を閲覧して確認することが望ましい
パブリック DNS リゾルバーが EDNS Client Subnet (ECS) 拡張機能をサポートしているかどうかを確認するには、どうすればよいですか?
後から編集して場所を追加することや、CIDRブロックを追加することもできる

2. 既存DNSレコードの編集
今回対象のドメインはすでにDNSに登録されているものとし、これをIPベースルーティングへと編集する
CIDRコレクションを作成出来たら、「シンプルルーティング」になっている既存のレコードをIPベースルーティングに書き換える必要がある
「レコードを編集」をクリックし、「ルーティングポリシー」を「IPベース」に変更する
- ルーティングポリシー:IPベース
- IPベース:*(デフォルトの場所)
- ヘルスチェックID:なし
- レコードID:default ※備考なので好きな内容でOK
IPベースを「*(デフォルトの場所)」にすることでアクセス制御するIP以外のIPからアクセスが来た時の挙動を設定する

3. DNSレコードの作成
次に特定のIPからアクセスが来た場合に参照させるレコードを作成する

それぞれの設定値(今回ALB)
- レコード名:対象のレコード名
- レコードタイプ:Aレコード
- エイリアス:オン
- トラフィックのルーティング先
- ルーティングポリシー:IPベース
- IPベース:先ほど設定したもの
- ヘルスチェックID:なし
- ターゲットのヘルスを評価:オフ
- レコードID:office-ip ※備考なので好きな内容でOK
内容を入力して作成すると同じ名前のAレコードが2つ作成されている状態になる

4. 接続確認
社内からは下記のコマンドでALBのIPが返ってくればOK
社外からはデフォルトのIPが返ってくればOK
nslookup <DOMAIN>
参考文献
【新機能】Amazon Route 53 でアクセス元 IP をベースとしたルーティングがサポートされました
https://dev.classmethod.jp/articles/amazon-route-53-now-supports-routing-based-on-source-ip/
[アップデート] Amazon Route 53のPublic Hosted ZoneでIPベースルーティングができるようになりました
https://dev.classmethod.jp/articles/amazon-route-53-ip-based-routing-dns-queries/
パブリック DNS リゾルバーが EDNS Client Subnet (ECS) 拡張機能をサポートしているかどうかを確認するには、どうすればよいですか?
https://repost.aws/ja/knowledge-center/route-53-find-ecs-support-dns-resolver