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と若干違いがありました。

dev.classmethod.jp

スキーマレジストリに関しては、スキーマの階層構造を示したものを出力していそうで、lambdaで取得したjsonは実際に送信されたデータを示しているという違いがありました。

構築手順

基本的にはCloudFormationだが、EventBusの作成のみDatadog側で実施する必要があります。

dev.classmethod.jp

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]を選択

  1. 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監視が行われそれでもすべて失敗した場合はアラートが発報される

  1. 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}}

  2. Set permissions
    このAPI Testを編集できる権限を選択する

Datadog-CPU使用率を監視する

概要

cpu使用率を監視するMonitor設定を作成する

事前に各サーバにdatadog-agentをインストールしておく必要あり

作業手順

左側メニューより、[Monitors]を選択する

[Metric]を選択する

  1. [Threshold Alert]を選択
  2. [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)

  1. Alert thresh old : 85
    Warning threshold : 75

  2. Notifi 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 は、アクセス可能なアベイラビリティーゾーンにタスクを分散するよう最善を尽くします。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-placement.html#fargate-launch-type

サイトが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)

この操作を行った後、正しいインスタンスIDが取得できるかcurlコマンドにて確認する

Datadog-プロセスチェック

概要

Datadogで任意のプロセスを監視するためにこの設定を行う。

psコマンドの結果をGrepしてプロセスが生きているかどうかを判定しているっぽい。

まああくまでそのプロセスを監視する手段がdatadog側に用意されてなかったときの最終手段的な監視方法なので多用することはなさそう。

CentOS5系とかめっちゃ古いサーバでdatadogの標準監視が使用できないみたいなときに使った

sshd, ntpd, crondなど一般的なプロセスの監視と、そのサーバ固有のプロセス(httpdtomcat)などの監視設定を行う。

作業手順

Agent-7

ファイルを作成する

vi /etc/datadog-agent/conf.d/process.d/conf.yaml

search_string内の記述は、psコマンド結果に記載されている内容をメモして記述する
tomcatapacheのプロセスチェックはサーバによって必要なら記載する

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コマンド結果に記載されている内容をメモして記述する
tomcatapacheのプロセスチェックはサーバによって必要なら記載する

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を作成する。

参考文献

プロセス
https://docs.datadoghq.com/ja/integrations/process/

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で起動する

docs.datadoghq.com

/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公式の下記ページを参照
https://docs.datadoghq.com/ja/agent/faq/certificate_verify_failed-error/#agent-%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%81%9B%E3%81%9A%E3%81%AB%E4%BF%AE%E6%AD%A3%E3%81%99%E3%82%8B

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