ストーリー
佐
佐藤CTO
SLIの設計ができた。次はSLO — Service Level Objectiveの設定だ
あなた
SLOの目標値はどう決めればいいのでしょうか。高すぎても低すぎても問題がありそうです
あ
佐
佐藤CTO
鋭い指摘だ。SLOが高すぎれば変更ができなくなり、低すぎればユーザーが離れる。ユーザーの期待値とビジネスの現実のバランスを取る技術がSLO設定の核心だ
SLOの基礎
SLO設定の原則
| 原則 | 説明 |
|---|
| ユーザーの幸福度を反映する | 内部メトリクスではなくユーザー体験を基準にする |
| 達成可能な目標を設定する | 過去のパフォーマンスデータを参考にする |
| 100%を目指さない | エラーバジェットの余地を残す |
| 段階的に引き上げる | 最初は控えめに設定し、データに基づいて調整する |
| シンプルに保つ | 1サービスあたり3〜5個のSLOに絞る |
SLO設定のアプローチ
graph TD
Title["SLO設定の2つのアプローチ"]
Title --- TopDown["トップダウン<br/><br/>ビジネス要件から<br/>逆算して目標を設定<br/><br/>「99.99%が必要」<br/>→ コストと実現性を検証する<br/><br/>推奨: SLA契約がある場合"]
Title --- BottomUp["ボトムアップ<br/><br/>実績データから<br/>現実的な目標を導出<br/><br/>「過去6ヶ月は99.95%」<br/>→ これを基準に少し高い<br/>目標を設定する<br/><br/>推奨: 既存サービスに<br/>SLOを初めて導入する場合"]
classDef title fill:#1a1a2e,stroke:#e94560,color:#fff
classDef approach fill:#0d6efd,stroke:#0a58ca,color:#fff
class Title title
class TopDown,BottomUp approach
SLO目標値の選び方
ステップ1: 過去データの分析
interface HistoricalPerformance {
period: string;
availability: number; // 可用性(%)
latencyP50: number; // レイテンシ p50(ms)
latencyP99: number; // レイテンシ p99(ms)
errorRate: number; // エラー率(%)
}
function analyzeSloCandidate(
data: HistoricalPerformance[]
): {
recommendedAvailability: number;
recommendedLatencyP99: number;
confidence: string;
} {
// 過去6ヶ月の最低値を基準にする
const minAvailability = Math.min(...data.map(d => d.availability));
const maxLatencyP99 = Math.max(...data.map(d => d.latencyP99));
// 過去実績の最低値よりやや高い目標を設定
// (最低値そのものだとSLO未達が頻発する)
const recommendedAvailability = Math.floor(minAvailability * 10) / 10;
const recommendedLatencyP99 = Math.ceil(maxLatencyP99 / 100) * 100;
return {
recommendedAvailability,
recommendedLatencyP99,
confidence: data.length >= 6 ? '高' : '低(データ不足)',
};
}
// 例: 過去6ヶ月のデータ
const historicalData: HistoricalPerformance[] = [
{ period: '2025-07', availability: 99.95, latencyP50: 45, latencyP99: 280, errorRate: 0.05 },
{ period: '2025-08', availability: 99.92, latencyP50: 50, latencyP99: 310, errorRate: 0.08 },
{ period: '2025-09', availability: 99.97, latencyP50: 42, latencyP99: 250, errorRate: 0.03 },
{ period: '2025-10', availability: 99.88, latencyP50: 55, latencyP99: 350, errorRate: 0.12 },
{ period: '2025-11', availability: 99.94, latencyP50: 48, latencyP99: 290, errorRate: 0.06 },
{ period: '2025-12', availability: 99.96, latencyP50: 44, latencyP99: 260, errorRate: 0.04 },
];
const recommendation = analyzeSloCandidate(historicalData);
// recommendedAvailability: 99.8%(最低値99.88%よりやや低めの安全目標)
// recommendedLatencyP99: 400ms(最大値350msに余裕をもたせた目標)
ステップ2: ユーザー期待との照合
| ユーザーの期待 | SLIへの反映 | SLO目標例 |
|---|
| 「ページが即座に表示される」 | レイテンシ p95 < 200ms | 95% of requests < 200ms |
| 「検索が使えなくなることはない」 | 可用性 | 99.9% |
| 「決済が途中で止まらない」 | 完了率 | 99.95% |
| 「データが消えない」 | 耐久性 | 99.999% |
ステップ3: ビジネス制約の考慮
# SLO設定のビジネス制約チェックリスト
business_constraints:
revenue_impact:
question: "SLO未達の場合、1時間あたりいくらの損失が出るか?"
analysis: "月間売上1億円 → 時間あたり約14万円"
implication: "99.99%と99.9%の差(年間約8時間)で約112万円の差"
competitive_landscape:
question: "競合のサービス品質はどの程度か?"
analysis: "主要競合は99.95%程度の可用性"
implication: "最低でも同等以上を目指す"
regulatory_requirements:
question: "法規制やコンプライアンスの要件はあるか?"
analysis: "決済はPCI DSS準拠が必要"
implication: "決済関連のSLOは特に高い目標が必要"
cost_budget:
question: "信頼性向上にかけられる予算は?"
analysis: "年間インフラ予算の20%を信頼性向上に充当可能"
implication: "99.99%は現在の予算では困難、99.95%が現実的"
Multi-Window Multi-Burn-Rate アラート設計
設計の考え方
重大度
│
Critical │ ◆ 短期間で急速消費
│ (1h window, burn rate 14.4x)
│
Warning │ ◆ 中期間で中速消費
│ (6h window, burn rate 6x)
│
Info │ ◆ 長期間で緩やか消費
│ (3d window, burn rate 3x)
│
└──────────────────────────→ 検知までの時間
5分 30分 6時間 3日
具体的なアラートルール(Prometheus)
# Prometheus Recording Rules
groups:
- name: slo_rules
interval: 30s
rules:
# SLI: 可用性(成功率)
- record: sli:availability:rate5m
expr: |
sum(rate(http_requests_total{status!~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
# エラー率(各ウィンドウ)
- record: slo:error_ratio:5m
expr: 1 - sli:availability:rate5m
- record: slo:error_ratio:30m
expr: |
1 - (
sum(rate(http_requests_total{status!~"5.."}[30m]))
/
sum(rate(http_requests_total[30m]))
)
- record: slo:error_ratio:1h
expr: |
1 - (
sum(rate(http_requests_total{status!~"5.."}[1h]))
/
sum(rate(http_requests_total[1h]))
)
- record: slo:error_ratio:6h
expr: |
1 - (
sum(rate(http_requests_total{status!~"5.."}[6h]))
/
sum(rate(http_requests_total[6h]))
)
- record: slo:error_ratio:3d
expr: |
1 - (
sum(rate(http_requests_total{status!~"5.."}[3d]))
/
sum(rate(http_requests_total[3d]))
)
---
# Prometheus Alerting Rules
groups:
- name: slo_alerts
rules:
# Critical: 2日でバジェット消尽するペース
- alert: SLO_HighBurnRate_Critical
expr: |
slo:error_ratio:1h > (14.4 * 0.001)
and
slo:error_ratio:5m > (14.4 * 0.001)
for: 2m
labels:
severity: critical
annotations:
summary: "SLO高速バーンレート検出(Critical)"
description: |
1時間エラー率: {{ $value | humanizePercentage }}
バーンレート: {{ $value | humanize }}x
このペースでは約2日でエラーバジェットが枯渇します
# Warning: 5日でバジェット消尽するペース
- alert: SLO_HighBurnRate_Warning
expr: |
slo:error_ratio:6h > (6 * 0.001)
and
slo:error_ratio:30m > (6 * 0.001)
for: 5m
labels:
severity: warning
annotations:
summary: "SLO中速バーンレート検出(Warning)"
# Info: 10日でバジェット消尽するペース
- alert: SLO_HighBurnRate_Info
expr: |
slo:error_ratio:3d > (3 * 0.001)
and
slo:error_ratio:6h > (3 * 0.001)
for: 30m
labels:
severity: info
annotations:
summary: "SLO低速バーンレート検出(Info)"
レイテンシSLOのアラート
# レイテンシSLI: 300ms以内のリクエストの割合
# SLO: 99%のリクエストが300ms以内
- record: sli:latency_good:rate5m
expr: |
sum(rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
/
sum(rate(http_request_duration_seconds_count[5m]))
# レイテンシSLOのバーンレートアラート
- alert: LatencySLO_HighBurnRate
expr: |
(1 - sli:latency_good:rate1h) > (14.4 * 0.01)
and
(1 - sli:latency_good:rate5m) > (14.4 * 0.01)
for: 2m
labels:
severity: critical
annotations:
summary: "レイテンシSLO高速バーンレート検出"
SLOドキュメント
SLOドキュメントテンプレート
# SLOドキュメント
service: "ShopNow API"
version: "1.0"
owner: "SRE Team"
last_reviewed: "2026-02-01"
next_review: "2026-05-01"
slos:
- name: "API可用性"
sli:
type: availability
description: "APIが正常なレスポンス(非5xx)を返す割合"
good_event: "HTTP status < 500"
valid_event: "全HTTPリクエスト(ヘルスチェック除外)"
target: 99.9%
window: 30days
error_budget: "43.2分/月"
alert_burn_rates:
critical: 14.4x
warning: 6x
info: 3x
- name: "API レイテンシ"
sli:
type: latency
description: "300ms以内にレスポンスを返したリクエストの割合"
good_event: "response_time < 300ms"
valid_event: "成功したHTTPリクエスト(status < 500)"
target: 99%
window: 30days
error_budget: "全リクエストの1%がSLO超過を許容"
- name: "決済成功率"
sli:
type: availability
description: "決済処理が正常に完了した割合"
good_event: "payment_status = 'completed'"
valid_event: "全決済リクエスト"
target: 99.95%
window: 30days
error_budget: "21.6分/月"
note: "外部決済APIの障害はSLI計測に含む"
consequences:
budget_exceeded:
- "全リリースを信頼性改善目的に限定"
- "CTO/VP Engineeringに週次報告"
- "根本原因分析と改善計画を2週間以内に策定"
SLO設定でよくある失敗パターン
| パターン | 問題 | 対策 |
|---|
| 最初から高すぎるSLO | エラーバジェットが即座に枯渇 | 過去実績より少し低い目標から始める |
| SLOが多すぎる | 焦点がぼやけ、管理コストが増大 | 1サービス3〜5個に絞る |
| SLOのレビューをしない | ビジネス環境の変化に追随できない | 四半期ごとにレビュー |
| 内部メトリクスをSLOにする | ユーザー体験と乖離 | ユーザージャーニーから導出 |
| SLOを罰則として使う | チームのモチベーション低下 | 改善のための道具として使う |
まとめ
| ポイント | 内容 |
|---|
| SLO設定原則 | ユーザー体験を反映、達成可能、100%を目指さない |
| 目標値の決め方 | 過去データ分析→ユーザー期待照合→ビジネス制約考慮 |
| Multi-Window Burn-Rate | 複数の時間ウィンドウとバーンレートでアラートを設計 |
| SLOドキュメント | サービスごとに3〜5個のSLOを文書化して定期レビュー |
| 段階的改善 | 最初は控えめに設定し、データに基づいて引き上げる |
チェックリスト
次のステップへ
次は「SLAの管理」を学びます。SLOとSLAの違い、SLA違反時の財務的影響、そしてSLA交渉のテクニックを深掘りしましょう。
推定読了時間: 40分