0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SLI/SLO 導入までの道のり

0
Last updated at Posted at 2026-02-16

はじめに

SRE として従事しておりながら SLI/SLO が運用されておらず、何を持ってプロダクトが健全だと言えるのかというものが定まっておらず、なんとなーく監視アラートチャンネルが荒れてなければOKだよね、というふわっとした状態だったので、見よう見まねでも導入してみようと思い立った時の記録。
同じような課題を抱えているけど何から手をつけたら良いか分からず困っている人にとって、少しでも参考になったら幸いです。

この記事は一部 AI により執筆されています

目次

概念

SLI(Service Level Indicator)

サービスレベル指標。サービスのパフォーマンスを測定するための具体的なメトリクス。

主なカテゴリ

  • 可用性:正常なHTTPレスポンス(2xx, 3xx)の割合
  • レイテンシ:リクエストの応答時間(95パーセンタイル、99パーセンタイル)
  • スループット:1秒あたりの処理リクエスト数(RPS)
  • 品質:データの完全性、機能の正確性

具体的なメトリクス例

  • 可用性:(成功リクエスト数 / 総リクエスト数) × 100
  • レスポンス時間:(閾値秒以内にレスポンスを返したリクエスト数 / 総リクエスト数) × 100
  • スループット:1秒間に処理されたリクエスト数

重要な原則:

  • 指標は多すぎず少なすぎず(多すぎるとノイズになり、少なすぎると重要な情報を見逃す)
  • ユーザーが気にする指標に焦点を当てる

SLO(Service Level Objective)

サービスレベル目標。SLIに対する具体的な数値目標。

主なSLOタイプ

  • 可用性SLO:月次可用性99.9%以上(月間43分以下のダウンタイム)
  • レイテンシSLO:95%のAPIリクエストが500ms以内に応答
  • エラー率SLO:月間エラー率0.1%以下
  • スループットSLO:ピーク時に1,000 RPS以上を維持

具体的な設定例

  • Webサイト:99%のページが2秒以内に読み込み完了
  • データベース:99.9%のクエリが100ms以内に応答
  • API:月次可用性99.95%、99パーセンタイルレスポンス時間1秒以内
  • バッチ処理:95%のジョブが予定時刻の30分以内に完了

重要な原則:

  • 過度に達成しすぎない(コストが増加する可能性)
    • 例:99.9%のSLOなら月間43分のダウンタイムが許容される
    • この「エラーバジェット」を新機能開発やリスクを取った改善に活用
    • 100%を目指すと過度な冗長化・慎重な運用でイノベーションが阻害される
  • 平均値ではなくパーセンタイル値を使用
    • 平均値の2つの問題(例:100件中95件が100ms、残り5件が5000ms ⇒ 平均 345ms)
      • 大多数の実態が歪む:95%は100msでも異常値に引っ張られて全体が遅く見える
      • 深刻な遅延が隠れる:5000msの遅延が正常値に薄められ、「平均345msなら許容範囲」と見過ごされる
    • パーセンタイル値で計測した場合:p95, p99 で計測すると、「95%のリクエストが100ms」「しかしp99は5000ms(一部で致命的な遅延が発生)」のように実態を正確に把握できる
  • 依存サービスのSLA制約:自社のSLOは依存しているサービスのSLAを上回ることはできない

エラーバジェット(Error Budget)

SLOで許容される失敗の量。(100% - SLO)

  • 可用性 SLO(時間) 99.9% → エラーバジェット 0.1%(月間43分のダウンタイムを許容)
  • 可用性 SLO(成功率) 99% → エラーバジェット 1%(月間総リクエストの内1%のエラーを許容)
  • レイテンシー SLO 95% → エラーバジェット 5%(月間総リクエストの内5%の遅延を許容)

バーンレート(Burn Rate)

エラーバジェットの消費速度。

バーンレート計算
バーンレート = 現在のエラー率 / エラーバジェット

:SLO 99%(月間エラーバジェット1%)のサービスで、1週間経過時点でエラー率が2%

バーンレートは以下の通り。

2% / 1% = 2
  • このペースだと2週間でエラーバジェット枯渇(予定の2倍の消費速度)
  • 残り3週間あるのに既に予算の半分を使用している危険な状態

この辺り少しややこしいのですが、要は常にエラー率1%であればエラーバジェットをちょうど消費し切るところを、1週間で切り取ってみると2%のエラーが発生しているため、予定の倍のエラーが発生している、ということが言いたいのです。
これが1日であっても1時間であっても考え方は同じで、エラーバジェットの何倍かを示すということが理解できれば良いかと思います。

概念についてはここまでで、続いては実際の進め方に移ります。

監視アラートチャンネルの整理

SLI/SLO を導入するということは、プロダクトの健全性を可視化し、もし SLO 違反になった場合は何らかの対応をするということになります。つまりは違反時に即座に検知する必要があります。
監視アラートチャンネルがあるとして、もしここが無法地帯になっていた場合検知するのは困難です。そもそもそんな状態では SLI/SLO を導入しても、他のアラートと同じように埋もれていつしか過去の遺産になりかねません。
そこでまずは、不要なアラートを削減していくことが大事になると考えました。まず以下のようなものを対象に、プロダクトチームと連携してアラートの見直しを図りました。

  • 閾値が過剰でアラートが発報されてもいつも無視されているもの
    → 閾値の調整
  • 夜間バッチ処理などで特定の時間帯は高負荷になることが分かっているもの
    → EventBridge Scheduler を使用し特定の時間帯のみアラートを無効化

すごく単純ですが、これだけで相当数の無用なアラートを削減することができました。
アラートが発報されたら対応が必要となるもの以外は思い切って削除してしまう、というかの有名なオライリーの『入門 監視』から得た学びを活かせた気がしました。

これで SLI/SLO を導入する最初の下準備はできたので、本題の SLI/SLO の導入を進めました。

SLI/SLO の設計

SLI/SLO は一人では設計できません。会社規模やプロダクト規模の目標値になるからです。私の場合はマネージャー陣に打ち出した上で、サーバーサイドの EM と SRE チームと共に進めることになりました。

認識合わせ

まずやったことは、なぜ導入するのか、改めて SLI/SLO とは何なのかという認識合わせです。
例えば導入のモチベーションについては以下のように考えることができます。

なぜ今SLI/SLOが必要なのか

  • サービスの安定性を数値で管理したい
  • 開発速度と品質のバランスを適切に取りたい
  • 障害対応の優先度を明確にしたい
  • チーム間の共通認識を作りたい

現在の課題

  • サービスレベルの判断が属人的・感覚的になっている
  • 「安定している」「不安定」の基準が曖昧
  • 開発を進めるべきか、品質改善を優先すべきかの判断が難しい
  • 障害の影響度評価にバラツキがある

期待される効果

  • 意思決定の高速化:数値ベースでの判断が可能
  • リソース配分の最適化:開発 vs 運用の投資判断が明確に
  • 組織全体の共通言語:エンジニアから経営層まで同じ指標で議論可能

SLI/SLO という単語自体には耳馴染みがあるものの、正確な言葉の定義や、結局どんなメリットがあるんだっけ、ということを共通認識化しておくことは非常に重要だと思います。

SLI を決める

認識合わせができたところで、おそらく一番最初に決めるのは何を対象にするか、だと思います。「我が社の SLI/SLO」という大きな単位で決めようとしても、複数プロダクト、複数 API がある場合は当然バラつきが出るため、意味のある数値にはなりません。
そのため、「最注力している」「ユーザー影響が大きい」「売上が大きい」など、何か一つ基準を決めると良いと思います。一般的には、CUJ(Critical User Journey) という 「ユーザーがサービス上で行うもっとも重要な操作の流れ」 を考えると良いとされています。例えば EC サイトであれば「トップページ → 商品ページの閲覧 → カートに入れる → 決済完了」の一連の流れなどが考えられます。
ただし今回は CUJ ベースではなくプロダクトベースで考え、最注力プロダクトを対象にしようということに決まりました。

ではこのプロダクトの何を測るかです。これがいわゆる SLI にあたります。よくあるのが可用性レイテンシーだと思いますのでこれを採用しました。(CUJ をしっかり検討された場合は、何を測れば良いのかはまた変わってくると思います)
このプロダクトはよくある ALB, ECS, RDS を用いた構成だったので、ユーザーへの影響をそのまま表しているであろう ALB を対象にしました。

可用性 SLI の定義

特に言うことはありません。以下のようになりました。

  • SLI: 成功リクエスト数 / 総リクエスト数 * 100

レイテンシー SLI の定義

可用性 SLI であれば上述のように何ともわかりやすい設定ができます。これは明確にリクエストを◯✖️で判定できるからです。
一方レイテンシーは秒数なので、単純に◯✖️では判定できません。目標値を設け、それを超えたかどうかで◯✖️判定する必要があります。
つまり、例えば以下のような設定になります。

  • SLI: レスポンスタイムが0.5秒以内のリクエスト数/総リクエスト数*100
  • SLO: 95(%)

これは実は以下と全く同じです。

  • SLI: p95のレスポンスタイム
  • SLO: 0.5秒

こちらの方がシンプルに見えます。しかし2つ目の場合、エラーバジェットが算出できないという問題があるのです。エラーバジェットは、どのくらい✖️判定のリクエストを許容するかを示す値です。あと何件の遅延が許容されるのかを示します。
これは上述した『開発を進めるべきか、品質改善を優先すべきかの判断が難しい』という課題解決に直結する大事なデータです。エラーバジェットに余裕があれば開発を優先し、エラーバジェットを下回っていたら開発を止めて回復に努めるといった判断材料になります。

もし SLI を「p95のレスポンスタイム」、SLO を「0.5秒」とした場合、「p95のレスポンスタイム」が仮に0.1秒だったとして、では一体どのくらいの遅延が許容されるのか判断できません。なのでレイテンシー SLI は 「レスポンスタイムが0.5秒以内のリクエスト数/総リクエスト数*100」 としています。

Athena で API ごとに測定する

SLI の定義はできましたが、多数の API を持つ ALB を対象にしていても、結局先の話の通り単位が大きいままです。API によってリクエスト数、エラー率、レイテンシーはまるで異なるので、同じ指標で測定してもまだ意味のある数値とは言えそうにありません。
そこで、更に重要な API だけに絞って API ごとに測定することにしました。

しかし、今度はこうなってくると単純な CloudWatch のメトリクスでは測定できません。API ごとの数値が出せないからです。そのため、 ALB のアクセスログを Athena を使用して測定することにしました。
尚、アクセスログはかなりの量になりがちなので、Partition Projection を用いてやるとクエリパフォーマンスが上がります。よろしければ以下記事を参照ください。

アクセスログの elb_status_code, target_status_code, target_processing_time フィールドを使用します。また、API(パス)のフィルターは request_url を使用します。(以下ドキュメントから request_url フィールドがなくなっている?)

その他レイテンシーについては以下のフィルターを導入しました。

  • elb_status_code, target_status_code が200~299の成功リクエストに限定したものと、エラーも全て含めたリクエストで分けて測定する

これは、例えば一部のタイムアウトエラーによってレイテンシーが増加傾向に引っ張られたり、逆に即座にエラーが返された場合はレイテンシーが減少します。そのため、エラーに左右されずアプリケーション本来のレイテンシーを分けて測定したい場合に必要だと考えたためです。
尚、これとは別にエラーも含めた全リクエストのレイテンシーも測定しています。

特に「即座にエラーが返された場合はレイテンシーが減少する」という点については、「Watermelon Effect」という、観測者側からは正常(Green)に見えているが、ユーザーから見ると異常(Red)が発生しているという状態に繋がりかねません。

どのような条件で測定したいかは各々違ってくると思うので、それは Athena のクエリで自由に表現すれば良いかと思います。

SLO を決める

SLI とフィルター条件が決まったので、具体的に目標値を決めていきます。これに関しては正解はありませんし、常々調整していくものだと思います。なので、まず現状を把握した上で妥当な値を決めてみて、あとは運用しながら調整することにしました。

ただし、可用性はそれを構成する各コンポーネントの可用性に依存します。自社サービスの SLO は、依存している全てのサービスの SLA を掛け合わせた値を上回ることはできません。
例えば AWS を使用しているとして、AWS が SLA を99.9%としているのに、自社サービスの SLO を99.99%にはできないということです。
今回の対象プロダクトは以下の構成でしたので、それぞれの SLA を掛け合わせた数値が上限値になります。

Route 53 + ALB + ECS + RDS(全てMulti-AZ構成)

それぞれの SLA は以下の通りです。

# Route 53
99.99%

# ALB
99.99%(Multi-AZ)

# ECS on Fargate
99.99%(Multi-AZ)

# RDS
99.95%(Multi-AZ)

Route53

ALB

ECS

RDS

これらを掛け合わせると以下の通りです。

99.99% * 99.99% * 99.99% * 99.95% = 99.92%

上限値がわかったところで、ざっと本サービスの過去実績も見てみたところ、可用性が恒常的に 99.9% を下回るということはなかったため、ほぼ上限値いっぱいですが SLO は「99.9%」としました。一方レイテンシーは可用性と同じように SLO の上限値を判断することはできませんが、同じく過去実績を見て「95%」で設定しました。

尚、厳密に言えば他にも使用しているサービスはありますが、まずは確実にユーザー体験に影響する主要サービスだけに限定して SLO 上限値を計算しました。仮に SLO 上限値を判断する上で考慮すべき依存サービスが漏れているとしても、それはあくまで SLO を 厳しく 設定しているということになるので、頻繁に SLO 違反になってしまう、ということがなければこのままでも問題ないと思います。

バーンレートアラーム

SLI/SLO の設計ができたところで、あとは Lambda などで日次で月間の累積値を Slack に通知したり、SLO 違反時に通知したりすれば何となく良さそうです。今回は以下のような通知をすることにしました。

20260318103554.png

ただし、当初の目的はプロダクトの健全性を測ることであり、SLO 違反かどうかの◯✖️判定をしたいわけではありません。
もちろん毎日通知されればなんとなくのトレンドは分かりますが、もし短期間で急激に悪化しても、月間の累積値で均されたら SLO 違反にはならず埋もれてしまうかもしれません。そしてある日突然 SLO 違反の通知が来てしまう、なんてことになりかねません。
つまり、ただ閾値ベースで監視していると、「緩やかな劣化」 に気付けないのです。
そこでバーンレートアラームが必要になります。この辺りは以下の記事に書かれている通りです。

バーンレートについては Google SRE の考え方を参考にしています。

ここで提唱されている閾値は以下のとおりで、これをほぼそのまま採用しました。

Severity Long window Short window Burn rate Error budget consumed
Page 1 hour 5 minutes 14.4 2%
Page 6 hours 30 minutes 6 5%
Ticket 3 days 6 hours 1 10%

表の意味としては、例えば1時間のタイムウィンドウで見た場合、バーンレートが14.4を超えた場合にアラートを発砲し、これは月間のエラーバジェットの2%を消費しているということを意味します。

例:

  • SLO: 99.9%
  • 月間リクエスト: 1,000,000件
  • エラーバジェット: 1,000,000 × 0.1% = 1,000件のエラーを許容

平均的に均した時の消費速度は以下の通りです。

  • 1,000件 / (30日×24時間) = 1.39件/時間 のエラーを許容

ではバーンレートが14.4の状態というのは、これの14.4倍のスピードでエラーが発生しているということになるため、

  • 1.39件 * 14.4 = 20.016/時間

つまり1時間あたり約20件のエラー発生となり、月間のエラーバジェット1000件のうち20件の消費なので、 Error budget consumed が2%ということになります。

尚、3日で10%というのは、単純計算すると30日で100%なのでエラーバジェットが枯渇することはないペースだが、全て消費するペースではあるため何らかの対策が必要という状態を指します。

ちなみに「エラー」という言葉に引っ張られてどうしても可用性のみで考えてしまいがちですが、レイテンシーも◯×で判定できるようにしたので、×判定のリクエスト(閾値設定した秒数を超えている)は「エラー」扱いになります。

そしてこのようなバーンレートの判定を、 Short window 列のサイクルで回しています。1時間のタイムウィンドウにおけるバーンレートは5分ごとに、6時間のバーンレートは30分ごと、3日間のバーンレートは6時間ごと、という感じです。
こうすることで、「一気にエラーが跳ねることはないが徐々に増えている」という、いわゆる 「緩やかな劣化」 にも気づけるようになりました。

あとは、以下のようなダッシュボードを作成して週1回の定例会で各 API の健全性を評価する場を設けることにしました。 ここに載せたものは全体が見られるシートですが、これとは別で複数のシートがあるように、個別の指標についてもそれぞれ用意しています。
尚、ダッシュボードは AWS の Quick Sight と S3 Tables を使用して構築しました。

20260318103547.png

ものすごく小さくなってしまいますが全体構成図だけこちらに置いておきます。

sli_slo_monitoring.drawio.png

まとめ

以上が SLI/SLO 導入までの道のりでした。手探り状態から他社様の事例などを色々と参考にさせていただきながら始まったプロジェクトですが、日々目の前のタスクにばかり目が向きがちなところを、プロダクトに向き合って議論するのはとても良い機会でした。
まだ運用を始めたばかりのため、色々と見直すべきポイントは多分出てくるのだと思いますが、これから徐々にアップデートしていこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?