CloudFront のエラー監視精度を上げた話
はじめに
はじめまして、メドレー新卒入社 2 年目の森川です。
インフラ経験がまだ 4 ヶ月ほどの未熟者ですが、AWS 認定資格クラウドプラクティショナー の試験に合格することができました。上位の資格取得に向けて今後も勉強していきます。
先日私が担当させていただいた CloudFront のアラート改善について、問題の原因と対応方法を本記事で書かせていただきます。
よろしければお付き合いください。
背景と問題
弊社が運営しているプロダクトの一つ ジョブメドレー ではインフラ環境に AWS を利用しています。
監視には CloudWatch や Datadog などを使用しています。サービスの異常を検知するための設定のひとつに、CloudFront のエラーレスポンス増加を検知するためのアラート通知があります。
CloudFront が返すレスポンスのうち、特定の時間範囲の中で 4xx, 5xx 系のエラーを返した割合が閾値を超過したことを検知して、CloudWatch アラームから Lambda を通して Slack に通知を行っています。
ところが、ある頃を境に CloudFront での 4xx 系エラーレスポンスの発生割合が増加し、アラートの通知頻度が想定以上に高くなってしまいました。
原因
調査を行ったところ、刷新した社内システムにて以下 2 つの原因でアラートが発生していることが分かりました。
原因 1. 社外サービスからのアクセスでアラートが発生
CloudFront のログを確認したところ、社外サービス(Slack, Google スプレッドシートなど)からのアクセスに対してステータスコード 403 を返しているレスポンスログが数多く記録されていました。
これらのサービスに弊社の社内管理システムの URL がポストされると、プレビューを表示するためのリクエストが送信されますが、この時のリクエストが社外からのアクセスとして WAF で制限されていました。
インフラ刷新前から現在まで稼働している CloudFront のログも確認したところ、こちらでも同様のエラーレスポンスが発生していることが分かりました。しかし、エラー割合増加のアラートが頻発することは現在でもほとんどありません。
以前はジョブメドレーが持つシステム全体へのアクセスをひとつの CloudFront で処理していたため、アラート通知の割合として計算する際の母数が大きく、社外からのアクセスによるエラーが発生していても、その割合が閾値を超過することが少なかったからだと考えられます。
インフラ構成を刷新したことをきっかけに、これまで目立っていなかった社外からのアクセスという問題が表面化してきたのです。
原因 2. 利用者が少ない時間にエラーレートが高くなりアラートが発生
CloudWatch アラームでは、一定期間内でのレスポンスのうち、4xx, 5xx 系のエラーごとにその割合が閾値を超過したことを検知してアラートを発生させる設定としていました。
しかし、深夜など利用者が少ない時間に一度でもエラーが発生すると、その割合が跳ね上がってしまうことでアラート発生頻度が増加し、誤検知と言える状態になっていました。
以下の画像では、4xx 系エラーの割合が夜間に 100%となっている箇所が確認できます。(表示時間は UTC です)
対応方法
2 つの原因に対し、それぞれ対応を行いました。
対応 1. 特定の社外サービスからのアクセスをエラー検知の対象外とする
各サービスの設定により、プレビュー表示によるアクセスを停止させる選択肢が考えられます。しかし、該当するサービスすべてに設定を行うのは難しく、管理も複雑になりそうです。
そこで、特定の社外サービスからのアクセスを エラー検知の対象外とする 方針で対応を行いました。
ログのすべてを CloudWatch アラームの評価対象としていたために、誤検知と言えるアラートが発生しているのが現状です。したがって、評価させたいログだけに絞り CloudWatch で評価させることができれば解決が図れます。今回であれば、特定のユーザーエージェントや IP アドレスなどを除外して CloudWatch に渡すという処理が求められます。
その実現のため、今回新たに作成したのが Lambda の関数です。
S3 に CloudFront のログが保存されたことをトリガーに Lambda を起動させるように設定しました。
ログごとに記録されているリクエスト元のユーザーエージェントや IP アドレスなどを確認し、除外対象かどうかを判定します。
そうして選別を通過したログを今度はステータスコードの 5 つのクラス(1xx, 2xx, 3xx, 4xx, 5xx 系)ごとに振り分けます。
ただし、CloudFront ではステータスコードに 000
が入ることがあります。
ステータスコード 000
はアラートで検知したところで対応できることが特にないため、検知対象から除外する方針としました。
(S3 のログを直接確認すると 000
なのですが、Athena でログを確認すると 0
で表示されるため、少しハマりました)
こういった意図しない値がステータスコードに含まれていた場合などを検知できるようにするため、5 つのクラス以外の値が含まれていた場合に UNKNOWN_STATUS_CODE
なクラスとして分類するようにしました。
必要なものに絞ったログを 6 つのステータスパターンに分け、それぞれの件数を CloudWatch メトリクスへ PUT させます。
ここまでが Lambda の仕事となります。
各ステータスのログの件数を CloudWatch メトリクスで確認できるようになったので、レスポンス全体における 4xx, 5xx 系エラーの割合が算出できます。これを元に閾値を設定し、以前のようなアラートを作成することができました。
対応 2. CloudWatch アラームの検知ルールを調整する
利用者が少ない時間にエラーレートが高くなりアラートが発生する件については、 CloudWatch アラームの検知ルールを調整 することによって対応しました。
一定期間でのエラー数に閾値を定め、超過した際にアラートを通知するように変更しました。つまり、割合ではなく絶対数で判断させるようにしています。
以下の画像の緑色のグラフが新たな検知ルールで参照するものとなります。橙色で示しているのが 4xx 系エラーの割合ですが、これが 100%となっている箇所においても新たな検知ルールには反応していないことが分かります。
対応を終えて
Lambda を用いた集計処理の作成と、アラートの検知ルールの調整を行うことで、CloudFront のエラー監視精度を向上させることができました。
以前は頻繁にアラートがあがっていましたが、対応後はすっかり落ち着きを見せています。
システムの安定稼働を実現するためにも、適切にアラートを検知できるように今後も改善を図っていきたいと思います。
今回の課題に対する解決手段としてはシンプルな対応であったかとは思いますが、私には実りの多い紆余曲折な経験となりました。
AWS の基本的なサービスの連携を学ぶことができたことに加え、新たに作成する AWS のサービスの課金額の試算や、実行計画を定めてからの実装など事前準備を意識して取り組むことができました。恵まれた環境の中、日々学ばせていただいております。
さいごに
メドレーでは「医療ヘルスケアの未来をつくる」というミッションを掲げ、各プロダクトの開発・運営が進められています。
エンジニア・デザイナーをはじめ多くのポジションで新たなメンバーを募集しています。ご興味をお持ちいただけた方は、ぜひお気軽にお話しさせていただければと思います!
ここまでお付き合いいただき、ありがとうございました。