SLO策定とアラート設定までの長い道のり

こんにちは、@ueokandeです。早速ですが、皆さんが運用しているサービスには、SLO (Service-level objective: サービスレベル目標) がありますか?アラートの監視項目はどのように設定して、基準値をどのように決めていますか?

社外とのコミュニケーションだけでなく、社内向けのSLOを決めておくことで、サービスの健康状態を知るための手がかりや、普段の開発・運用タスクの優先度を決める上での指標にもなります。 またSLOがあると、サービスを監視するアラートに、理にかなった閾値を設定できます。 この記事ではAWS版kintoneの、SLOとアラートを設定するまでの記録について紹介します。

cybozu.com版kintoneのSLOとアラート

国内のcybozu.comで運用しているkintoneにも、もちろんSLOやアラートはあります。 しかし現状のSLOはkintoneが利用できるかどうかであって、性能やスループットなどの、機能面やお客様視点の指標はありません。 そして、それらに基づくアラートも設定できていませんでした。 そのため「kintoneが遅い」というお問い合わせがあっても、障害なのか否かの判断ができなかったり、適切な監視項目や閾値を設定できませんでした。

もちろん社内でも問題意識はありました。 しかし開発チームと運用チームが組織的に分かれており、SLOや性能指標に関する議論をなかなか進められなかったのが現実です。 そんな中で、新たにSLOを見直す機会ができました。 それがUS向けkintoneのAWS移行プロジェクトです。

このプロジェクトのゴールは単なるAWSへの移行だけでなく、クラウドネイティブな開発・運用体勢のための仕組みづくりも含まれます。 プロジェクトのメンバーはkintone開発チームやcybozu.com運用チームから構成し、SLO、アーキテクチャ、CI/CDパイプラインなどを見直すチャンスとなりました。

AWS版kintoneのSLOとアラート (v1)

AWS版kintoneのリリースまでにチームでSLOを設定し、SLOに基づくアラートを仕掛けました。 国内のcybozu.comでは稼働率に基づくSLOを設定しており、AWS版kintoneのSLOでも稼働率の概念を導入しました。 結論から言うと、ここで紹介するSLOやアラートはうまくいきませんでした。

SLOの設定

kintoneの主要な機能(レコード操作やアプリ管理)に対して、それぞれの機能ごとにSLOを設定しました。 SLOで稼働率を計算するために、それぞれの機能でダウンタイムを定義しました。 同期処理 (APIリクエスト) のダウンタイムは、エラーレートと応答時間をもとに定義されます。

あるリクエストRに対するダウンタイムの定義は以下のとおりです。

リクエストRが、5分ウィンドウで以下のどちらかの基準を超えれば、そのウィンドウはダウンタイムとする。

  • エラー件数がN件以上かつエラーレートがM%以上
  • 応答時間のXパーセンタイルがY秒以上

たとえばレコード操作の応答時間が著しく低下して基準値を上回ると、その5分間でレコード操作機能がダウンしたとカウントされます。 ダウンタイムの基準が決まれば、1ヶ月の稼働率がわかります。 あるリクエストRの月間稼働率は「(1ヶ月 − リクエストRの月間ダウンタイム) ÷ 1ヶ月」となります。

ここから、それぞれの機能に対して以下のSLOを設定しました。

リクエストRの月間稼働率が99.9%

アラートの設定

SLOが決まると、それに基づくアラートを設定できます。 SLOに基づくアラートは、障害によってSLOを違反する前に気づくことができます。 それぞれの機能に対してSLOに基づいたアラートを設定しました。

アラートの閾値はダウンタイムの定義を元にして設定しました。 リクエストRに対して、以下の2つのアラートを設定しました。

  • 5分ウィンドウで、エラー件数がN件以上かつエラーレートがM%以上
  • 5分ウィンドウで、応答時間のXパーセンタイルがY秒以上

5分ウィンドウでどちらかの閾値を超えると、PagerDutyに通知されてチームメンバーが緊急対応します。

結果

このSLOとアラートを、およそ半年間運用してみました。 その結果は、設定したSLOやアラートはうまく機能しませんでした。 そこで気付いたことがいくつかあります。

アラートが過敏すぎる。 アラートの基準値が非常に過敏だとわかりました。 リクエスト数の少ない機能(アプリ管理機能など)では特に顕著となります。 1リクエストが遅くなっただけなのに、アラートが鳴るということがありました。 アラートは昼夜問わず鳴り、過敏過ぎるアラートはチームメンバーの健康状態にも影響します。

アラート基準の定義が曖昧になる。 SLOに対してアラートが過敏だとわかると、次にとるアクションは閾値の緩和やウィンドウ幅の拡大です。 リリース後しばらくは、アラートの調整を続けました。 それを繰り返していると、だんだんと「今の閾値はどうやって決めたんだっけ?」と、閾値の基準がわからなくなってきます。

シンプルじゃない。 稼働率に基づくSLOを設定するために、ダウンタイムという概念を導入しました。 ダウンタイムや稼働率は、実際にどれくらいサービスを利用できなくなったかのコミュニケーションには便利です。 しかしその一方で、SLOの集計が複雑になったり、アラートやエラーバジェットの計算が難しくなります。

AWS版kintoneのSLOとアラート (v2)

およそ半年間運用してみて、SLOがややこしかったりアラートが過敏過ぎるというのがわかりました。 ちょうどその頃、GoogleのThe Site Reliability Workbookの邦訳版が出版され、社内でも勉強会が開催されました。 この本はSite Reliability Engineeringの続編ですが、より実践的なSLOの運用方法や、具体的なアラートの設定が紹介されています。 そこで改めてSLOを見直し、それに基づく新たなアラート基準を設けました。

SLOの設定

以前のSLOはシンプルではなく、計算が複雑になったりアラートを仕掛けにくかったという課題がありました。 新しいSLOは、kintoneの主要な機能(レコード操作やアプリ管理)に対して、エラーレートと応答時間を別々に定義しました。 あるリクエストRに対するSLOは以下のとおりです。

  • リクエストRが、リクエスト成功率が1ヶ月で99.9%
  • リクエストRが、応答時間X秒未満のリクエストが1ヶ月間でY%未満

以前のSLOのダウンタイムの概念はありませんが、定義がシンプルになりました。 そのためSLOの実績の計算や、エラーバジェットの算出が容易になっています。

SLOダッシュボードによる可視化

以前設定したSLOでは、ダッシュボードによる可視化をせずに、月末にSLOの実績を計算するのみでした。 そのため月の途中で残りのエラーバジェットを確認できず、チームメンバーもそれを気にすることがありませんでした。 The Site Reliability WorkbookのImplementing SLOsでは、SLOが決まると実績を可視化するとよいとあります。

新しいSLOに基づいて、現在どのくらい達成できているかをダッシュボード上に可視化しました。 ダッシュボード上では過去1ヶ月間のリクエスト成功率と、応答時間が基準値を上回った割合を表示します。 このダッシュボードは開発チームだけでなくPMも見れるようにして、SLOの実績を確認したりタスクの優先度付けに利用しています。

SLOの実績をダッシュボードで可視化
SLOの実績をダッシュボードで可視化

アラートの設定

新しいSLOが可視化できれば、いよいよアラートの設定です。 以前のアラートは過敏で、たとえば月間SLOを達成できそうな一時的な遅延でもアラートが鳴りました。 新しいアラートでは、The Site Reliability WorkbookのAlerting on SLOsで紹介されている、バーンレートに基づくアラートを採用しました。 バーンレートとはエラーバジェットの消費速度を表す指標です。 バーンレートに基づくアラートは、エラーバジェットが枯渇する勢いのエラーが発生したときにアラートを鳴らすことができます。

以下の図はバーンレートとエラーバジェットの消費量の関係です。 SLOの期間内(この場合は1ヶ月)でちょうどエラーバジェットを使い切るバーンレートを1とし、1ヶ月後にエラーバジェットが0になります。 バーンレート2はその2倍の速度でエラーバジェットを消費し、15日後にエラーバジェットが0になります。

バーンレートとエラーバジェットの消費量の関係
バーンレートとエラーバジェットの消費量の関係(The Site Reliability Workbook Figure 5-4より)

具体的なアラートの評価期間と閾値も紹介されています。 まずはじめは、1時間でエラーバジェットの2%を消費、または6時間でエラーバジェットの5%を消費したときに、アラートを鳴らすとよいとありました。

エラーバジェットの消費量 ウィンドウ バーンレート
2% 1時間 14.4
5% 6時間 6

たとえばリクエストRの、1時間ウィンドウのエラーレートに関するアラートの基準は以下のとおりです。

  • リクエストRの1時間のエラーレート > (14.4 * 0.001)

1時間、6時間というウィンドウ幅はかなり長いように思えますが、仮にサービスが全断 (エラーレート100%) した場合に、検知にかかる時間は1分未満です。

結果

このSLOやアラートを運用してまだ十分な期間は経過してないので、結果はまだわかりません。 これから数ヶ月は、設定したSLOが十分か、あるいはアラートの閾値が妥当か明らかになるフェーズです。 バーンレートに基づくアラートの運用実績を積むまでは、以前の“過敏な”アラートもしばらく残す予定です。

新しいSLOにより、SLOの達成率やエラーバジェットの計算がしやすくなりました。 それだけでなく、ダッシュボードによる可視化をしたことで、チームメンバー全員がSLOを意識するようになりました。

おわりに

何度かSLOやアラートを見直して、現在の形になりました。 ここに至るまでに得られた教訓はいくつかあります。

  • 誰のためのSLOか。 SLOを決める上で、誰にとってのSLOなのか議論することが多かったです。 「ユーザービリティに直結するからSLOはこのくらい」「少し遅延しても問題ないのでこのくらい」のように、 運用面だけではなく利用者視点でのSLOを考慮しました。 サービスを運用する上でSLOは必要ですが、その背景にはサービスの利用者がいるはずです。

  • シンプルであれ。 SLOの見直しによって、複雑なSLOの定義を見直すこととなりました。 複雑なSLOやアラートは計算が難しくなるだけでなく、実際のコミュニケーションでの障害にもなりました。 口頭で人に説明できるくらいのシンプルさが大事です。

  • みんなが見える場所に可視化。 SLOに限らず可視化は大事だと言うのは昔から言われていますが、今回改めて認識しました。 容易に計算できる数値であっても、それを見える場所や導線を用意しないと、誰も意識しないのがわかりました。

  • データに基づくコミュニケーション。 SLOの可視化により、メンバー全員がSLOを意識することが増えて、定期的にサービスのパフォーマンスを気にするようにもなりました。 サービスのチューニングをするときも、勘に頼るのではなくSLOを見てユーザーへの影響をデータで判断できるようになりました。

この記事では、AWS版kintoneのSLOとアラートの取り組みについて紹介しました。 皆さんの運用しているサービスにSLOがなくコミュニケーションで悶々としていたり、職人芸でアラートの閾値を設定している方の参考になればと思います。