Open6

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

yamoyamotoyamoyamoto

現時点でCloudWatch DashboardをTerraform管理する際に工夫できる点としては、↓のような点があるよう。(テンプレートエンジンは自分も活用した)

  • JSONをテンプレートエンジン(templatefile)でレンダリングさせる
    • これによって動的に変わりうるリソース名を変数で埋め込むことができる
  • 予めAWSサービスごとのテンプレート的なダッシュボードをTerraform Module化しておくことで、複数PJから再利用できるようにする

https://zenn.dev/finatext/articles/manage-cloudwatch-dashboard-with-terraform

yamoyamotoyamoyamoto

↑のような工夫をした上でも、今だいくつかのつらみがある。

バリデーションが皆無

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" {
│ 
╵
yamoyamotoyamoyamoto

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に同じ値を埋めないといけないし、メトリクス定義に修正がある時は両方とも修正する必要があり、辛い。

yamoyamotoyamoyamoto

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は使わずにheightwidthのみでwidget配置を行う場合はこのつらみは発生しない。(個人的には基本的にx, yは無しで運用するのが良さそうと感じている)