カミナシ エンジニアブログ

株式会社カミナシのエンジニアが色々書くブログです

監視ツールを迷ったら CloudWatch から始めてみるのもありなのでは

こんにちは、新規プロダクトの開発をしています、a2 (@A2hiro_tim )です。 昨日、開発してきたプロダクトについて、正式リリースを発表させていただきました 🎉

prtimes.jp employee.kaminashi.jp

さて、新規プロダクトの立ち上げは、技術選定や運用ツールの自由度が高く、どの監視ツールを使うか、選択に迷うこともあると思います。

我々のチームでは複数ツールの使用経験はあるものの、特定のツールの導入経験や深い知見があるメンバーはいなかったので、フラットに比較検討し、 Amazon CloudWatch の利用から始めてみよう、と意思決定しました。 主な選定理由は、

  • AWS エコシステムの中で完結できるため、Terraform Cloud などの既存の設定を流用できて新しく覚えることが少ない、AWS 上でコストを一元管理できる、等のメリットがある。
  • サービス開始時でユーザーが少ない段階では、その他のツールは導入コスト、学習コストが割に合わない

の 2 点でした。

Amazon CloudWatch はできることが少ないイメージをもっていましたが、比較のために調査してみると、「意外と色々できるぞっ」と認識を改めました。 今回は Amazon CloudWatch を使った監視体制の構築の一例としてダッシュボード作成と、Slack 通知を実現する流れをterraform のコードも書きつつ紹介します。

監視ツール選定に悩んでいるチームに、新しい情報を提供できれば幸いです。

サマリー

以下のような構成を取ることで、Amazon CloudWatch で必要な監視体制を整えることができました。不足点もありますが、これから運用を整えるチームにおいては十分な機能を備えています。その他、CloudWatch Alarm にはアラームを受けとったエンジニアリングメンバーがどのような初動対応をすれば良いかを記載し、スムーズで正確な運用になるように工夫しています。

CloudWatch を活用した監視システムの全体像

1.ダッシュボードのガワを作成

監視ツールの最終的なアウトプットはダッシュボードでしょう。CloudWatch もダッシュボードを作成できます。空の状態で作っておきます。

resource "aws_cloudwatch_dashboard" "web_server" {
  dashboard_name = "WebServer"

  dashboard_body = jsonencode({
    widgets = []
  })
}

apply した後に、CloudWatch のページを開くと、空のダッシュボードが作られています。

空の状態のダッシュボード

ダッシュボードには、メトリクスや Markdown で書いたテキスト、CloudWatch Alarm などをウィジェットとして配置できます。

2. CloudWatch Alarmの作成

ダッシュボードは一覧性を高めるものであり、実際に欲しいのはシステムの監視です。Amazon CloudWatch の中で閾値を設定してアラートを上げたりできるのは、 CloudWatch Alarm です。 例として、 Amazon SQS を CloudWatch Alarm を使って監視してみます。

CloudWatch Alarm 作成に Amazon SNS topic が必要になるので、先に作っておきます。この Amazon SNS topic は、アラートを Slack に通知する時に使います。

resource "aws_sns_topic" "cloudwatch_alarm_for_slack_topic" {
  name = "cloudwatch-alarm-topic"
}

CloudWatch Alarm は、最初はマネジメントコンソールから定義するのがわかりやすいのでおすすめです。CloudWatch > Alarms から “Create Alarm” を押して進めます。

CloudWatch Alarm 作成途中の画面

閾値の計算方法や数値を設定できます。シンプルな監視には十分でしょう。他にも、正規分布を想定した異常検知も設定可能です。

CloudWatch Alarm を作成したら、Terraform コードとして import します。

import {
  to = aws_cloudwatch_metric_alarm.sqs_approx_age_of_oldest
  id = "sqs_approx_age_of_oldest" # alarm に設定した名前
}
terraform plan -generate-config-out=generated.tf

以下のように terraform block が生成されます。

# __generated__ by Terraform from "sqs_approx_age_of_oldest"
resource "aws_cloudwatch_metric_alarm" "sqs_approx_age_of_oldest" {
  actions_enabled     = true
  alarm_actions       = ["arn:aws:sns:ap-northeast-1:012345678901:cloudwatch-alarm-topic"]
  alarm_description   = null  # 書いておくと便利。後述
  alarm_name          = "sqs_approx_age_of_oldest"
  comparison_operator = "GreaterThanThreshold"
  datapoints_to_alarm = 1
  dimensions = {
    QueueName = "batch_queue"
  }
  evaluation_periods = 1
  metric_name        = "ApproximateAgeOfOldestMessage"
  namespace          = "AWS/SQS"
  period             = 300
  statistic          = "Average"
  threshold          = 300
}

Amazon SQS を terraform で生成していれば、 alarm_actions は書き換えておきます。

alarm_actions       = [aws_sns_topic.cloudwatch_alarm_for_slack_topic.arn]

3. Alarm のダッシュボードへの追加

作成した Alarm をマネジメントコンソールから Dashboard に追加して、おまけで Text ウィジェットを追加してみます。

Text と Alarm を追加したダッシュボード

CloudWatch Alarm はそのステータスによって囲んでいる線の色がかわります。設定した正常範囲に収まっていない時は赤くなるのでわかりやすいです。

あとは同じ要領で好きなだけウィジェットを追加していきます。 Dashboard がある程度できたら、terraform に反映します。 ”View/edit Source” からJSON形式でダッシュボードの中身を閲覧できます。

JSON を表示する導線

我々のチームでは現在、JSON をコピーしてファイルに保存して templatefile で参照しています。

resource "aws_cloudwatch_dashboard" "web_server" {
  dashboard_name = "ApplicationStatus"

  dashboard_body = templatefile("../../modules/dashboard/dashboard-source.json", {
    cloudwatch-alarm-for-slack-topic = aws_sns_topic.cloudwatch_alarm_for_slack_topic.arn
  })
}

ウィジェットの座標指定や ARN 指定の置き換えなどが煩雑なので、他にも選択肢を提案しておきます。

  • copy した JSON を jsonencode の引数に渡す(必要に応じて変換ツールを利用 )方法もあります。
  • そもそもダッシュボードはコード管理しない方針もありえると思います。
  • 座標指定については、頭の中に render がある人は最初から直接 JSON を編集することでカバーできるかもしれません。健闘を祈ります。

4. メトリクスやログをダッシュボードに表示する

メトリクスやログの表示は、ダッシュボードの画面から行いますが、 CloudWatch Alarm の作成とほぼ同じです。 複数のメトリクスを同じグラフに表示できたり、Logs Insights の結果を表示できたりします。

ぽちぽち触ればある程度分かると思うので、本記事では割愛します。

5. アラートを Slack に通知する

監視している値に異常があれば、気づいてすぐに対応に着手できるようにしておきたいです。よくある例として Slack 通知の方法を取り上げます。CloudWatch Alarm の作成時に指定した Amazon SNS topic から、Slack への通知までの処理を追加します。

Slack への通知には AWS Chatbot を使います。他にも Email 経由での通知、Slack app と Lambda を使った通知、の二つを検討しましたが、通知の分かりやすさ、運用の簡単さから Chatbot を利用することに決めました。

AWS Chatbot 用の subscription を作ります

resource "aws_sns_topic_subscription" "cloudwatch_alarm_for_slack_subscription" {
  topic_arn = aws_sns_topic.cloudwatch_alarm_for_slack_topic.arn
  protocol  = "https"
  endpoint  = "https://global.sns-api.chatbot.amazonaws.com"
}

AWS Chatbot は terraform 公式のリソースとしてはリリースされていません。コミュニティ版がありますが、どうやら近い内に公式からリリースされそう*1なので、今はマネジメントコンソールから作ることにします。

AWS Chatbot を作成した後、認証処理を済ませたら、test message を送って確認できます。

テストメッセージの Slack 投稿

以上で設定は完了で、実際に CloudWatch Alarm で設定した閾値を超えると、 Slack メッセージがChatbot から届きます。

テストメッセージの Slack 投稿

実際の運用やチームでのアラート対応においては Slack 通知だけでは不十分で、チケット管理等も必要になってくると思いますが、本記事では割愛いたします。

6. Alarm に Description を記載して、運用負荷を大きく下げる

Slack に投稿されるメッセージの右下に Alarm Description が記載されています。CloudWatch Alarm に設定された Description です。(先述の terraform コードはサンプルコードなので null になっています) スクリーンショットに記載してあるのは仮の内容ですが、実際に運用している Alarm では、 Description に以下を書くようにしています。

  1. どんな状況か、どんなユーザー影響が出ているか
  2. そのアラートを見た人は次にどういう行動をとればいいか(必要に応じて手順書へのリンクなども記載)

特に 2 はこだわりがあるポイントです。なんとなく監視対象を追加していくだけだと、1を書いて終わることが多いです。それだと、アラートが鳴ってもシステムに習熟している人でないとどうすればいいかわかりません。

例えば、SQS のキューのメッセージの滞留の CloudWatch Alarm の記載は以下のようになっています。

タスクA のキューに60 秒以上 message が滞留しています
サービスA でのユーザーの追加・削除が即時反映されていません
**対応**
滞留の原因と担保するサービス品質の観点(link)から、以下のいずれかを行なってください
- worker の数を増やす
- メッセージの処理を最適化して、時間を短縮する
- 「ユーザーの同期にはX分程度時間がかかる場合があります」と画面表示する

対応を書いておくと、忘れたころにアラートが鳴っても、やることはそこに書いてあるので明確です。 また、そもそもアラートを追加する際に「監視対象がアラート状態になった時に、どうすればいいか」を考えるようになるので、実際の運用フローをイメージして実装をあらかじめ修正しておいたり、他のメトリクスを監視対象に追加したり、スムーズな運用体制を構築できます。

触ってみてわかったこと

以上が、 Amazon CloudWatch を活用して監視体制を構築する大まかなフローになります。 最終的な構成のイメージは以下のようになります。

CloudWatch を活用した監視システムの全体像

最後に、実際に構築してみて、想定と違ったこと、注意点を列挙しておきます

  • CloudWatch Alarm がイベントを発行するのは、ステートが変わった時のみです。そのため、「15分間は通知しないようにサイレンスしたい」「直っていない間はずっと通知したい」といったことはできません。EventBridge や Lambda を活用して実現するか、Datadog 等のツールに乗り換える必要があります。
  • 既に触れた通り、Dashboard のコード管理は煩雑です。terraform での差分がわかりづらいといった問題もあります。我々のチームではインフラ環境をモジュール化して複数の環境に適用している関係で IaC にこだわっていますが、ダッシュボードはコード管理から外して Production 環境のみでぽちぽちするのも手かと思います。
  • メトリクスは Dimension で特定するようになっており、目的のメトリクスを CloudWatch の画面上から探すのが大変かもしれません

おわりに

Amazon CloudWatch を活用して監視の土台を整えてみました。運用を進める中で、早くも不足する点や運用上の手間になる箇所もみえてきています。痒いところに手が届かない感触もありますが、プロダクトの初期フェーズなど、システム運用への大きな時間的・金銭的投資が難しい PMF 前のような状況下では十分だと思います。

私個人は、機能が豊富なツールを入れると、凝ってしまったり、知らない機能を使ってみたくなるタイプ*2なので、その意味でも、ある程度の不自由がある方が却っていいことがあるかも、と自分を正当化したりしています。

チーム数が増えたり、サービスが成長して細かい要求が出てきた段階で、あらためて監視ツールの拡張や見直しを行うことを最初から視野にいれています。チームのスキルセットに応じて、スタートアップに求められる速度を実現できるツール選択が大事だと思います。

運用まで視野にいれつつ、スタートアップの速度とのバランスを取りながら意思決定して物事を進めていく、そんなプロダクト志向の方、AWS 好きな方、カミナシで一緒に働きましょう!

カミナシでは面談からスタートさせていただいております、ぜひご応募お待ちしております!

herp.careers