ストーリー
佐
佐藤CTO
SREの基礎を学んだところで、次はSLI — Service Level Indicatorの設計だ
あなた
SLOを設定するにはまずSLIが必要ですよね。何を測定するかを決めないと、目標も立てられない
あ
佐
佐藤CTO
その通り。そして何を測定するかが最も重要な判断だ。間違ったSLIを選ぶと、SLOは形骸化する。ユーザー体験を正確に反映するSLIを設計する力を、ここで身につけよう
SLIの基礎
SLIとは
SLI(Service Level Indicator)は、サービスの品質レベルを定量的に測定する指標です。
| 概念 | 定義 | 例 |
|---|
| SLI | サービス品質の定量的な測定値 | リクエスト成功率、レイテンシp99 |
| SLO | SLIに対する目標値 | 成功率 99.9%、p99 < 500ms |
| SLA | SLO違反時のビジネス上の取り決め | SLO未達時に翌月10%割引 |
良いSLIの条件
| 条件 | 説明 | 良い例 | 悪い例 |
|---|
| ユーザー体験を反映 | ユーザーの満足度と相関する | レスポンスタイム | CPU使用率 |
| 測定可能 | 客観的に計測できる | HTTPステータスコード | 「体感の速さ」 |
| 比率で表現 | 0〜100%のスケールで表現できる | 成功率、良好なレイテンシの割合 | エラー数(絶対値) |
| 集約可能 | 時間ウィンドウで集約できる | 30日間の成功率 | 特定時点のスナップショット |
4つのゴールデンシグナル
Googleが提唱する、サービス監視の4つの基本シグナルです。
概要
graph TD
Title["4つのゴールデンシグナル"]
Title --> Latency["レイテンシ (Latency)<br/>リクエストの処理にかかる時間<br/>成功リクエストと失敗リクエストを分離"]
Title --> Traffic["トラフィック (Traffic)<br/>システムへの需要の量<br/>HTTP RPS、同時接続数など"]
Title --> Errors["エラー (Errors)<br/>失敗したリクエストの割合<br/>明示的(5xx)、暗黙的(遅いレスポンス)"]
Title --> Saturation["飽和度 (Saturation)<br/>リソースの利用率<br/>CPU、メモリ、ディスク、接続数"]
classDef title fill:#1a1a2e,stroke:#e94560,color:#fff
classDef signal fill:#0d6efd,stroke:#0a58ca,color:#fff
class Title title
class Latency,Traffic,Errors,Saturation signal
PromQLでの4ゴールデンシグナル
# 1. レイテンシ: リクエストの処理時間(p50, p90, p99)
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{job="api-server"}[5m]))
by (le)
)
# 2. トラフィック: リクエスト/秒
sum(rate(http_requests_total{job="api-server"}[5m]))
# 3. エラー率: 5xxレスポンスの割合
sum(rate(http_requests_total{job="api-server", status=~"5.."}[5m]))
/
sum(rate(http_requests_total{job="api-server"}[5m]))
# 4. 飽和度: CPU使用率
1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m]))
SLIの種類
サービスタイプ別SLI
| サービスタイプ | 主要SLI | 測定方法 |
|---|
| リクエスト駆動型(API) | 可用性、レイテンシ、スループット | ロードバランサーのアクセスログ |
| パイプライン型(バッチ) | 鮮度、正確性、完了率 | ジョブの完了時間・成功率 |
| ストレージ型(DB) | 耐久性、スループット、レイテンシ | ディスクI/O、クエリレスポンス |
| ストリーミング型(Kafka) | スループット、遅延、データロス率 | Consumer Lag、データ整合性 |
リクエスト駆動型のSLI詳細
// SLIの定義と計測
interface SliDefinition {
name: string;
description: string;
goodEventFilter: string; // 「良い」イベントの条件
totalEventFilter: string; // 全イベントの条件
unit: string;
}
const apiSLIs: SliDefinition[] = [
{
name: 'availability',
description: '正常にレスポンスを返したリクエストの割合',
goodEventFilter: 'status != 5xx',
totalEventFilter: 'all requests',
unit: '%',
},
{
name: 'latency',
description: '閾値以内にレスポンスを返したリクエストの割合',
goodEventFilter: 'response_time < 300ms',
totalEventFilter: 'successful requests (status != 5xx)',
unit: '%',
},
{
name: 'correctness',
description: '正しいレスポンスを返したリクエストの割合',
goodEventFilter: 'response matches expected schema AND data is correct',
totalEventFilter: 'successful requests',
unit: '%',
},
{
name: 'freshness',
description: '最新データを使ってレスポンスを返した割合',
goodEventFilter: 'data_age < 60s',
totalEventFilter: 'successful requests',
unit: '%',
},
];
SLIの測定ポイント
測定ポイント
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
クライアント側 ロードバランサー サーバー側
(RUM/合成監視) (アクセスログ) (アプリログ)
最もユーザー 推奨: 内部の
に近い測定 多くのケースで 詳細情報は
↓ 最適なバランス 得られるが
ネットワーク ↓ ↓
遅延も含む 全リクエストを クライアント
網羅的に記録 体験と乖離
しやすい
| 測定ポイント | メリット | デメリット | 推奨ケース |
|---|
| クライアント側 | 最もユーザー体験に近い | データ収集が困難、ノイズが多い | Webフロントエンド |
| ロードバランサー | 網羅的、信頼性が高い | ネットワーク遅延を含まない | API、マイクロサービス |
| サーバー側 | 詳細な内部情報が得られる | クライアント体験と乖離しうる | 内部サービス |
SLI設計のベストプラクティス
1. ユーザージャーニーからSLIを導出する
# ユーザージャーニーベースのSLI設計
user_journey: "商品を検索して購入する"
critical_user_journeys:
- name: "商品検索"
slis:
- type: availability
good_event: "検索APIが200を返す"
measurement_point: "API Gateway"
- type: latency
good_event: "検索結果が300ms以内に返る"
threshold: 300ms
percentile: p99
- name: "商品詳細表示"
slis:
- type: availability
good_event: "詳細APIが200を返す"
- type: correctness
good_event: "価格と在庫が最新(60秒以内)"
- name: "決済処理"
slis:
- type: availability
good_event: "決済が正常に完了する"
- type: latency
good_event: "決済処理が5秒以内に完了する"
threshold: 5000ms
2. SLI仕様書テンプレート
interface SliSpecification {
sliName: string;
sliType: 'availability' | 'latency' | 'correctness' | 'freshness' | 'throughput';
description: string;
goodEvent: string;
validEvent: string;
measurementPoint: string;
dataSource: string;
formula: string;
excludes: string[]; // 除外条件
implementation: string; // PromQL等の実装
}
const searchAvailabilitySli: SliSpecification = {
sliName: 'search_availability',
sliType: 'availability',
description: '検索APIが正常にレスポンスを返した割合',
goodEvent: 'HTTPステータスコードが5xx以外のレスポンス',
validEvent: '検索API (/api/v1/search) へのすべてのリクエスト',
measurementPoint: 'API Gateway (ALB)',
dataSource: 'ALB Access Logs / Prometheus metrics',
formula: 'count(good_events) / count(valid_events) × 100%',
excludes: [
'ヘルスチェックリクエスト (/health)',
'ロードテスト用リクエスト (X-Load-Test header)',
'メンテナンスウィンドウ中のリクエスト',
],
implementation: `
sum(rate(http_requests_total{handler="/api/v1/search", status!~"5.."}[30d]))
/
sum(rate(http_requests_total{handler="/api/v1/search"}[30d]))
`,
};
SLI設計でよくある間違い
| 間違い | 問題 | 正しいアプローチ |
|---|
| CPU使用率をSLIにする | ユーザー体験と直接相関しない | レイテンシやエラー率を使う |
| 平均値だけを見る | 外れ値が隠れる | p50/p90/p99を使う |
| 全リクエストを同等に扱う | 重要度の違いを無視 | ユーザージャーニー別に分ける |
| サーバー側だけで測定 | クライアント体験と乖離 | ロードバランサーでも測定 |
| ヘルスチェックを含める | SLIが歪む | ヘルスチェックは除外 |
| 障害中のリクエストを除外 | 障害を隠してしまう | 障害中のリクエストこそ含める |
まとめ
| ポイント | 内容 |
|---|
| SLIの定義 | サービス品質を定量的に測定する指標 |
| 4ゴールデンシグナル | レイテンシ、トラフィック、エラー、飽和度 |
| SLIの種類 | サービスタイプに応じて可用性、レイテンシ、正確性、鮮度等 |
| 測定ポイント | ロードバランサーでの測定が多くのケースで最適 |
| 設計手法 | ユーザージャーニーからSLIを導出する |
チェックリスト
次のステップへ
次は「SLOの設定」を学びます。設計したSLIに対して、どのように適切な目標値を設定するか、Multi-Window Multi-Burn-Rateアラートの詳細設計を深掘りしましょう。
推定読了時間: 40分