こんにちは、インフラエンジニアの小林です。
今回は、CloudWatch Metric Mathを使用したメトリクスの検索機能を解説し、そのメトリクスを使用したダッシュボードのTerraformでのサンプルコードをご紹介します。
はじめに
LCLでは AWS WAFのマネージドルールを使用し、悪意のあるリクエストからサービスを保護しています。
マネージドルールは簡単な設定で強力にサービスを保護してくれますが、ユースケースによっては誤検知の危険があります。現状、誤検知は発生していませんが、将来的にマネージドルールが更新された時などに、誤検知が増える可能性があります。
そのため、各マネージドルールがブロックしたリクエスト数を CloudWatch ダッシュボードで可視化し、何か問題があったときにすぐに気付けるようにしました。
また、CloudWatch ダッシュボードで表示するにあたり、今回のような複数のグラフを絞り込むために、Metric Math という機能を使用しました。
なお、ダッシュボードとは別に CloudWatch Aram を使用した slack 通知も作成しましたが、長くなりますので別記事にて紹介いたします。
Metric Mathとは?
CloudWatchのさまざまなメトリクスを、SQLのような構文でクエリできる機能です。
Metric Mathを利用することで、さまざまのメトリクスの合計や平均などを簡単に検索することができます。
Metric Mathの検索クエリの基本構文
Metric Math の基本的な構文は以下のようになります。
SEARCH(' {Namespace, DimensionName1, DimensionName2, ...} SearchTerm', 'Statistic')
SEARCH: 検索をするための Metric Math の関数です。SEARCHの 引数は、シングルクォートで囲った2つの文字列です。(ぱっと見、もっと引数があるように見えてややこしいですね)- 1つ目の引数は、
{}で囲ったところ{Namespace, DimensionName1, DimensionName2, ...}と、SearchTermがあります。 -
{}で囲ったところは、カンマ区切りで 名前空間(Namespace) と、 ディメンジョン を指定します。- 名前空間 とは、各メトリクスの大まかな分類です。 AWS/EC2 のように、サービスごとに分類されています。また、カスタムの名前空間も作ることができます。
- ディメンジョン とは、各メトリクスをが持つ固有の情報で、 SearchTerm にてメトリクスを絞り込むために使用します。
- 例えば、EC2であれば、
InstanceIdや、InstanceTypeなどを持っています。
SearchTermには、検索条件を入力します。次章の Metric Math のクエリ例 で解説いたします。- Statistic には、どのように統計を取るかを入力します。合計なら Sum 、平均ならば Average があります。
Metric Math のクエリ例
以下は、特定のWebACLの、複数のマネージドルールがブロックしたリクエストを探すクエリの例です
SEARCH('
{AWS/WAFV2,Rule,WebACL,Region}
Rule=(
“managed-rule-a” OR
“managed-rule-b” OR
“managed-rule-c”
)
WebACL="web-acl-name”
Region="${data.aws_region.current.name}"
MetricName=(
"BlockedRequests"
),
'Sum')
{AWS/WAFV2,Rule,WebACL,Region}AWS/WAFV2メトリクスを取る名前空間です。Rule,WebACL,Region絞り込み対象のディメンジョンです。
SearchTermRule=...: 表示したいルールを絞り込んでいます。複数あるため、OR 検索をしています。WebACL=...: 表示したいWebACLを絞り込んでいます。Region=...: 表示したいリージョンを絞り込んでいます。(何も書かないとデフォルトリージョンで絞り込んでくれることを期待しましたが、エラーが出ました)MetricName=...: 対象のどのメトリクスを取るかを決定します。今回はブロックしたリクエストを計測したいので、BlockedRequestsを指定します。
Statistic- 今回は、合計値を知りたいので、
Sumを指定します。
- 今回は、合計値を知りたいので、
ここまでで、Metric Mathを使用したメトリクスの検索方法を解説いたしました。 ここからは、上記のクエリを組み込んだダッシュボードを表示するTerraformのサンプルコードを紹介いたします。
Metric Mathで検索したメトリクスを表示するダッシュボードのTerraformのサンプルコード
locals {
blocked_managed_rules_expression_base = <<-EOS
SEARCH('
{AWS/WAFV2,Rule,WebACL,Region}
Rule=(
“managed-rule-a” OR
“managed-rule-b” OR
“managed-rule-c”
)
WebACL="web-acl-name”
Region="${data.aws_region.current.name}"
MetricName=(
"BlockedRequests"
),
'Sum')
EOS
blocked_managed_rules_expression = join(" ", split("\n", local.blocked_managed_rules_expression_base))
}
resource "aws_cloudwatch_dashboard" "waf_dashboard" {
dashboard_name = "waf_dashboard"
dashboard_body = jsonencode({
widgets = [
{
type = "metric",
x = 0,
y = 0,
width = 24,
height = 6,
properties = {
metrics = [
[
{
period = 3600,
expression = local.blocked_managed_rules_expression
}
]
],
region = data.aws_region.current.name,
title = "Blocked by managed rules"
stacked = true
}
]
})
}
簡単な解説
aws_cloudwatch_dashboardの dashboard_body に、ダッシュボードの設定をJSONで定義します。metricsのexpressionで、実際に検索したい Metric Math のクエリを設定します。ここに直接クエリを書くと、視認性が下がりそうでしたので、locals にクエリを分離しています。また、視認性を上げるためにクエリをヒアドキュメントで書いていますが、Metric Math に改行を入れることはできなかったので、後から削除しています。metricsのperiodでは、メトリクスの時間区切りを定義します。今回の場合は、1時間ごとのブロック数の合計が表示されますstacked = trueにて、複数のメトリクスが重なって表示されます。これにより、マネージドルール全体でどれだけブロックしたかを可視化できます
最後に、上記の設定にて実際に作成されたメトリクスのスクリーンショットを紹介いたします。 どのマネージドルールがどれだけブロックしたかと、全体でどれだけブロックしたかの両方が素早く把握できるグラフができ上がりました。

まとめ
CloudWatch の Metric Math は、クエリを使うことでかなり自由にグラフを作成することができます。
本記事が皆様の監視業務の一助になりましたら幸いです。
参考
- https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/aws-managed-rule-groups.html
- https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/search-expression-syntax.html
- https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/using-metric-math.html
- https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html