TerraformでCloudWatch Dashboardを管理する際のつらみ

TerraformでCloudWatch Dashboardを管理する機会があったが、JSONの手動編集がとても辛かった。
これならコード管理諦めてGUI編集してしまいたくなるくらいの面倒さだったのでメモ程度につらみをメモしておく。

現時点でCloudWatch DashboardをTerraform管理する際に工夫できる点としては、↓のような点があるよう。(テンプレートエンジンは自分も活用した)
- JSONをテンプレートエンジン(templatefile)でレンダリングさせる
- これによって動的に変わりうるリソース名を変数で埋め込むことができる
- 予めAWSサービスごとのテンプレート的なダッシュボードをTerraform Module化しておくことで、複数PJから再利用できるようにする

↑のような工夫をした上でも、今だいくつかのつらみがある。
バリデーションが皆無
AWS公式のProviderはダッシュボードのJSONが正しい形式かどうかまでは見てくれず、applyしてPutDashboard APIをコールした時に初めてエラーが出ることになる。
これでは、開発サイクルが伸びてしまう(plan->applyまでしないとエラーに気づけない)のと、よく分からないPutDashboardのエラー分を解読しないといけず、辛い。
以下のようなエラーを引くと、JSON上で18個目のwidgetを探す旅に出るハメに、、
aws_cloudwatch_dashboard.test: Modifying... [id=test]
╷
│ Error: putting CloudWatch Dashboard (test): operation error CloudWatch: PutDashboard, https response error StatusCode: 400, RequestID: 91be6dee-0a51-45ee-af2f-b86c7b3ae3c9, InvalidParameterInput: The dashboard body is invalid, there are 1 validation errors:
│ [
│ {
│ "dataPath": "/widgets/18/properties/metrics/5",
│ "message": "Should NOT have more than 3 items"
│ }
│ ]
│
│ with aws_cloudwatch_dashboard.test,
│ on dashoboard_test.tf line 2, in resource "aws_cloudwatch_dashboard" "test":
│ 2: resource "aws_cloudwatch_dashboard" "test" {
│
╵

Metric定義の再利用性の低さ
Dashboardのwidget定義は↓のような構造になっており、表示したいメトリクスの定義はproperties.metrics
に書く。
{
"height": 6,
"width": 8,
"y": 2,
"x": 0,
"type": "metric",
"properties": {
"metrics": [
[
"AWS/ApplicationELB",
"RequestCount",
"LoadBalancer",
"${alb_arn_suffix}"
]
],
"view": "singleValue",
"region": "${region}",
"title": "Request Count in 7 day",
"period": 604800,
"stat": "Sum",
"singleValueFullPrecision": true
}
}
これはALBのリクエスト数をnumber widgetとして表示するwidget定義(以下例)。
ただここでよくあるケースとして、「同じメトリクスを複数のwidgetで表示したい」ということがあると思う。例えばALBのRequestCount
を取っても、
- ダッシュボードの先頭ではnumber widgetでサマリ的に表示
- それより後ろではline graph widgetを使って時系列で推移が見られるようにする
というようなユースケースはあり得ると思う。
その際に、公式のTerraform Providerだとそれぞれのwidget定義のproperties.metrics
に同じ値を埋めないといけないし、メトリクス定義に修正がある時は両方とも修正する必要があり、辛い。

widgetの位置変更のつらさ
これはシンプルなtext widget。見てわかるように、widgetの配置はx
, y
で絶対的な位置として指定する。
{
"height": 2,
"width": 24,
"y": 0,
"x": 0,
"type": "text",
"properties": {
"markdown": "# Overview"
}
}
ここで、例えばダッシュボード先頭のwidgetを削除したときを考える。先頭のwidgetがあった場所がぽっかり空いてしまうので、後続のwidgetを詰めて空白を消す作業が発生してしまう。
備考
リファレンスによるとx
, y
はオプショナルのようで、省くとAWS側で空いている場所に左上から順にwidgetを配置してくれる模様。つまりx
, y
は使わずにheight
とwidth
のみでwidget配置を行う場合はこのつらみは発生しない。(個人的には基本的にx
, y
は無しで運用するのが良さそうと感じている)

マークダウン書きづらいもあったな。
templatefileのvariable経由で別ファイルからマークダウンを渡せば切り出すことは出来るけどそっちの方が可読性的にもしんどそう。