#概要
監視、モニタリングで使用している複数のDatadogの環境(Organization)がある。
これらを1つにOrganizationをまとめて管理しやすくしたい。
でも、、、全部手作業でやるのはめんどくs工数が掛かる!
そこでterraform
を使って一気にできたらいいなぁなんて思ってやってみました。
#前提条件
Orgaqnizationは2つあり、以下のダッシュボードのみを持つ。
記事簡略化のためダッシュボード以外のリソースは持たないことにする。
また、各Organizationでは共通のメトリクスが取得できているものとする。
既存Datadogリソースのtf化については以下の方法が考えられた。
- 手動で全部書く
-
terraform import
でリソースを取得し、tfファイルに記載する -
terraformer
というインポートツールを使用して自動インポートする
結果、3のterraformer
を使用する方法を採用した。Datadog公式ページにて推奨されていることと、リソースが多い場合一括でimportできるので結果的に一番手間が少ないと判断したためである。
###Datadog環境(example)
- Organizetion1: Yojo_Dog
- resourse: Dog_moniter_dashboard
- Organization2: Yojo_Cat
- resourse: Cat_moniter_dashboard
今回は、Yojo_Cat
環境のCat_moniter_dashboard
をterraformerを使ってtfファイルとして出力し、Yojo_Dog
環境にterraformからapplyすることで、2つのdashboardがある状態を作ります!
#使用ツール
-
Terraform: コンピュータやネットワークを自動構築するツール。Datadog用のモジュールが用意されているためDatadogの環境をコード化、自動化できる。
-
terraformer: 構築済みの既存リソース(AWSやDatadogなど)を読み取り、terraformのコードとして出力してくれるインポートツール
-
tfenv: 複数のTerraformバージョンを切り替えして使用できる管理ツール
#構築作業手順
###ツールのインストール、セットアップ
local環境はMac向けとなります。Widowsをお使いの方は~~Macを買ってください~~
WSLのUbuntuとかでできるんじゃないですかねぇ(投げやり)
####tfenvのインストール
#Terraformがインストールされている場合エラーになるので一旦消す
$ brew uninstall terraform
#tfenvをインストール
$ brew install tfenv
#tfenvの確認
$ tfenv --version
tfenv 2.2.0
####tfenvからterraformをインストール
今回はterraformer用にv0.13.6
を使用します。
#tfenvからterraformをインストール
$ tfenv install 0.13.6
Installing Terraform v0.13.6
Downloading release tarball from https://releases.hashicorp.com/terraform/0.13.6/terraform_0.13.6_darwin_amd64.zip
##################################################################################################################### 100.0%
Downloading SHA hash file from https://releases.hashicorp.com/terraform/0.13.6/terraform_0.13.6_SHA256SUMS
No keybase install found, skipping OpenPGP signature verification
Archive: tfenv_download.TOSAgI/terraform_0.13.6_darwin_amd64.zip
inflating: /usr/local/Cellar/tfenv/2.2.0/versions/0.13.6/terraform
Installation of terraform v0.13.6 successful. To make this your default version, run 'tfenv use 0.13.6'
#インストールされたか確認
$ tfenv list
* 0.13.6 (set by /usr/local/Cellar/tfenv/2.2.0/version)
#インストールしたterraformバージョンを使用する
$ tfenv use 0.13.6
#terraformコマンドの確認
$ terraform --version
Terraform v0.13.6
####terraformerのインストール
$ brew install terraformer
$ terraformer version
Terraformer v0.8.10
###Datadogリソースをインポートする準備
terraformer
でDatadogリソースをインポートするにはAPI Key
とAPP Key
が必要になります。
以下手順で確認します。
####API Keyの確認
Datadogのコンソールにログインし、左のメニューからIntegrations → APIs
を選択します。
以下画面に遷移しますので、API Keysを展開しKeyを控えておきます。
####APP Keyの確認
同様のページからApplication Keys have moved to the Teams page
を選択するとApp Keyの作成、確認ページに遷移します。
作成済みのKeyがあっても作成時に一度しかKeyは確認できないようです。
また、Key作成の際は自身のユーザの権限のみを持ちますので個人ではなく会社でやる際は偉い人を脅す確認しましょう。
+New Key
ボタンを押すとKey作成されクリップボードにコピーすることができます。控えておいてください。
これでこのOrganizationからterraformerでtfファイルをインポートする準備ができました!!ヨシっ!!
同様の手順でもう一つのOrganizationのKeyを控えておきます。
###terraformerの実行
####terraformの初期設定
まずはterraformを実行できるようにサクっと環境を作りましょう。
#実行ディレクトリの作成(自由に)
terraform
└── datadog
####main.tfの作成
Datadog公式ドキュメント通りに書いていきます。
api_key
app_key
は__Datadogリソースをインポートする準備__で取得したリソースを書き出したい方のOrganizationのものを記載します。
この記事ではkeyを直接記載しますので間違えてgithubに公開しないように気をつけてくださいね
Yojo_Cat
のリソースをYojo_Dog
に追加するので以下のようになります。
terraform {
required_providers {
datadog = {
source = "Datadog/datadog"
}
}
}
provider "datadog" {
api_key = "Yojo_Dog_api_key"
app_key = "Yojo_Dog_app_key"
}
####initする
Datadog用のprovidersをインストールするため、init
します。
$ terraform init
Terraform has been successfully initialized!
####1つ目のOrganizationのリソースをterraformer import
する
今回はdashboardだけですが、その他のリソースがある場合は--resorces=hoge,fuga,piyo
とカンマ区切りで指定できます。
また、特定のリソースだけを出力する場合は--filter=dashboard=Dog_moniter_dashboardID
のように指定できます。1
#Yojo_Dog Organizationのリソースを出力
$ terraformer import datadog --resources=dashboard --api-key "Yojo_Dog_api_key" --app-key "Yojo_Dog_app_key"
2021/03/05 02:58:27 datadog importing... dashboard
2021/03/05 02:58:28 Refreshing state... datadog_dashboard.tfer--dashboard_<Dog_moniter_dashboardID>
2021/03/05 02:58:36 datadog Connecting....
2021/03/05 02:58:36 datadog save dashboard
2021/03/05 02:58:37 datadog save tfstate for dashboard
#generateディレクトリとファイルが出力される
./generated
└── datadog
└── dashboard
├── dashboard.tf
├── outputs.tf
├── provider.tf
└── terraform.tfstate
####2つ目のOrganizationのリソースをterraformer import
する
このまま実行すると__なんと全部上書きされてしまいます・・・What's!?__
なので、別のディレクトリに一旦退避させましょう
terraform
└── datadog
├── Yojo_Dog
│ └── generated
│ └── datadog
│ └── dashboard
│ ├── dashboard.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── terraform.tfstate
└── main.tf
#Yojo_Cat Organizationのリソースを出力
$ terraformer import datadog --resources=dashboard --api-key "Yojo_Cat_api_key" --app-key "Yojo_Cat_app_key"
2021/03/05 03:16:40 datadog importing... dashboard
2021/03/05 03:16:44 Refreshing state... datadog_dashboard.tfer--dashboard_<Cat_moniter_dashboardID>
2021/03/05 03:16:55 datadog save dashboard
2021/03/05 03:16:56 datadog save tfstate for dashboard
#generateディレクトリとファイルが出力される
.
├── Yojo_Dog
│ └── generated
│ └── datadog
│ └── dashboard
│ ├── dashboard.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── terraform.tfstate
├── generated
│ └── datadog
│ └── dashboard
│ ├── dashboard.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── terraform.tfstate
└── main.tf
#統一感だしていこ???笑笑笑
.
├── Yojo_Cat
(略)
├── Yojo_Dog
###リソースファイルの修正
出力したファイルはそのままでは使うことができません。これを使用するために2つのことをファイル追加修正します。
- tfファイルのバージョンアップを行う
- 競合するIDを削除する
####tfファイルのバージョンアップを行う
これはDatadog公式ドキュメントの手順で推奨されているので実行します。
terraformerでimportしたtfファイルのバージョンをv0.13.x
に調整します。
#Yojo_Catに実行
$ pwd
/datadog/Yojo_Cat/datadog/dashboard
$ terraform 0.13upgrade .
Would you like to upgrade the module in the current directory?
Only 'yes' will be accepted to confirm.
Enter a value: yes #yesを入力してエンター
-----------------------------------------------------------------------------
Upgrade complete!
#なんか変わってる。まぁ任せた!!
$ git status
Changes not staged for commit:
modified: provider.tf
Untracked files:
(use "git add <file>..." to include in what will be committed)
versions.tf
#initする
$ terraform init
Terraform has been successfully initialized
.
├── dashboard.tf
├── outputs.tf
├── provider.tf
├── terraform.tfstate
└── versions.tf
#忘れずにYojo_Dogにも適用する
$ pwd
/terraform/datadog/Yojo_Dog/generated/datadog/dashboard
$ terraform 0.13upgrade .
$ terraform init
####競合するIDを削除する
terraformerの弱点の一つとして、リソースの固有IDまでtfファイルにもってきてしまうことです。
このままapplyしようとしても既存リソースと競合してしまいエラーとなります。
ちょっと状況を確認してみましょう。
$ terraform plan
Error: "widget.10.id": this field cannot be set
on dashboard.tf line 125, in resource "datadog_dashboard" "tfer--dashboard_<dashboard_ID>":
125: resource "datadog_dashboard" "tfer--dashboard_<dashboard_ID>" {
Error: "widget.10.id": this field cannot be set
.
.
.
.
echo '天才の僕「ぎゃーーー!!!!」'
・・・とご丁寧にどのリソースやウィジットがエラーになってるか書いているのでtfファイルを修正していきましょう
以下は"爆速なお仕事(笑)"
が特技の筆者の方法です。
$ ls
dashboard.tf outputs.tf provider.tf terraform.tfstate versions.tf
#伝説の武器、VSCodeを起動!!俺のターーーン!!!!!(エンターキーをターン!する)
$ code dashboard.tf
ID = .*$
で検索してみると。。。
なんかいた!!!!これが入ってるとapplyできません。
全部いらないので置換で消しちゃいましょう。神経質な方は確認してから消しましょう。
筆者はできなきゃ戻せばいいやみたいな悪いエンジニアなのでそのまま全部置換
エラーが出なくなるまで特定して修正します。
$ terraform plan
Error: api_key and app_key must be set unless validate = false
上記は大丈夫なやつです。generated配下でplanしているのでキーがなくて正常です。
エラーが出なくなったらもう一つのOrganizationも修正しましょう。
$ terraform plan
Error: "widget": required field is not set
6731: resource "datadog_dashboard" "tfer--dashboard_<dashboard_ID>" {
見たところ、widgetが無いテストみたいなダッシュボードでした。
からっぽのdashboardはGUIから保存できてしまいますがコード上は許されていないようです。
ただファイルから削除しただけだとtfstateとの整合性が取れなくなりややこしくなります。
その辺りは、今回は触れません。
つまり、、、GUIから物理削除してimportしなおしました!
(exampleだとdashboardが1個になってますが、こういうエラーもあるよということで例外紹介でした)
###リソースを統合する
いよいよ最終章です。2つのOrganizatioのdashboardをおまとめして、Yojo_Dog環境を最強にします。
####ファイルの移動
importしたデータメインディレクトリに移動しましょう。
dashboard.t
terraform.tfstate
versions.tf
が対象です。
$ pwd
/datadog/Yojo_Cat/datadog/dashboard
$ cp dashboard.tf terraform.tfstate versions.tf ../../../
.
├── Yojo_Cat
│ └── datadog
│ └── dashboard
│ ├── dashboard.tf
│ ├── outputs.tf
│ ├── provider.tf
│ ├── terraform.tfstate
│ └── versions.tf
├── Yojo_Dog
│ └── generated
│ └── datadog
│ └── dashboard
│ ├── dashboard.tf
│ ├── outputs.tf
│ ├── provider.tf
│ ├── terraform.tfstate
│ └── versions.tf
├── dashboard.tf
├── main.tf
├── terraform.tfstate
└── versions.tf
###planで内容を確認する。
注意:このログは良く確認してください。適当に実行してしまうと・・・
破壊と創造を行うシステム障害の神になりえます。
しっっかっかっかっかりとログを確認
して念のため退職届を書いておきましょう。
#ファイルが増えているので一旦initしておく
$ terraform init
$ terraform plan
#変更のあるリソースを確認
datadog_dashboard.tfer--dashboard_<Cat_moniter_dashboard_ID>: Refreshing state... [id=Cat_moniter_dashboard_ID]
------------------------------------------------------------------------
#Createdのみなはず。deleteがあるなら要確認
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# datadog_dashboard.tfer--dashboard_<Cat_moniter_dashboard_ID> will be created
+ resource "datadog_dashboard" "<Cat_moniter_dashboard_ID>" {
+ dashboard_lists_removed = (known after apply)
+ description = <<~EOT
## Overall
Dashbord for
(略)
# +が追加される部分です。リソース、ウィジットなど変更点を確認しましょう。
#最後に変更点のカウントが出ます。
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
###applyする
ここまで問題がなければapplyすることでリソースの統合ができるはずです。
Yojo_DogにYojo_Catの全てをぶっこんであげましょう!!!
$ terraform apply
datadog_dashboard.tfer--dashboard_<Cat_moniter_dashboard_ID>: Refreshing state... [id=<Cat_moniter_dashboard_ID>]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
(略)
#実行するか聞かれるのでyesを入力します。
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Outputs:
datadog_dashboard_tfer--dashboard_<Cat_moniter_dashboard_ID>_id = datadog_dashboard.tfer--dashboard_<Cat_moniter_dashboard_ID>.id
Apply complete!が出ていれば成功です!お疲れ様でした
###結果をGUIから確認する
ナイスー!!!!!
勝ち申した!!!!
####Twitterやってます!エンジニアアカウントも音楽アカウントもフォローしてね
わんわんもにゃんにゃんもかわいいけど、どっちかだったら…😑💭
— 天才ハッカー幼女こはるちゃん (@koharu_infra) March 4, 2021
わんわんが好きです😚😬😝😘💞💞💞💞💞✨✨✨✨
🐶🐶🥰🥰🥰🥰🥰💨
-
--filter
で使用するIDはリソースのnameではなく個別にDatadogから振られているIDを使います。ブラウザから例えば対象のダッシュボードを開くとブラウザのURLにIDが表示されているのでそれを使用します。 ↩