Repro における組織横断した SLO 運用のはじまり

Development Division / Platform Team の村上です。

Repro では、数年前から組織横断した SLO を運用する取り組みを進めてきました。
ここでいう「組織横断」とは、特定のチームや自部署内に閉じて運用するのではなく、部署を跨いだ共通の信頼性指標として SLO が運用できていることを指しています1
あるユーザー体験において、SLO やエラーバジェットポリシーの同意が部署間で得られている状態、とも言えます。

SLO 運用に関連する部署は、私が所属する Development(以降 Dev) と Customer Success(以降 CS) になります。
CS は、カスタマーサポートやグロースマーケターとしてお客様と直接やり取りをする部署であり、Repro のシステムで障害や何か問題が発生したときは CS 部署と連携して対応しています。

2023 年から SLO の活動を始め、ここ最近、SLO 運用のための仕組みが整いそれなりに浸透してきたなと感じます。課題はまだまだあるものの、SLO 推進活動もひと段落してきたので、Platform Team で行ってきたこれまでの取り組みを改めて振り返ってみます。

1 記事ですべてを語ると長くなりそうなので、今回の記事では Repro で初めて組織レベルの SLO を導入したときの話を紹介します。

SLO を始めたきっかけ

Repro は、Kafka を基盤としたイベント駆動アーキテクチャで構成されていて、Kafka からレコードを取得して処理を行うストリームアプリケーションを運用しています。
ストリームアプリケーションでは、処理スループットを上回る速度で大量のレコードが Kafka に積まれると、あるレコードの処理が完了するまで通常よりも大きな遅延が発生します。

私達が運用するストリームアプリケーションの 1 つに、大量のレコードが一気に積まれて、レコードを処理しきるまでそれなりの時間がかかっているものがありました。
このアプリケーションは、各ノードのローカルディスクにストリーム処理で使うパーティショニングされたデータを格納していて、ノード数が増減するとデータの再配置が行われて処理が一時停止するので、負荷に応じて一時的にスケールアウトさせることが難しいです。

これが運用上の負荷となっていて、具体的には次のような問題がありました。

  • 未処理レコード数を監視するモニターからアラートを受け取ったときに、スループットを超えるほどの大量のレコードが積まれたのか、何らかの障害が発生したのかの切り分けを毎回行っている
  • どのくらいの遅延が発生したら CS 部署に報告すべきなのか、の共通認識が揃っていない
  • 遅延緩和のための対応をどの優先度でどこまで工数かけられるかが不明確
  • 一定の処理遅延を伴うメンテナンスを実施するときのポリシーが定まっていない(深夜帯にやるべきなのか、など)

これらの問題は「遅延の大きさや発生頻度がどの程度であればユーザー体験に支障がないのか」という問いに対して、部署を跨いで共通認識として持つことができれば解消につながると考え、組織横断な SLO 導入に踏み出しました。

Repro における組織横断的な SLO 運用は、ある 1 つのコンポーネントが抱える運用上の問題を解決することからはじまりました。

SLO 導入の計画

SLO を導入するにあたり、以下の条件を完了の定義としました。

  • SLO を知らない人が、SLO に関連する用語や目的、運用方法などの前提知識を理解できる資料が作成されている
  • SLO 策定のためのプロセスが定まっている
  • CS 部署から SLO を運用することの納得感を得られていて、SLO を合意におけるステークホルダーを選出してもらっている
  • 今回作成予定の SLO が運用ができている(モニタリングやダッシュボード作成含む)

「最初の SLO を作り上げる」「次の SLO を作りやすくする」という点にフォーカスした内容です。
SLO の文化を広げる活動はスコープ外としてます。

SLO 説明資料と策定プロセスの整備

SLO の説明資料を作成する上で、まずは「サイトリライアビリティワークブック」の SLO に関する章(2章から5章まで)を読んでインプットしました2

インプットした内容を元に、社内向けの SLO 説明資料を作成しました。
資料では以下のような内容を、Repro の組織体制や自社プロダクトの事例などを交えながら仕上げています。

  • SLO はサービスの信頼性における目標レベルを定量的に定めたもの
  • サービスの信頼性とはサービスが期待通りに動作し、問題なく利用できている度合いであり、「ユーザーの満足度」と言い換えることもできる
  • SLI はサービスの信頼性を計測するための指標で、パーセンテージが使われる
    • e.g. API の成功率 = API でエラーにならなかったリクエスト数 / API の総リクエスト数
  • エラーバジェットは損失できる信頼性の許容度
    • e.g. API の成功率 99% をSLOとする場合、100 リクエスト中 1 回エラーになることを許容できる
  • エラーバジェットポリシーはエラーバジェットが一定量減ったときや尽きたときに取るべきアクションを定めたルール
    • e.g. API の成功率が 99% を下回ったらロードマップを変更してエラー率を下げる開発をする
  • SLO は信頼性維持のための開発と新規開発の投資バランスの意思決定をサポートする
  • SLO の運用にはステークホルダー全員の同意が必要になる
  • サービスの信頼性を定義するのは難しい営みであり、SLO は継続的な改善が大切である

そして、SLO の策定プロセスについては、ざっくり以下のような流れで定めました。

  1. SLO 定義のドキュメントを作成する
  2. SLO を満たすことに責任を追うメンバー(大抵は自チーム内)から承認を得る
  3. ステークホルダーから承認を得る
  4. SLO のモニター実装とダッシュボード反映する
  5. 次回の SLO レビューをタスク化する

これらの内容を、同じ Platform Team の人達にレビューしてもらい、チーム内に SLO のナレッジも蓄積していきました。

CS 部署に向けた説明会の実施

CS 部署のマネージャー陣に向けて SLO 説明会を実施しました。

作成した説明資料を元に SLO の概念や目的、協力いただきたい内容などを話しましたが、結果として、SLO を運用することのメリットや意義を十分に伝えきれず、時間内に納得感を得てもらうまでは至らなかったです。

そのため、別で質疑応答の場を設けるつもりではありましたが、説明会に参加いただいた CS の方が部署内で SLO 運用する意義や懸念点の解消をしていただき、さらに CS 側のステークホルダー選出まで取り決めてくれたので、追加で場をつくる必要はなくスムーズに進めることができました。

以下、CS 部署でどのような話をしたのかをヒアリングした内容です。

  • CS 側で得られる利益のイメージに乖離があり、運用上の不安を解消できてなかった
    • SLO を決めることで、調査をしなくなることがあるのであれば、それが問題につながることがあるのでは?
    • エラーバジェットは余裕があるが、特定のお客様にだけ不具合が集中しているケースはどのように対応するのか?
  • 目標値とそれに違反したときのアクションポリシーを一緒に決めていくことで、お互いの期待値が揃った機能と運用になる、という説明で理解をしてもらえた

これはとてもありがたいフィードバックでもありました。
エラーバジェットの仕組みでは拾いきれないユーザー体験の損失に対しても、ドキュメント上に明記し、ポリシーを定めようと考えるようになりました。

SLO の策定

次は対象とするユーザー体験について SLO のドキュメントを作成し、チームとステークホルダーから承認をもらうフェーズです。

ドキュメントは次のフォーマットで書いています。フォーマットを決めるにあたって、サイトリライアビリティワークブックの内容を大いに参考にしました。

# サービスの概要

<!--
SLO ドキュメントの読者に前提知識を伝えるためのサービス概要。

次の観点で記載するのが良いだろう。
- 何のサービスに対する SLO なのか
- どのようなユーザー体験になるのか
- ステークホルダーはサービス概要を見て、SLO をレビューできるのか
-->

# SLO

## ステータス

<!--
次のステータスを管理する。

- SLO の作者
- SLO の承認者(ステークホルダー)
    - SLO のレビューを行い、承認したら記載
- 最終承認日と次回レビュー予定日
    - ステークホルダー全員の承認を獲得したら、最終承認日に日付を記載
    - その後、次回レビュー予定日を入れる。レビューの間隔は SLO によって異なる。特にこだわりがなかれば四半期ごとで良いだろう。

作成者、承認者の部署異動や退職などにより、SLO の問い合わせ先が分からなくなることを避けるため、所属も記載しておくとよい。
-->

## SLI/SLO

<!--
対象とする SLI/SLO の内容とその詳細。
複数の SLO を定義する場合はそれぞれ載せる。

SLI は特にシステム用語が使われがちなので、その場合は補足することを忘れずに。
その SLO がユーザー体験にどのように影響するのか、を把握できるように詳細を記載すること。
-->

### 詳細説明

## 数値の背景となる論拠

<!--
SLO の値や評価期間などの数値の背景となる論拠。
それらが経験則によるものなのか、今までの観測データから導出されたものなのか、も合わせて記載する。
SLO における数値が強固なエビデンスに基づくものではなく、暫定的に決定した場合も、その旨を書いておくことで、
将来の読者がその事実を理解し適切な判断を下せるようにする。
-->

## エラーバジェット

<!--
エラーバジェットがどう計算されて消費されるのかの詳細。

例えば、エラーバジェットが 1% だった場合、
過去 30 日間で API サーバに 10000 回のリクエストがあったとすれば、10000 の 1% である 100 回まではエラーリクエストを許容する、といった具合に、具体的な例を上げて説明すると良い。
-->

## SLOを満たす責務を持つ運用担当者向け

<!--
ステークホルダーは知っていなくても問題ないが、SLO を満たす責務を持つ運用担当者には把握しておいて欲しい内容。
例えば、SLI を実装する Datadog の query や、必要なメトリクスを取るためのシステム改修など。
-->

# エラーバジェットポリシー

## ステータス

<!--
エラーバジェットポリシーのステータス管理。
項目や運用は SLO のステータスと同じ。
-->

## SLO違反のポリシー

<!--
エラーバジェットが 100% 消費したときの信頼性回復のための具体的なアクションを記載する。
信頼性回復のための作業をしなければいけないケースと、しなくてもよいケースをそれぞれ記載すると良い。
例えば、AWS がアナウンスするレベルの障害起因で枯渇した場合などは、信頼性回復のための作業を行う必要はない、など。

また、エラーバジェットが半分消費されたタイミングなど、100% の消費ではないにせよ枯渇しないためのアクションを近い内に取ったほうが良い場合は、それも合わせて定義しておくと良い。
-->

## 障害のポリシー

<!--
エラーバジェットの枯渇や消費量では気づきにくいが明らかに問題が発生しているケースに対して適切に検知してアクションが取れるよう、障害時のポリシーも定義しておく。
例えば、 1 時間でエラーバジェットの 20% 以上を消費した場合はポストモーテムを行う、など。
監視方法はエラーバジェットの消費量を見るのではなく、エラーバジェットの消費ペース(Burn rate alert) や別のモニターを用意することになる。
-->

このときのテーマが、ストリームアプリケーションの処理遅延によるユーザー体験への影響で、前提の説明がそれなりに必要なとっつきにくい部分だったので「サービス概要」はそこそこのボリュームになりました。

現実的な SLO でないとレビューに出しても意味がないので、ドキュメントを書いているときに想定した SLI による現時点での実績値を確認しました。
Datadog では SLO をモニタリングする機能 が提供されていて、最終的には Datadog の SLO を作成することになります。実績値の確認では、この Datadog の SLO を仮で作って値を確認していました。SLI で使用するメトリクスは、すでに取得しているものを使ったので追加実装はスキップできました。

このときは使用したメトリクスの都合もあり Datadog の Monitor-based SLO を使ったんですが、この SLO type は時間ベースであり「モニターがアラート状態になっている時間がウィンドウに対してどのくらいの割合か」を評価します。
そのため、処理の遅延時間が閾値を越えていることは捕捉できますが、遅延の度合いはモニターしないので、許容出来ないレベルの遅延時間が発生したのであれば、エラーバジェットに関係なく優先的に対応するよう障害ポリシーに記載しています。

ドキュメントを埋めた後は「SLO を満たすことに責任を追うメンバー」へのレビューの後に「ステークホルダー」からのレビューを受けて、承認をもらいました。
最初の SLO というのもあり、ステークホルダーへの説明は同期的に実行したので、承認まではスムーズだったと記憶しています。

SLO のモニタリングとダッシュボード

最後に Datadog の SLO を作成してモニタリングの環境を整えて、ダッシュボードを作成して完了です。

Datadog の SLO は Terraform で管理しています。1 つの SLO を作成するときに必要となるリソースを束ね、共通のタグやアラートメッセージフォーマットを定める Module も用意しました。
SLO ドキュメントの URL をアラートメッセージに表示することで、エラーバジェットやバーンレートのアラートを受け取ったとき、ドキュメントに記載されたエラーバジェットのアクションをすぐに参照できるようにしています。

おわりに

組織横断した SLO を初めて導入したときの話を紹介しました。

今回の SLO を策定した後、既存のアラート見直したり、遅延緩和の対応の優先度を調整したりと、運用負荷を下げて他の業務にリソースを投資する意思決定ができるようになりました。

解決したかった問題は必ずしも SLO 導入を前提としなくてもよいものでしたが、「ユーザー体験にフォーカスする」「信頼性に対する期待値を合わせる」「違反時に強制実行されるアクションを定義する」といった SLO の要素は、既存機能やこれから新らに作られる機能で非常に有用だと感じたため、問題の解消をすると同時に SLO の土台作りにも踏み出しました。

この後の活動としては、主要機能に対して SLO を作成する取り組みをしてきました。そちらに関してはまた別の記事で紹介します。


  1. 特定のチーム内で運用している SLO はすでにいくつか存在していました。
  2. 当時はまだ「SLO サービスレベル目標」は出版されていませんでした