ENECHANGE の CTO 室でインフラエンジニアを務めている岩本です。
今回は CloudWatch Metric Math の DIFF 関数によって解決できた課題をご紹介します。課題そのものは地味ですが、DIFF 関数が役立つ場面は多そうだと感じたため、記事にする次第です。
# 状況
AWS には Trusted Advisor というサービスがあります。コスト最適化、パフォーマンス、セキュリティといった観点から適切なアクションを勧めてくれる便利なサービスです。
Trusted Advisor の推奨アクション例には下記があります。
- EC2 インスタンスに関連づけられていない Elastic IP アドレスを解放する
- セキュリティグループの不必要なルールを削除する
- 特定の IP アドレスからのみにアクセスを制限する
ENECHANGE では、Trusted Advisor の推奨アクションのうち、実施すべきと判断したものだけを実施しました。不要と判断したものには、たとえば「VPC 数の制限緩和」があります。緩和が実際に必要となったときに申請すれば済むからです。
# タスク
しかしながら、実施すべきアクションを実施すれば終わり、というわけにはいきません。
たとえば下記の事象が起こると、推奨アクションが復活してしまいます。
- EC2 インスタンスに関連づけられていない Elastic IP アドレスをすべて解放したのに、また現れてしまった
- セキュリティグループの不必要なルールをすべて削除したのに、また追加されてしまった
- 任意の IP アドレスからのアクセスをすべて制限したのに、また許可されてしまった
そのような事象を予防できればよいのですが、現時点では手段がありません。監査サービスである AWS Config を使ったとしても、コンプライアンス違反となるアクションは防げないのです。
また、Trusted Advisor にはチェック状況を週次でメール通知する機能がありますが、推奨アクションに1週間も気づけない事態は避けたいところです。セキュリティ向上の推奨アクションに気づくまでに事故が起こると困ります。
そこで、推奨アクションが増えたら「すぐに」気づける仕組みを作ることにしました。
# 行動
## 「EventBridge による通知」案の検証
まず試したのは、Trusted Advisor のチェックステータスの変化を EventBridge で通知する方法でした。「Amazon CloudWatch Events での Trusted Advisor チェック結果のモニタリング」として公式ドキュメントで紹介されているので、うまくいきそうです。
しかし、この方法では同じ通知が何度も来てしまい、目的を果たせませんでした。EventBridge は現状、ステータスに変化がなくてもチェック結果を通知するようです。
## 「CloudWatch アラームによる通知」案の検証
次に試したのが、本題である CloudWatch Metric Math の DIFF 関数を用いた監視方法でした。
DIFF 関数を使うと、CloudWatch メトリクスの各値とその前の値の差に基づく新たな時系列が作れます。メトリクスの各値が「2, 2, 3, 5, 4」だった場合、「0, 1, 2, -1」という時系列が作れるのです。
この DIFF 関数を、Trusted Advisor のメトリクスである RedChecks と YellowChecks に適用すれば目的を果たせそうです。前者は「緊急度が高くアクションが推奨されるチェック項目の数」を、後者は「調査が推奨されるチェック項目の数」を意味します。
さっそく「コスト最適化の RedChecks」や「パフォーマンスの YellowChecks」といったメトリクスの差に基づく時系列を用意し、差が 1 以上だった場合にアラーム状態とする CloudWatch アラームを作ったところ、意図通りの挙動となりました。
下記は Terraform テンプレートの例です。なお、ここでは定義していませんが、SNS トピックから先の経路には AWS Chatbot と Slack を選択しました。
resource "aws_cloudwatch_metric_alarm" "this" { for_each = var.cloudwatch_metric_alarm_map alarm_name = each.value.alarm_name comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = 10 threshold = 1 actions_enabled = true alarm_actions = [aws_sns_topic.this.arn] datapoints_to_alarm = 1 treat_missing_data = "ignore" metric_query { id = "m1" return_data = false metric { dimensions = { Category = each.value.category } metric_name = each.value.metric_name namespace = "AWS/TrustedAdvisor" period = 60 stat = "Maximum" } } metric_query { id = "e1" expression = "DIFF(m1)" label = "diff" return_data = true } }
# 結果
以上の通り、DIFF 関数を用いて、Trusted Advisor の推奨アクションが増えたらすぐに気づける仕組みを実装できました。運用を始めたばかりのため通知はまだ来ていませんが、忘れた頃に届くだろうと思っています。
今回のタスクを通じて、ちょっとした監視を実装するだけで、少なからぬ安心感が得られることを実感しました。見逃している監視すべきメトリクスは Trusted Advisor 以外にも多々あるはずなので、AWS のドキュメントを漁って探すことにします。