「SLO サービスレベル目標」読書メモ②
こんにちは、Azukaritai の小松です。先日の記事の続きで、O'reilly の「SLO サービスレベル目標」をAzukaritaiのSREチームで読んで学び、理解したことを読書メモとしてまとめていきます。
この記事では、第1部のうち3章から5章にて書かれていることを扱います。ちなみに、第1部の前半の1章と2章では、信頼性スタックという考え方と、信頼性という概念自体についての掘り下げが扱われていました。3章〜5章にかけては、信頼性スタックを構成する要素である、SLI、SLO、エラーバジェットを下から順番にそれぞれ掘り下げて説明されている構成になっていました。
3章 「意味のあるサービスレベル指標の開発」
サービスレベル指標、つまりSLIについて詳しく説明されている章になります。SLIは1章に登場する信頼性スタックの一番下のレイヤーを構成する要素になります。冒頭でまず、SLIが的外れであれば、その上に構築されるSLOやエラーバジェットも、期待通り機能しなくなるという点において、SLIが非常に重要であるということが改めて説かれています。
1章、2章で強調されているように、本書で触れられているSLI, SLO, エラーバジェットは「信頼性スタック」であり、その中心には「信頼性」という概念があります。信頼性とは、「ユーザー必要とする動作をシステムが実行すること」であると記述されており、SLIはつまり「ユーザーが必要とする動作をシステムがどれだけ実行できているか」を表現する指標であることが期待されます。
ただ、そういう理想的なSLIを開発するのはそう簡単なことではありません。ユーザーがシステムに期待する動作と一言で言っても、そこに様々なものが含まれることがあり、それを全部指標化すればいいというものでもありません。SLIおよび、SLO、エラーバジェットは、様々な場面で立場の違う関係者の間でのコミュニケーションや意思決定のためのツールとして期待されるものであり、そこにはシンプルさというものも重要になってきます。
また、SLIを開発する上で、それが「良い」か「悪い」かの二者択一の状態を表すように記述されることが重要であるということが説明されています。本文中の例にあるような、リクエスト・レスポンスサービスの例で、レイテンシーをSLIの対象にするとしても、「400ミリ秒以内にレスポンスされる」などと、閾値を設定して、ユーザーの期待と合致する水準を明確にしています。これは、SLIとして、個別のイベントごと、あるいは単位時間あたりの集計値として、良い状態であったか、悪い状態であったかのブール値を取ることで、上位のSLOを設定する時に、特定期間の中で、どれだけの割合(パーセント)でユーザーの期待を満たす状態であったか、という所に関心を集中できるようにするためにまず必要なことであり、また、「ユーザーの必要とするレイテンシーなどの水準」を具体的に目標として設定することにも意味があります。
4章「適切なサービスレベル目標の選択」
SLIによって、「サービスがユーザーの期待と合致する動作をしているかどうか」を評価する基準が明確になり、個別のサービス利用のイベントであったり特定の瞬間に対して「期待を満たしている」状態と「期待を満たしていない」状態とを分類できるようになりました。ただ、必ずしも、常に「期待を満たしている」状態を維持しなければならないかというとそうでもないということに触れられています。サービスの性質によって変わってきますが、例えばウェブサイトにおいて、多少エラーが発生してページが正常に表示されなかったり、ページが表示されるのに時間がかかるようなことがあったとしても、リロードして再度表示されればユーザーは目的を達成することができ、そのことでそのサービスに対してクレームを出したり、利用するのを辞めたりするようなことはありません。SLOはSLIで表される値がどの程度の水準を達成していればユーザーが満足しているか、というところから検討され、設定される目標値であるとされています。
ユーザーの満足といっても、実際には色々なユーザーがいて、それぞれのサービスへの期待も少しずつ違ったりするわけですし、満足した状態と満足していな状態も、1か0かということではなかったりするわけですが、ここではある種の抽象化を行い、SLIがこの水準を満たしていれば、ユーザーの大部分は概ね満足している、というような目標値を定めようとしましょう、ということと理解をしました。本の中では、満足している状態というより、逆に「不満を抱いていない状態」と考えた方がわかりやすいかもしれないとあります。信頼性が低いと、ユーザーがサービスを使わなくなり、他の競合に乗り換えてしまうなどの、好ましくない状況が発生するという想定のもとに、SLOを設定するというアイデアは成り立っているようで、SLOとして適切な目標値を選択する際には、ユーザーはどの程度なら使うのをやめたりせずに使い続けてくれるか、というような視点を持ち込んだりすることもあるようです。
信頼性は、高ければ高いほど良いのでは、と一般的には考えられがちですが、この章の中では信頼性が高すぎることの問題について言及されています。信頼性が高すぎることで失われる機会として、「実験を行う機会」、「カオスエンジニアリングを実施する機会」、「それまでより短時間で機能をリリースする機会」などが具体的に挙げられていつつ、必要以上に高い信頼性を達成することで、ユーザーの期待値が上がってしまい、その後は本来必要とする以上の信頼性が求められるようになり、前述のような機会を得られない状態が続いてしまうという問題についても言及されていました。
SLOは、この、低すぎても問題であり、高すぎても問題である信頼性について、一番メリットの大きくなる水準と想定される値を目標値として定めて、それを目指せるようにするというアイデアと言えそうです。
理屈としてはそうなのですが、その最適なバランスとなるSLOを選択するというのは、実際には非常に難しいものであるということも、この本の中で述べられていました。実際にどういう水準の信頼性であれば十分なのか、ユーザーがクレームを出したり、サービスを使うのをやめていかないのか、というのは過去の出来事からある程度推測できることもあるかもしれませんが、実際にはやってみないとわからないという部分もあります。なので、この本の中でも強調されていることとして、SLOはユーザーとの間の拘束力を持った約束(SLA)ではないということであり、変更が可能であるという点です。一旦暫定値で初めて、その目標値が適切でないことが確認できたら、その時に調整していくことができ、それが賢いやり方になります。
この章では、他にも、統計の話や、その応用でのパーセンタイルの考え方を使ったSLOの設定など、色々と有用なトピックが丁寧に解説されていましたが、割愛します。
5章「エラーバジェットの使い方」
エラーバジェットは信頼性スタックの最上位に位置するものであり、つまりSLI, SLOを前提として導入される考え方になります。エラーバジェットは端的に言えば、SLOを達成している範囲であとどれだけ、信頼性のない状態になっても良いかの残量なのですが、この章では、主にこのエラーバジェットの考え方がどのように活用できるかについて詳細な説明がありました。一番代表的な話としては、「エラーバジェットが残っている(SLOを達成できている)場合には、機能の開発・リリースを進め、エラーバジェットが枯渇している(SLOを達成できていない)場合には、機能の開発・リリースをとめ信頼性を高めるための活動を行う」という、行動の制御の意思決定に活用するというものです。あるいは単に、開発を進めるか、機能リリースを止めるか、という二者択一ではなく、複数ある開発項目の選択肢の中で、何に焦点を当てるかを考える際に、エラーバジェットの消費状況を踏まえて判断する、という、もう少しグラデーションのある意思決定への反映に使われるケースもあったりするようです。その他にも、「リスク要因の調査」、「実験とカオスエンジニアリング」、「負荷テスト及びストレステスト」、「ブラックホール演習」などといった形で、バジェットを意図的に消費しながら、様々な貴重な洞察を得たりするためのアプローチが色々と紹介されています。このように、あえて信頼性を落としながら、将来のプロダクトの改善につながる情報を得るというのは、エラーバジェットの活用としてはかなり高度な部類であると、本の中でも説明されていました。
それ以外にも、エラーバジェットについての具体的な計算方法であったり、エラーバジェットの考え方をソフトウェアシステム以外に応用する考え方であったり、こちらもかなり丁寧に記述されていました。また、エラーバジェットポリシーと呼ばれる、エラーバジェットベースで、特定の状況に、行動を制限するなどの規定を事前に設定するプラクティスについても詳述されていましたが、この記事では長くなってしまうので割愛します。
まとめ
3章〜5章は、信頼性スタックの構成要素のSLI、SLO、エラーバジェットについてそれぞれ深堀して、詳細な記述、説明、関連するプラクティスの説明が丁寧に行われている印象のパートでした。SRE本やオブザーバビリティ本で、SLI、SLO、エラーバジェットという概念は登場していて、概念としてはわかっていつつ、具体的な部分であったり、実際にどのように設定して活用していくか、というところについては、ぼんやりした理解だったところから、本書のこの部分を読んで、かなり理解が深まった感触がありました。
引き続き、以降の章についても読んでまとめていこうと思います。