CloudFormationレジストリを使ってDatadogのモニターを設定する

この記事はZOZOテクノロジーズ [#3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech3) 18日目の記事です。
昨日は@niba1122さんの[Rust+WebAssemblyでメタボールを作る](https://niba1122.dev/rust-wasm-metaball/)でした。

今年ZOZOテクノロジーズでは全部で5つのAdvent Calendarが公開されているので、
他の記事もぜひ目を通していただけると嬉しいです。

[ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech)
[ZOZOテクノロジーズ #2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech2)
[ZOZOテクノロジーズ #4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech4)
[ZOZOテクノロジーズ #5 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech5)

# この記事について
先日CloudFormation レジストリが発表され、
CloudFormationでサードパーティのリソースも定義できるようになったのはご存知でしょうか、、、？

[CloudFormation 最新情報 – CLI + サードパーティのリソースサポート + レジストリ](https://aws.amazon.com/jp/blogs/news/cloudformation-update-cli-third-party-resource-support-registry/)

今回対応したサードパーティのベンダーに弊社で採用しているDatadogも含まれていたので、
感触を確かめるべく設定を試してみました。

本記事では実際に設定で使用したCloudFormationテンプレートを交えて
一連の流れや試してみてわかったこと等をご紹介します。

日々修行中の身ですので、
認識が誤っている点やアドバイスいただける点があればコメントいただけると幸いです。

# [CloudFormationレジストリ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html)とは

名前通り、CloudFormationで利用可能なリソースのリストです。

レジストリは以下の2タイプに別れており、
今回試すDatadogのリソースが登録されるのはPrivateのレジストリです。

- Public：　AWSのネイティブリソースが登録されている
- Private：　ユーザが作成したリソースやサードパーティベンダーから取得したリソースが登録される　

同じタイミングで公開されたCloudFormationCLIを使ってスキーマやハンドラーを作成すれば
ユーザ独自のリソースも登録することができるようです。

# Datadog×CloudFormation レジストリで設定できること

2019/12現在は以下の設定が可能です。

- AWSとのインテグレーション
- モニターの作成、更新、削除
- モニターのダウンタイムの有効化、無効化
- ユーザ作成と管理

まだできることは少ないものの、監視するAWSリソースが多い（モニターが多い）環境では
少なからず役立つ部分もあるのではと思っています。

# 前提

- DatadogとAWSのインテグレーションは設定済みである（DatadogのApiKeyも作成済み）

# 準備編
## 1. ApplicationKeyを作成しておく

DatadogのAPIにフルアクセスできるよう、あらかじめ上記を取得しておく必要があります。
Datadogにログインし、画面左のIntegrations > APIsを選択します。
<img width="580" alt="スクリーンショット 2019-12-17 午後11.47.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/1e4b1896-5d08-4d96-fa4e-de8170cbe5c8.png">

表示された項目のうち、Application Keysから必要事項を入力して作成します。
<img width="1047" alt="スクリーンショット 2019-12-17 午後11.53.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/0ac5350f-446f-675d-dd25-7a6fedb8446d.png">



## 2. AWSCLIの認証情報を設定しておく

AWSCLIを使って設定する場面があるため、IAMUserの[アクセスキーとシークレットキーを取得](https://docs.aws.amazon.com/ja_jp/powershell/latest/userguide/pstools-appendix-sign-up.html)し、
以下のような設定が必要です。

```~/.aws/credential
[hoge]
aws_access_key_id = {アクセスキー}
aws_secret_access_key = {シークレットキー}
```
```~/.aws/config
[profile hoge]
region = {主に使用しているリージョン}
output = json
```

# 設定編
今回はDatadogに2つのモニターを設定します。

- healthcheckが成功しているFargateの数を監視するモニター
- FargateのCPU利用率を監視するモニター<br>
→いずれも閾値で監視し、閾値を超えるとhogeという名前のslackチャンネルに通知が来るようにします。

ここから先の作業は大きく２ステップで、[Datadogの公式ドキュメント](https://docs.datadoghq.com/ja/developers/amazon_cloudformation/#resources-available)を参考にして行いました。

## STEP1: CloudFormationレジストリにDatadogのリソースを登録する
AWSCLIを使って作業を行います。
まずは以下のコマンドを実行し、リソースプロバイダーとしてDatadogのMonitorを登録します。

```
$ aws cloudformation register-type \
    --type RESOURCE \
    --type-name Datadog::Monitors::Monitor \
    --schema-handler-package s3://datadog-cloudformation-resources/datadog-monitors-monitor/datadog-monitors-monitor-1.0.1.zip \
    --profile hoge
{
    "RegistrationToken": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxx"
}
```
RegistrationTokenが返ってくれば成功です。
type-nameやschema-handler-packageを指定していますが、値は[こちら](https://docs.datadoghq.com/ja/developers/amazon_cloudformation/#resources-available)を参考にしました。
schema-handler-packageは、作成したいリソースの"RESOURCE LINK"からダウンロードしても確認した方が楽かもしれません。

このようにして登録されたリソースは複数バージョン登録が可能で、どのバージョンをデフォルトで使うのかを指定する必要があります。
そのため、以下のコマンドで登録したリソースのバージョンを確認します。

```
$ aws cloudformation list-type-versions \
   --type RESOURCE \
   --type-name Datadog::Monitors::Monitor \
   --profile hoge
{
    "TypeVersionSummaries": [
        {
            "Description": "Datadog Monitor",
            "TimeCreated": "2019-12-09T10:15:56.394Z",
            "TypeName": "Datadog::Monitors::Monitor",
            "VersionId": "00000001",
            "Type": "RESOURCE",
            "Arn": "arn:aws:cloudformation:ap-northeast-1:123456789123:type/resource/Datadog-Monitors-Monitor/00000001"
        }
    ]
}
```

返ってきたバージョン"00000001"を指定してデフォルトに登録します。

```
$ aws cloudformation set-type-default-version \
    --type RESOURCE \
    --version-id 00000001 \
    --type-name Datadog::Monitors::Monitor \
    --profile hoge
```

ここまで設定すると、webコンソール上からCloudFormationレジストリに作成したリソースが確認できます。
<img width="1669" alt="スクリーンショット 2019-12-18 午前4.43.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/1b463d4c-af8b-3b0e-5280-8d449fa965d2.png">





## STEP2: CloudFormationスタックを作成する
今回は以下のテンプレートを作成し、スタックの作成を行いました。

```datadog-monitor.yml
AWSTemplateFormatVersion: 2010-09-09
Parameters: 
  GlobalEnvironment:
    Type: 'String'
    Default: 'stg'
  ALBName:
    Type: 'String'
    Default: 'ALBのDNS名'
  ClusterName:
    Type: 'String'
    Default: 'ECSのクラスター名'
  SlackName:
    Type: 'String'
    Default: '@slack-hoge'
  DatadogApiURL:
    Type: 'String'
    Default: 'https://api.datadoghq.com'
  DatadogApiKey:
    Type: 'String'
    Default: ''
    NoEcho: true
  DatadogApplicationKey:
    Type: 'String'
    Default: ''
    NoEcho: true
  ALBHealthyHostCritical:
    Type: 'String'
    Default: '0'
  ALBHealthyHostWarning:
    Type: 'String'
    Default: '1'
  ECSCpuCritical:
    Type: 'String'
    Default: '90'
  ECSCpuWarning:
    Type: 'String'
    Default: '85'
Resources:
  MonitorsMonitorALBHealthyHost:
    Type: 'Datadog::Monitors::Monitor'
    Properties:
      Type: 'query alert'
      Query: !Sub sum(last_1m):avg:aws.applicationelb.healthy_host_count{host:${ALBName}} <= ${ALBHealthyHostCritical}
      Name: 'ALB healthy host is low'
      Message: !Sub '{{#is_warning}} <!channel> ALBのhealthy host数が{{warn_threshold}}です。Fargateのステータスを確認してください。 {{/is_warning}} {{#is_alert}} <!channel> ALBのhealthy host数が{{threshold}です。Fargateのステータスを確認してください。 {{/is_alert}} {{#is_recovery}} <!channel> ALBのhealthy host数が正常に戻りました。{{/is_recovery}} Notify ${SlackName}'
      Tags:
          - !Ref GlobalEnvironment
      Options:
        Thresholds:
          Critical: !Ref ALBHealthyHostCritical
          Warning: !Ref ALBHealthyHostWarning
        NotifyNoData: false
        EvaluationDelay: '900'
      DatadogCredentials:
        ApiURL: !Ref DatadogApiURL
        ApiKey: !Ref DatadogApiKey
        ApplicationKey: !Ref DatadogApplicationKey

  MonitorsMonitorECSCpu:
    Type: 'Datadog::Monitors::Monitor'
    Properties:
      Type: 'query alert'
      Query: !Sub avg(last_5m):avg:ecs.fargate.cpu.percent{cluster_name:${ClusterName}} by {container_id} > ${ECSCpuCritical}
      Name: 'ECS cpu percent is high'
      Message: !Sub '{{#is_warning}} <!channel> {{ecs_task_family.name}} のCPU使用率が{{warn_threshold}}%を超えました。 {{/is_warning}}  {{#is_alert}} <!channel> {{ecs_task_family.name}} のCPU使用率が{{threshold}}%を超えました。 {{/is_alert}}  {{#is_recovery}} {{ecs_task_family.name}} のCPU使用率が正常値に戻りました {{/is_recovery}} Notify ${SlackName}'
      Tags:
          - !Ref GlobalEnvironment
      Options:
        Thresholds:
          Critical: !Ref ECSCpuCritical
          Warning: !Ref ECSCpuWarning
        NotifyNoData: false
      DatadogCredentials:
        ApiURL: !Ref DatadogApiURL
        ApiKey: !Ref DatadogApiKey
        ApplicationKey: !Ref DatadogApplicationKey



```

AWSCLIでもスタックの作成は可能ですが、普段通りWebコンソールから設定を行いました。

CloudFormation > スタックの作成 > 新しいリソースを使用（標準） をクリックし、
テンプレートをアップロードします。
パラメータに値が入っていない項目は値を入力し、
<img width="1021" alt="スクリーンショット 2019-12-18 午前4.34.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/c964e87c-fcea-e4e4-08a1-4f668e790053.png">
![スクリーンショット 2019-12-18 午後3.53.35（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/40fb8138-ff07-81a8-63f7-a6d87dd11f2f.png)

スタックを作成します。
<img width="529" alt="スクリーンショット 2019-12-18 午前4.36.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/dc71220c-d2d0-29a1-9f4d-c55c1911f0e2.png">

スタックの更新が完了すると、作成したモニターがDatadogに表示されます。
<img width="1495" alt="スクリーンショット 2019-12-18 午前5.04.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413013/e8f4f840-c424-245f-fe3f-b34f7aad47de.png">

作成直後はステータスがNO DATAになりますが、時間が経つとOKに変わります。

# 試してみてわかったこと
- 設定そのものにかかった時間は1時間程度でした。（スタックそのものの更新は２、３分）
- 今回のテンプレートには記載していませんが、Conditionや!IfなどのCloudFOrmationの記法を使ってモニターを設定することも可能でした。
- 更新や削除を行う際もAWSリソース同様に、ymlファイルを修正してスタック更新を行うとDatadogに反映されます。
- Datadog側で設定を変更した状態でCloudFormationを実行してもDatadog側の設定は残るようでした。
- 指定すべき値に不足や誤りがある時等はスタック更新時にエラーが出るようになっていました。<br>
（ex.閾値を使うと定義しているのに指定していない）
- サンプルコードは[DatadogのGitHubのリポジトリ](https://github.com/DataDog/datadog-cloudformation-resources)や[公式ドキュメント](https://docs.datadoghq.com/ja/developers/amazon_cloudformation/)に記載されていますが、<br>
それ以外で指定できるプロパティは[JSONスキーマ](https://github.com/DataDog/datadog-cloudformation-resources/blob/master/datadog-monitors-monitor-handler/datadog-monitors-monitor.json)を読み込む必要がありました。


# 今後の課題
- 繰り返し呼び出しが発生する部分の汎用化<br>
モニターが増えるごとにほぼ同じ内容を記述するのが勿体無いので、この部分を解消したいと考えています。

# まとめ
CloudFormation レジストリという新しい機能を使ってDatadogのモニターを設定する流れをご紹介しました。

普段からAWSのリソース管理にCloudFormationを利用しているので、
AWSリソースを設定する時と同じ感覚・手順でDatadogのモニターを設定できるのはやはり便利だったので
今後どんどん設定できるリソースが増えていくことを期待しています。

今後の課題についてはどこかのタイミングで取り組みたいと考えているので
また改善できた際は投稿したい思います。

明日のZOZOテクノロジーズ [#3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech3)は@maaaaaaaaさんです。
ぜひそちらもご覧ください！

# 参考サイト

- [CloudFormation 最新情報 – CLI + サードパーティのリソースサポート + レジストリ](https://aws.amazon.com/jp/blogs/news/cloudformation-update-cli-third-party-resource-support-registry/)
- [Using the CloudFormation Registry](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/registry.html)
- [AWS アカウントとアクセスキー](https://docs.aws.amazon.com/ja_jp/powershell/latest/userguide/pstools-appendix-sign-up.html)
- [aws-cliにて、複数の認証情報を使い分けたい場合の設定方法](https://qiita.com/bakira/items/3a4876cbb39f9a7ec3b8)
[Datadog-Amazon CloudFormation](https://docs.datadoghq.com/ja/developers/amazon_cloudformation/)