はじめに
こんにちは。BtoB開発チームの中島です。Fulfillment by ZOZO(以下、FBZ)で提供しているAPIシステムの開発・運用を担当しています。
FBZの運用では、エラーログ発生時にアラートを通知させ、エラー内容をチェックして対応要否を判断しています。しかし、アラート通知が多すぎると運用負荷が高くなったり、重要なアラートを見落とすリスクもあるため、適切な量で通知することが重要になってきます。
本記事では、FBZで実施した例を紹介しながらアラート通知の最適化について解説します。
FBZにおけるサービス監視
FBZでは、ログ解析によるサービス監視を実施しています。
AWS Lambda(以下、Lambda)から出力されたログを解析し、外部サービスのPagerDutyやDatadogに連携して監視しています。必要に応じてフィルタリングを行い、ログの通知量を都度調整しながら運用をしていました。
ログ解析によるサービス監視の詳細は、過去記事をご覧ください。 techblog.zozo.com
サービス監視の課題
上記の過去記事でも紹介しているように、監視不要なログのフィルタリングを実施することでアラートを削減する効果がありました。
しかし、FBZサービスの機能追加などに伴い、再度アラートが増えてきました。デイリーで数十件程度アラートが通知されることも多く、通知が多いことでアラートがオオカミ少年化し始めていました。
そのため、フィルタリングだけでは対応が不十分と考え、監視方法を再検討することにしました。
通知されるアラートの現状分析
監視方法を再検討するために、まず現状の分析を実施しました。
現状は通知されるアラートを運用担当者が内容を確認して、1件1件対応要否を判断しています。運用を担当するメンバーから、日々運用をしている中で以下のLambdaのアラートが多く、ノイズになっている可能性が高いという意見が出てきました。
- バッチ処理内でFBZ外と連携しているLambda(以下、外部連携バッチ)
- リトライで回復していることが多い
- FBZのデータを参照するAPIのLambda(以下、参照系API)
- 一時的なタイムアウトが多い
ただし、あくまでも感覚的なものでしかなく、定量的なものではありません。仮説が間違っている場合、対策を実施しても改善につながらないため、アラートの発生状況を定量的にデータ分析することにしました。
アラート分析の観点
アラートを分析する観点を明確にします。今回は、「アラート発生件数」ではなく「アラート発生日数」を指標としました。
アラート発生件数を観点として考えてしまうと、他のアラートよりも大量に発生したアラートが1日だけある場合、その対策をしようとしてしまいます。しかし、それだけを対策しても運用改善に繋がりません。
定常的に発生するようなアラートに着眼するためにも、複数日にまたがって発生しているアラートの対策をすることで、運用改善につながると考えました。
高頻度でアラートが発生していたLambda
アラート発生日数でFBZ内のLambdaを調査しました。過去100日程度の期間で調査し、週1回以上の頻度でアラート発生しているものを高頻度と定義して抽出したところ、以下のような結果になりました。
予想通り、「外部連携バッチ」と「参照系API」のアラートが多く、全体の半数以上を占めていることがわかりました。仮説が検証できたので、実際にこれらのアラート対策を実施しました。
外部連携バッチのアラート対策
まず、外部連携バッチで実施した具体的なアラート対策について説明します。
外部連携バッチのエラー内訳を調査したところ、99.5%がリトライで成功していることがわかりました。
FBZのバッチ処理はLambdaの非同期処理で実行しています。Lambdaは非同期で動作する場合、エラー発生時は自動的に3回リトライする仕様になっています。
エラー発生時のほとんどのケースは、このリトライが成功しており、自動回復していました。そのため、リトライでも自動回復していないケースに絞って監視をすることで、アラートの最適化が可能だと考えました。
具体的には、Lambda Destinations(非同期呼び出しの宛先指定)を使った監視に変更しました。エラーログの監視ではリトライで成功しているものも検知してしまいますが、Lambda Destinationsを使うことでリトライをしても成功しなかったものだけを通知できます。そのため、外部連携バッチの監視は、エラーログの監視をやめ、Lambda Destinationsの通知の監視に切り替えました。
FBZではServerless Frameworkを使っているため、Serverless.yml
に以下のような設定を加えることでLambda Destinationsを設定できます。
functions: helloStarting: handler: handler.starting destinations: onFailure: arn:of:some:existing:resource
onFailureにアラート通知用のLambdaを設定することにより、リトライでも成功しなかったもののみアラート通知する仕組みを実現しています。
参照系APIのアラート対策
次に、参照系APIでのアラート対策について説明します。
参照系APIで発生しているアラートの詳細を調査したところ、99.1%がネットワーク起因の一時的なエラーでした。
参照系のAPIということもあり、一時的に発生している点と再実行で取得可能となる点から1件1件の監視は不要であると判断しました。また、実際の運用時にエラーを検知した際にも、一時的なエラーの場合は対応不要と扱っていたことが多い点も監視不要とした理由です。
1件1件は監視不要ですが、短時間に頻発した場合は障害の可能性があります。そのため、頻度ベースでの監視をすることで、監視の最適化が可能だと考えました。
頻度ベースの監視は、Datadogを利用しました。Datadogを利用することにした理由は以下の点です。
- 既にサービス監視のためにDatadogを利用していた点
- API Gatewayのメトリクスで頻度ベースの監視ができる点
- FBZ側に新規の作り込みが不要な点
既にサービス監視のためにDatadogを利用していました。しかし、ログ調査での利用がメインであり、監視での利用はほとんどしていませんでした。
今回、頻度ベースで監視したいと考えた際に、Datadogのモニター機能でアラートのしきい値設定を、固定値だけではなく過去データから自動設定できるため、Datadogを利用しました。モニター設定の詳細などはDatadogのマニュアルをご確認ください。
AWSとDatadogのインテグレーションを事前に設定しておく必要はありますが、FBZ側での新規開発なしで、頻度ベースの監視が実現できました。
アラート最適化の効果
今回、アラートの最適化として、以下の対策を実施しました。
- 外部連携バッチはLambda Destinationsでアラート通知したものを監視
- 参照系APIはDatadogでエラー頻度ベースでのアラート通知したものを監視
これらの対策を実施したことで、アラートの発生数が、1日数十件から数件程度に抑えられました。昨年にはアラートが0件という日もあり、アラートの発生頻度が下がったことで運用工数を月あたり約15時間削減できました。
まとめ
アラートがオオカミ少年化すると、アラート対応が疎かになりサービスの安定的な運用ができなくなります。それを防ぐために、アラートの通知は必要最小限に抑える必要がありますが、単純なエラーログの監視では通知を減らすのにも限界があります。
今回はFBZで実施した監視手法として、Lambda Destinationsを利用した非同期実行Lambdaの監視と、Datadogを利用した頻度ベースでの監視を紹介しました。この対応によって、アラートを最適な量で通知できるようになりました。
今後は、分散トレーシングのために、Datadog APMの導入などを検討しています。
さいごに
ZOZOテクノロジーズでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください!