Docker×Datadog×PHP実装まとめ(APM編)

### 概要
Datadogを使って、Docker(ECS)で実装しているPHPウェブアプリのメトリクスを収集し、Datadogコンソール（APMService）で監視できるようにする。

### アウトライン
・PHPコンテナに、DatadogAPMの計測設定
・ローカル開発環境（docker-compose）で、datadog/agentコンテナを実装
・クラウド開発環境（ECS）で、datadog/agentコンテナを実装

### 作業ログ
#### PHPコンテナに、DatadogAPMの計測設定

・PHPにDatadog拡張機能(datadog-php-tracer)をインストール
→PHPコンテナのDockerfileにインストールする。

```dockerfile
ENV DDTRACE_VERSION=0.30.1
RUN curl -Lo datadog-php-tracer.apk https://github.com/DataDog/dd-trace-php/releases/download/${DDTRACE_VERSION}/datadog-php-tracer_${DDTRACE_VERSION}_noarch.apk \
&& apk add datadog-php-tracer.apk --allow-untrusted \
&& rm datadog-php-tracer.apk
```

※コンテナを実行して、↓phpinfo()でインストールされていることを確認
<img width="1061" alt="83EB3AE9-FBA4-4C11-8B98-30BD6F8A12BD.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400875/f1cfb1dd-9cc1-a870-a082-7f06dcd2d95f.png">

※datadog-php-tracerをインストールするだけで、勝手に計測してdatadog/agentのEPに計測データを送信してくれる。


#### ローカル開発環境（docker-compose）で、datadog/agentコンテナを実装

ローカルでコンテナを実行し、datadogコンソールにデータを送信できることを確認する。
↓構成としてはこんな感じ。
![local-env-datadog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400875/e948f766-15a2-7f34-fb60-5ec755342b9e.jpeg)

##### datadog/agentコンテナ
datadogの公式イメージ（[datadog/agent](https://hub.docker.com/r/datadog/agent/)）に、環境変数を設定して実行

- datadogのAPIキー

※キーは、Datadogコンソールの Integrations - APIs - API keys から確認

```yml
DD_API_KEY=***
```

- Datadog Agentのトレースメトリクスを有効にする。

```yml
DD_APM_ENABLED=true
```

- データ送信先サイトを設定

```yml
DD_SITE=datadoghq.com
```

- 非ローカルトラフィックのトレース許可

```yml
DD_APM_NON_LOCAL_TRAFFIC=true
```

##### PHPコンテナの設定

環境変数で計測データの設定を行う。

- datadog-agentコンテナのhost名を設定

```yml
DD_AGENT_HOST=datadog-agent
```

※datadog/agentのサービス名をdatadog-agentにしたのでそのまま設定(デフォルトはlocalhost)

- APM - Services名　（APMのサービス名）

```yml
DD_SERVICE_NAME=php-apm
```
<img width="994" alt="スクリーンショット_2019-11-25_18_55_56.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400875/67b1b86b-832d-0d3a-5bab-cbb72dd4b267.jpeg">

>docker-compose.yml


```yml
version: '3'
services:
  php-apache:
    container_name: php_apache_container
    build: ./php_apache_container
    volumes:
      - ./php_apache_container/src:/var/www/html
    environment:
      DD_AGENT_HOST: "datadog-agent"
      DD_SERVICE_NAME: "php-apache"
      DD_TRACE_GLOBAL_TAGS: "env:local,service:php-apache"
      DD_TRACE_ANALYTICS_ENABLED=true
    networks:
      - net


  datadog-agent:
    container_name: datadog-agent
    image: datadog/agent:latest
    environment:
      DD_API_KEY: "******"
      DD_APM_ENABLED: "true"
      DD_SITE: "datadoghq.com"
      DD_APM_NON_LOCAL_TRAFFIC: "true"
    networks:
      net:

networks:
  net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.16.238.0/24
```
※だいたい↑の感じ。。業務用コード、固有名詞をざっくり削除、編集したもの載せてます。動作は見てない。


##### クラウド開発環境（ECS）で、datadog/agentコンテナを実装

↓だいたい下記の感じで実装
![KAKUNIN_ECS-Sample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400875/e7506549-d6b2-c7b2-0053-3101d182cd06.jpeg)

・ECSはEC2モード
・PHPコンテナは、Replica、AWSVPCモード、Datadogコンテナは、Daemon、Bridgeモードで起動

>ENIの制限
<font color="#bbbbbb">
※使用するインスタンスタイプはENI数：３
AWSVPCモードだと１タスクにつき１つのENIを使用する為、ENI枯渇を防ぐ為、datadogコンテナはbridgeモードで実装</font>


##### PHPコンテナ→Datadogコンテナの通信経路

タスク間を跨いで通信する場合、直接通信できない為、Route53でPrivateHostedZone→ALBを通して、datadog/agentコンテナに計測メトリクスを送信する。
※サービス検出とSRVレコードを使った方法もあるらしいが、datadog-php-tracer(の通信に使ってるCURL)がSRVレコードに対応してないようなので使えない?ぽい。


>タスク定義

・ローカル環境でも設定した環境変数をenvironmentに設定
・APIキーはパラメータストアに設定して、ARNを指定
・portはdatadogAPM用ポート`８１２６`を設定
※terraformで管理してる為、設定値を${var}の形で外部から設定できるようにしてる。（JSONのLINTに怒られるけど気にしない）


```json
[
  {
    "name": "datadog-agent",
    "image": "datadog/agent:latest",
    "cpu": 10,
    "memory": 256,
    "portMappings": [
      {
        "hostPort": ${dd_trace_agent_port},
        "protocol": "tcp",
        "containerPort": ${dd_trace_agent_port}
      }
    ],
    "essential": true,
    "mountPoints": [
      {
        "containerPath": "/var/run/docker.sock",
        "sourceVolume": "docker_sock",
        "readOnly": true
      },
      {
        "containerPath": "/host/sys/fs/cgroup",
        "readOnly": true,
        "sourceVolume": "cgroup"
      },
      {
        "containerPath": "/host/proc",
        "readOnly": true,
        "sourceVolume": "proc"
      }
    ],
    "environment": [
      {
        "name": "DD_APM_ENABLED",
        "value": "true"
      },
      {
        "name": "DD_SITE",
        "value": "datadoghq.com"
      },
      {
        "name": "DD_APM_NON_LOCAL_TRAFFIC",
        "value": "true"
      },
      {
        "name": "DD_TAGS",
        "value": "php-sample"
      }
    ],
    "secrets": [
      {
        "name": "DD_API_KEY",
        "valueFrom": "${dd_api_key}"
      }
    ]
  }
]
```