Terraform+AWS CodePipelineを使ってDatadogの設定作業を合理化するまでの道のり（1）

この記事は、DatadogでTerraformとAWS CodePipelineを導入するに至った経緯と理由について記載した内容になっています。
技術的な実現方法に興味がある方は後日公開予定の後続の記事をご覧ください。

## Terraform導入まで

私たちのチームでは、Datadogを使って自分たちの製品の監視を行っています。
Datadogは素晴らしいWebのコンソールを持つサービスで、多くの設定作業を直感的に行うことができます。  

しかし監視対象が多岐にわたり、設定を頻繁に変更する必要がある場合、Webのコンソールは最適な設定手段ではありません。一般的にWebブラウザでの作業は証跡を残しづらく、手順書を作成するのに多くの時間を要します。加えて、設定する項目の数が増えるにつれて、作業時間が増加するという問題も抱えています。

Webのコンソール以外の設定手段として、Datadogでは以下の3つの方法を提供しています。

* REST API
* CLI(dogコマンド)
* Terraform

当初、私たちのチームではREST APIでの設定方法を採用していました。事前の準備が必要ない最も簡単な方法だったからです。JSON形式の設定ファイルを作成し、curlコマンドでDatadogのエンドポイントに送信するだけです。これで、上述した問題は全て解決できました。

しかし時が経つにつれ、この方法では不充分だと考えるようになりました。設定手順の簡素化という課題は解決できた一方で、以下のような問題が残されている事に気づいたのです。

### JSONファイルの管理

REST APIで用いるJSONファイルはユーザフレンドリーというよりはシステムフレンドリーな内容になっています。
以下に記したのは最も簡単な部類のJSONファイルですが、これでも人が読むのに適しているとは言えないでしょう。

```
{
	"id": 11508119,
	"name": "CPU usage alert on {{host.name}}",
	"type": "metric alert",
	"query": "avg(last_5m):avg:system.cpu.idle{*} by {host} <= 10",
	"message": "CPUアラート",
	"options": {
		"notify_audit": false,
		"locked": false,
		"timeout_h": 0,
		"include_tags": false,
		"no_data_timeframe": null,
		"require_full_window": true,
		"new_host_delay": 300,
		"notify_no_data": false,
		"renotify_interval": 0,
		"escalation_message": "",
		"thresholds": {
			"critical": 10,
			"warning": 20
		}
	}
}
```

REST APIで設定を行うと決めた日から、私たちはこのJSONファイルをGitリポジトリで管理する事になりましたが、それは気分の良いものではありませんでした。後から見たときに（というよりは最初から）理解できる内容で無いことは分かり切っていました。

### 設定の抽象化

私たちのチームでは複数の製品群を1つのDatadogアカウントで管理していました。
運用していくなかで、こうしたケースでは、似たような設定項目を抽象化する事で管理を効率化できるはずだと考えるようになりました。

私たちは以下のように製品毎に1つずつ監視項目を割り当てていく設定スタイルを採用していましたが、その内容は基本的に同じものでした。以下の例で言えば、「CPU Alert in Product A」と「CPU Alert in Product B」はタイトルと監視対象のサーバ群を除いて、全て同じ値が設定されていました。

* CPU Alert in Product A
* Disk Alert in Product A
* LoadAverage Alert in Product A
* CPU Alert in Product B
* Disk Alert in Product B
* LoadAverage Alert in Product B

本質的に言えば、複数の監視項目で共有されている設定箇所は共通部分として切り出されるべきです。
共通設定と個別設定が明確に分離されている事によって、設定変更時に注視すべき点を絞る事ができます。

この2つの問題が要求している事は明らかでした。つまり私たちはDatadogで構成管理をすべき時期に差し掛かっていたのです。Terraformを使ってDatadogの構成を管理する事で、JSONファイルは可読性の高いTerraformのyamlスクリプトに差し替えられ、類似した設定箇所は1つにまとめることが出来ます。そういうわけで、私たちはDatadogにTerraformを持ち込むことを決めました。

## AWS CodePipelineの導入まで

Terraformを導入するに当たって1つの課題が生じました。「実行環境をどうするか？」という問題です。  
（ご存じの方も多いと思いますが）Terraformでは、状態を管理するStateファイルが存在し、チームで運用するにはこのファイルを共有する必要があります。また、インストールしたTerraformのバージョンによって実行結果に違いが生じることがあります。  

この課題を解決する最もシンプルな方法はTerraformを実行するLinuxサーバを用意することです。このサーバでTerraformの実行バイナリ、スクリプト、状態ファイルを管理するのです。私たちの環境には運用管理サーバと呼ばれるサーバが存在していたため、これは適当な選択肢のように思えました。  

しかし最終的にこの選択肢は放棄されました。拙い言い方ですが、これは"クラウド流なやり方"ではないと思えたのです。  
クラウドの時代は世界をよりステートレスにしました。今までは専用のサーバを用意する必要のあった状況を、クラウドのサービスを組み合わせる事で代替できるようになりました。クラウドのサービスはサーバと異なり、自分たちで保守・管理する必要が無いので、これは重要なゲームチェンジでした。

私たちは既に運用管理サーバを保守・管理していたので、この理屈が当てはまらない状況にいましたが、それでもクラウドなやり方を追求しました。結局のところ、新しいやり方を試してみたかったのです。

新しいやり方とはパイプラインによる設定の反映です。リモートリポジトリへのpushをトリガーにして、一時的に専用サーバ（マイクロインスタンス）とコンテナを起動し、事前に用意したTerraformを実行するためのスクリプトを処理します。私たちはAWSを利用していたので、AWS CodePipelineとその他のAWSサービスを組み合わせることで、このパイプラインを構築することになりました。

## 運用プロセス

私たちのチームがパイプラインを用いるのはこれが初めてだったため、運用プロセスを検討する必要がありました。
従来、私たちは以下のようなプロセスで運用を行っていました。

1. Datadogの検証アカウントで設定をテストする
2. テスト内容を基に手順書を作成する
3. 検証内容と手順書をチームでレビューする
4. 検証内容と手順書をマネジメント層でレビューする
5. 本番に設定を反映する

ちなみに私はかねてから「4」の「手順書をマネジメント層でレビューする」という部分に疑問を持っていました。
マネジメント層は新しい設定変更もしくは追加がサービスレベルにどのような影響を与えるのか、という点にのみ興味を抱いているはずですし、そうであるべきです。その観点は検証内容をレビューすることによって充足されるはずで、手順書のレビューは不要なはずです。  

手順書の中身は純粋に技術的な内容なので、不備があった場合はチームレビューにおいて指摘され、修正されるはずです。マネジメント層のレビューで指摘が入るということは（その指摘が適切であれば）、私たちのチームの怠慢であり、そうした状況が継続するのであれば何らかの是正措置が取られるべきです。

今回の運用プロセスの変更は、こうした状況を改善しました
これは以下のようなプロセスへ変更されたことにより、手順書そのものが無くなったためです。

1. 検証用のDatadogアカウントで設定をテストする
2. 検証内容をチームでレビューする
3. 検証内容をマネジメント層でレビューする
4. 本番に設定を反映する

まずはじめに、望ましい設定に変更するためにTerraformのスクリプトを書いてリモートリポジトリのdevelopブランチにpushします。これはパイプラインを通じて自動的にDatadogの検証アカウントに反映されます。この作業は検証アカウントが作業者の意図通りの状態になるまで繰り返されます。その後、チーム内で検証アカウントの設定を確認し、内容に問題ないかをレビューします。これを通過すると、マネジメント層で検証内容の概観をレビューし、それが完了するとチームにゴーサインが出ます。そして私たちのチームリーダーがリモートリポジトリ上で発行されているプルリクエストを承認することで本番アカウントに検証アカウントと同等の設定内容が反映されます。

重要なのは本番への反映作業が「プルリクエストの承認」で完了するという事です。これはAWSの画面で数クリックするだけです。手順書を作る作業は、検証アカウントで実施したのと同等の設定内容を本番へ反映する事を担保するために行われます。人が手動で設定する以上、その作業過程を明記し、内容が適切か確認する必要がどうしてもあるのです。Terraformとパイプラインの組み合わせは、この過程を人の手から解き放ってくれます。私たち人間がやるのは「本番へ設定コピーする（プルリクエストの承認）」だけです。その後はソフトウェアが面倒を見てくれます。

## むすび

この記事を書いている時点では、新しい運用が軌道に乗っている段階にありません。
実のところ、チーム内のレビューが完了しマネジメント層のレビュー及びリリースを待っている状況なのです。

ここまで読んで頂いた方はお分かりの通り、私はこの運用変更に大きな自信と期待を持っています。これはチームの運用を刷新し、近代化するだろうと考えています。より重要なタスクをする時間が増え、ヒューマンエラーが起こる機会を減少させるでしょう。

しかしより重要なのは、運用変更後にフィードバックを行うことです。チームメンバーの時間の使い方がどのように変わって、ヒューマンエラーがどのくらい減少したかを知ることが肝要なのです。あるいは、従来の運用には存在しなかった新たな問題が生じていないかを見極める事です。

自分が費やした労力や熱意が無駄になるのはもちろん辛いことですが、それ以上に辛いのは改悪された運用にしがみつくことです。