CloudFormationでDatadogを管理してみた

フォトクリエイト インフラグループの@ntakaaki です。
この記事は  [DataDog Advent Calendar 2019](https://qiita.com/advent-calendar/2019/datadog) の24日目 の記事です。

# はじめに

* 11月中旬にAWSからサードパーティーのリソースをCloudFormationで管理できるようにするCloudFormationレジストリが[発表](https://aws.amazon.com/jp/blogs/news/cloudformation-update-cli-third-party-resource-support-registry/)されました。
* フォトクリエイトではAWSリソースの管理はCloudFormation、監視にDatadogを使ってますがDatadogの設定のコード化はできてませんでした。
* Datadogの設定をコード化する際はTerraformを使うことが多いと思いますが、検証がてらCloudFormationレジストリでの管理がどんなものなのか触ってみたいと思います。

# 何ができるか

CloudFormationでは下記のDataDogリソースが管理できます。

* AWS Integration
  * DataDogでEC2やLambdaなどの各種サービスのうち、何に対して監視を有効にするかの設定
* Monitor
  * アラートと通知先の設定。
  * Slackに通知したい場合は事前にSlack Integrationを有効にしてチャンネルを登録しておく必要があります。
     * Slack IntegrationまではCloudFormationで面倒は見れないうようです。
  * 監視対象にできるのは以下のようですが全て対応してるわけではなさそうです。
     * JSON Schema内のEnum値から引っ張ってます。
     * composite
     * event alert
     * log alert
     * metric alert
     * process alert
     * query alert
     * service check
     * synthetics alert
     * trace-analytics alert
* Downtime
  * メンテ中など監視を無効にする時間帯の設定
* User
  * DataDogのユーザーの管理

# Terraform Providerとの比較

* 今の所TerraformにできてCloudFormationにできないことは下記になります。
  * ダッシュボードの管理
  * ログパイプラインの管理
  * SLOの管理
  * Synthetics（API、Browser Test両方）の設定
* 結構できないことが多いですが、[Issue](https://github.com/DataDog/datadog-cloudformation-resources/issues)ではDashboardやSyntheticsへ対応する予定のようです。

# 使用方法

## リソースの登録

* 最初にDataDogをCloudFormationのリソースとして登録します。
* この作業はIntegration、Monitor、Downtime、Userに対して1回ずつ実行します。
* schema-handler-packageのURLは12月19日時点のものになります。
    * S3のパスは各リソースのChangeLogに記載があります。
    
```:リソース登録コマンド
aws cloudformation register-type \
    --region ap-northeast-1 \
    --type RESOURCE \
    --type-name "Datadog::Monitors::Monitor" \
    --schema-handler-package s3://datadog-cloudformation-resources/datadog-monitors-monitor/datadog-monitors-monitor-1.0.2.zip
```

## リソース登録の確認

```:リソース一覧の取得コマンド
aws cloudformation list-types
```

* IntegrationとMonitorを登録してる場合。

```:実行結果
{
    "TypeSummaries": [
        {
            "Type": "RESOURCE",
            "TypeName": "Datadog::Integrations::AWS",
            "DefaultVersionId": "00000001",
            "TypeArn": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:type/resource/Datadog-Integrations-AWS",
            "LastUpdated": "2019-12-18T17:20:17.485Z",
            "Description": "Datadog AWS Integrations"
        },
        {
            "Type": "RESOURCE",
            "TypeName": "Datadog::Monitors::Monitor",
            "DefaultVersionId": "00000001",
            "TypeArn": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:type/resource/Datadog-Monitors-Monitor",
            "LastUpdated": "2019-12-18T17:15:58.911Z",
            "Description": "Datadog Monitor"
        }
    ]
}
```

## 監視対象の登録

* いくつか試しに登録してみます。
* ここからはいつもどおりのCloudFormationなので、関数も変数も普通に使えます。

```:Resource定義
Resources:
  QueryAlert:
    Type: 'Datadog::Monitors::Monitor'
    Properties:
      Type: "query alert"
      Query: 'avg(last_5m):avg:aws.applicationelb.un_healthy_host_count.maximum{loadbalancer:app/xxxxxxx/yyyyyy} > 2'
      Name: 'Unhealthy host count in Alb'
      Message: !Sub "An EC2 instance in the ${AWS::Region} region is offline."
      Options:
        NotifyAudit: false
        Locked: false
        TimeoutH: 0
        NewHostDelay: 300 
        RequireFullWindow: true
        NotifyNoData: false
        RenotifyInterval: '0' 
        EscalationMessage: ''
        IncludeTags: true
        Thresholds:
          Critical: 2
          Warning: 1
          OK: 0
      DatadogCredentials:
        ApiKey: !Ref DatadogAPIKey
        ApplicationKey: !Ref DatadogAPPKey

  ServiceCheck:
    Type: 'Datadog::Monitors::Monitor'
    Properties:
      Type: "service check"
      Query: '"process.up".over("host:i-xxxxxxxxxxx","process:pgpool").by("host","process").last(4).count_by_status()'
      Name: 'ALB Unhealthy host count'
      Message: !Sub "Pgpool process live monitoring"
      Options:
        NotifyAudit: false
        Locked: false
        TimeoutH: 0
        NewHostDelay: 300
        RequireFullWindow: true
        NotifyNoData: false
        RenotifyInterval: '0'
        EscalationMessage: ''
        IncludeTags: true
        Thresholds:
          Critical: 3
          Warning: 2
          OK: 2
      DatadogCredentials:
        ApiKey: !Ref DatadogAPIKey
        ApplicationKey: !Ref DatadogAPPKey
```
 
### ハマりどころ

* DataDogに登録されてるMonitorをExportしたものはそのままでは使えず。
   * JSONがスネークケースになってるのを変換する必要がありました。
   * Queryはエスケープさえ気をつければそのままで大丈夫でした。

# まとめ

* DataDogの監視設定をCloudFormationでやってみました。
* 出たばかりなので先行してるTerraform Providerと比べてしまうと足りない部分はあります。
* 普段からCloudFormationを使ってる人にとってはかなり手を出しやすくなったのではないでしょうか。
  * ParameterやMappingを組み合わせることで環境によって閾値をかえるなどもできるでしょう。
  * ただ、全部のリソースにDatadogCredentialsを書いて回るのはだるいのでそこはどうにかならないんだろうかと。。