TerraformでCloudWatch Metric Mathを使ったアラームを作成する

Metric Mathを使用してCloudWatch Alarmを設定した際のTerraformのサンプルコードを紹介します
2022.09.29

はじめに

ネクストモードの南です。

先日RDSのメモリ使用率の監視を構築する機会があり、Terraformで作成をしました。
RDSのメモリ使用率をメトリクスとして取得するためにMetric Mathを駆使する必要があったのですが、Terraformで書くとわりに面倒な部分もあったので備忘も兼ねて記事にまとめます。

アーキテクチャについては以下の記事を参考にさせていただいております。

構成概要

RDSの標準メトリクスでは、使用可能なメモリ容量という観点ではFreeableMemoryが使用できますが、これだけだと使用率(xx%)の形にすることはできません。

RDSの拡張モニタリングを有効化すればメモリの合計量を取得することができるので、Metric Mathを使ってFreeableMemoryと計算すればメモリ使用率を値として出すことができます。

拡張モニタリングはCloudWatch Logsに配信されるため、ロググループにメトリクスフィルターを作成してメトリクスを集計できるようにします。
その上で、Metric Mathを使用してCloudWatch Alarmを設定していきます。  

今回はこちらの構成をTerraformで構築しました。

なお、前提としてRDS側で拡張モニタリングの有効化が必要となります。
拡張モニタリングを有効化するにあたっては以下の公式ページをご参考ください。

サンプルコード

CloudWatch Logs、CloudWatch Alarmのサンプルコードが以下となります。

ロググループのRDSOSMetricsについては、すでに作成済みであれば不要です。
(先にマネジメントコンソールからRDSの拡張モニタリングを有効化していれば自動的に作成されます。)

cwlogs.tf

# ロググループ
resource "aws_cloudwatch_log_group" "logs-rdsosmetrics" {
  name              = "RDSOSMetrics"
  retention_in_days = 30
}

# メトリクスフィルター メモリ合計量
resource "aws_cloudwatch_log_metric_filter" "rds-memorytotal" {
  name           = "rds-memorytotal"
  pattern        = <<PATTERN
    { ($.instanceID="instance id") && ($.memory.total = *) }
PATTERN
  log_group_name = aws_cloudwatch_log_group.logs-rdsosmetrics.name

  metric_transformation {
    name      = "Memorytotal"
    namespace = "custom"
    value     = "$.memory.total"
    dimensions = {
      instanceID = "$.instanceID"
    }
  }
}

cwalarm.tf

# アラーム
resource "aws_cloudwatch_metric_alarm" "memoryusage-rds" {
  alarm_name          = "cw-alarm-memoryusage-rds"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  threshold           = 90
  treat_missing_data  = "missing"
  datapoints_to_alarm = 1
  actions_enabled     = "true"
  alarm_actions       = ["sns topic arn"]
  ok_actions          = ["sns topic arn"]

  # Memorytotal用metric_query
  metric_query {
    id = "m1"
    metric {
      namespace   = "custom"
      metric_name = "Memorytotal"
      period      = 300
      stat        = "Average"

      dimensions = {
        instanceID = "instance id"
      }
    }
  }

  # FreeableMemory用metric_query
  metric_query {
    id = "m2"
    metric {
      namespace   = "AWS/RDS"
      metric_name = "FreeableMemory"
      period      = 300
      stat        = "Average"

      dimensions = {
        DBInstanceIdentifier = "instance id"
      }
    }
  }

  # 計算式用metric_query
  metric_query {
    id          = "e1"
    return_data = true
    expression  = "(m1-m2/1024)/m1*100"
    label       = "MemoryUsage"
  }
}

メトリクスフィルターの方では、フィルタパターン{ ($.instanceID="instance id") && ($.memory.total = *) }で拡張モニタリングのメモリ合計量の値をフィルタし、metric_transformationでメトリクスとして集計できるようにします。

CloudWatch Alarmの方では、Memorytotal用のmetric_queryで、メモリ合計量をm1として設定します。
2つ目のFreeableMemory用のmetric_queryで使用可能なメモリ容量をm2として設定し、最後に計算式用のmetric_queryで、メモリ使用率を(m1-m2/1024)/m1*100で計算しています。

マネジメントコンソール上でも設定が反映されていることが確認できます。


参考

以下の記事を参考にさせていただきました。ありがとうございます!

RDSのディスク、メモリ使用量を%で表示する