実務で使えるCloudWatch活用事例 (+Qの所感)

はじめに

この記事は Akerun Advent Calendar 2023 - Qiita の5日目の記事です。

みなさま初めまして。SW開発部の @msuz です。Photosynthに入社して約1年になります。 Akerun入退室管理システムの開発運用、PjM、EMなどをやってます。

Amazon Q の話

AWS re:Invent 2023 にて生成AIアシスタントサービス「Amazon Q」が発表されました。

早速ドキュメントDevelopersIO などの記事を読み漁りながら手元の環境で試してみました。 一応の機能としてはそれなりに使えそうですが、現プレビュー版では日本語非対応なので、本格的な実戦導入はまだ先になりそうです。

近い将来SREのAWS管理業務やCSのコールセンター業務の改善に繋がることを期待して引き続きウォッチしていきます。以上!

ここからが本題、AWS CloudWatchのお話です。

CloudWatch とは?

Amazon CloudWatchは、AWSリソースやアプリケーションのパフォーマンスを監視し、メトリクスやログを収集するAmazon Web ServicesAWS)のモニタリングおよび管理サービスです。

今回はCloudWatch関連のサービスを弊社フォトシンスのシステム運用でどのように使っているのか、実務ベースでの活用事例をご紹介します。

標準メトリクス

ほとんどのAWSサービスは自動的にメトリクスをCloudWatchに送信します。 CPU使用率やネットワークIOなど一般的なメトリクスに加えて、各サービスの機能に合わせた固有のメトリクスがあります。

メトリクスがたくさんあり過ぎてどれを見れば良いかが分からないという方はAmazonQで質問してみてください。 分かりやすい説明と回答の根拠となった情報ソースへのリンクを提示してくれます。

AmazonQ - RDSの重要メトリクス

日頃私たちが機能リリースやシステムメンテナンスをする際には、以下のメトリクスでスパイクやトレンド変化が無いかを確認しています。

  • ApplicationELB
    • HTTPCode_ELB_5XX_Count
    • HTTPCode_ELB_4XX_Count
    • TargetResponseTime
    • RequestCount
  • EC2
    • CPUUtilization
    • NetworkIn/Out
  • RDS
  • CPUUtilization
  • DatabaseConnections
  • Queries
  • SlowQuery

カスタムメトリクス

標準メトリクスで不十分な場合はカスタムメトリクスを使うことでより柔軟なモニタリングが可能になります。 弊社で運用しているカスタムメトリクスをいくつか紹介します。

EC2インスタンスの拡張メトリクス

一般的なサーバ監視項目でありながら、なぜかCloudWatchの標準メトリクスに入っていないものがいくつかあります。 「ログローテートの設定をミスってディスクが溢れた」「コスト削減でインスタンスサイズを絞り過ぎた」などありがちな運用トラブルには備えておきましょう。

load_average=`uptime | awk 'BEGIN{FS="load average: "}{print $2}' | awk 'BEGIN{FS=","}{print $1}'`
memory_used=`free | grep "buffers/cache" | awk '{print ($3*100)/($3+$4)}'`
swap_used=`free | grep "Swap" | awk '{print ($3*100)/($3+$4)}'`
disk_used=`df -l | grep "${disk_name}" | awk '{print ($3*100)/$2}'`

上記のようなUNIXコマンドで数値を取得し aws cloudwatch put-metric-data に渡すスクリプトをcrontabで定期的に実行しています。

EC2インスタンス上のプロセス数

UNIX標準機能や各種アプリケーションが正しく起動されていることを確認するためにプロセス数を監視しています。

process_count=`ps awux | grep -v grep | grep -w "${process_name}" | wc -l`

対象は ntpd, crond, nginx, unicorn worker, delayed_job, rabbitmq、自前のデーモンなどです。

ntpdはおそらく過去障害の再発防止策でしょう。歴史が垣間見えて興味深いです。

RabbitMQ管理

弊社ではIoTデバイスへのメッセージングプロトコルとしてMQTTを使っています。 以前はAWS IoTを利用していましたが、諸般の事情により現在はEC2インスタンス上でRabbitMQ Brokerを運用しています。 前述のプロセス数のほか、接続数、同一IDでの重複、クラスタ間でのミラーリング、書き込みエラーなどの監視項目一式を独自で設定しています。

改めてマネージドサービスのありがたみを感じます。

アプリケーションログ

サーバやミドルウェアで取得できるメトリクス以外だけでなく、アプリケーションの性能やビジネス指標に関わる数値を監視することも重要です。 Ruby on Railsなどのプログラムから出力されたログをCloudWatchLogsに送信・蓄積し、メトリクスフィルターを適用することでCloudWatchのメトリクスとして扱うことが出来ます。

設定例です。以下のようなログに対して

I, [2023-12-05T12:34:56.789012 #24680]  INFO -- : my_app:peformance duration: 13.579 sec, records: 432

以下のようなフィルターパターンを適用してやると

[lv, timestamp, level, s1, s2, app_name="my_app:peformance", duration_key="duration:", duration_value, duration_unit="sec,", records_key="records:", records_value]

メトリクス値 $duration_value として 13.579 が取得できます。 ここに名前空間・メトリクス名・Unitを割り当ててやればカスタムメトリクスとして利用できるようになります。

アプリケーション開発時のログ設計が鍵となります。

ダッシュボード

AWSサービスの標準的なメトリクスについては自動ダッシュボードを使うのがお手軽です。 それでも数が多過ぎるし、カスタムメトリクスが見られないので、結局カスタムダッシュボードが必要になります。 システムメンテナンスや障害発生時に必要なメトリクスがすぐに見られるようにしておきましょう。

アラーム

CloudWatchアラームは、メトリクスに異常があった際に運用者に通知するための仕組みです。 監視設定は新サービスのリリース時に必ず実施して、システム構成変更や障害試験のタイミングで逐一見直しましょう。

判定方法は、静的な閾値のほか、数式や統計モデルを用いた異常検知などがあります。 通知方法は、Amazon SNSでのメールやSMS、AWS Chatbot経由でのSlack通知、LambdaとAWS Connectを組み合わせた電話発信など。 そもそもEC2の再起動やオートスケーリング、Lambdaをトリガーして自動復旧させるという手もあります。

と言いつつ、弊社ではSentry, PagerDutyなどの運用ツールを使っているため、 CloudWatchアラームでは メトリクス単体×静的閾値×Slack通知 ぐらいしかやってません。 機会があれば今後色々試してみたいと思います。

Logs Insights を使ったログ解析

トラブル発生時の原因究明や影響範囲調査のために、どうしても大量のアクセスログを漁らなきゃいけない場面ってありますよね。 複数台のサーバにログインしたりS3から大量のログファイルをダウンロードするのは手間もかかりサーバ負荷やセキュリティも気になる。 そんな時はLogs Insightsを使ってCloudWatch Logsのログデータをインタラクティブに検索して分析しましょう。 クエリ構文は独特だけど慣れれば簡単!ChatGPTに書いてもらうという手もあります。

記述例です。以下のようなログデータに対して、

time:5/Dec/2023:00:01:00 +0900 host:192.0.2.0 request:GET /v1/hoge HTTP/1.1 status:200
time:5/Dec/2023:00:02:00 +0900 host:198.51.100.0 request:GET /v1/hoge HTTP/1.1 status:200
time:5/Dec/2023:00:03:00 +0900 host:198.51.100.0 request:GET /v1/fuga HTTP/1.1 status:200

以下のクエリを実行すると、

fields @timestamp, @message, @logStream, @log
| parse @message /host:(?<host>[^\s]+)/
| stats count(@timestamp) as record_count by host
| order by record_count desc

以下の結果が得られます。

# host record_count
1 198.51.100.0 2
2 192.0.2.0 1

なお、CloudWatch Logs Insightsは従量課金制ですので、過度なコストが発生しないようにご注意ください。 例えば、以下の点に留意すると良いでしょう。

  • クエリの作成・検証中は期間を「5分」にする
  • 集計した結果は消さずに保存しておく
  • 対象期間が長過ぎる場合は分割して実行する
  • filterは早めにかける、不要なfieldは取得しない、不要なsortはしない

さいごに

今回はフォトシンスにおけるCloudWatchの活用方法をご紹介しました。 これからクラウド監視に取り組まれる方の一助になれば幸いです。 私たちも日々便利な技術を取り入れながら、品質の高いシステムを提供していきたいと思います。

最後までお付き合い頂きありがとうございました。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com