ストーリー
ランブックとは
ランブックの定義と目的
| 要素 | 説明 |
|---|---|
| 定義 | システム障害や運用タスクに対する標準化された対応手順書 |
| 目的 | 誰でも一貫した品質で障害対応ができるようにする |
| 対象者 | オンコールエンジニア、SREチーム、開発チーム |
| 形式 | Markdown/Wiki、コマンド付き手順、判断ツリー |
| 更新頻度 | インシデント対応後、ポストモーテム後に随時更新 |
ランブックが必要な理由
graph TD
subgraph "ランブックがない場合"
A1["障害発生"] --> A2["誰か知ってる人いない?<br/>(Slackで呼びかけ)"]
A2 --> A3["詳しい人が捕まらない<br/>(深夜・休暇中)"]
A3 --> A4["試行錯誤で復旧を試みる"]
A4 --> A5["MTTR: 60分以上"]
end
subgraph "ランブックがある場合"
B1["障害発生"] --> B2["アラートにランブックURLが含まれている"]
B2 --> B3["手順に従い診断・復旧を実行"]
B3 --> B4["MTTR: 15分以内"]
end
style A5 fill:#ffebee,stroke:#c62828
style B4 fill:#e8f5e9,stroke:#2e7d32
ランブックテンプレート
基本テンプレート
# ランブックテンプレート
runbook:
metadata:
title: "[アラート名] 対応手順"
alert_name: "AlertName"
severity: "SEV1/SEV2/SEV3"
service: "対象サービス名"
last_updated: "2026-02-14"
author: "SRE Team"
review_date: "2026-05-14" # 3ヶ月ごとにレビュー
overview:
description: "このアラートが示す状況の説明"
impact: "ユーザーへの影響"
urgency: "対応の緊急度"
diagnosis:
steps:
- order: 1
action: "ダッシュボードで現在の状況を確認"
command: "https://grafana.example.com/d/xxx"
expected: "エラー率のスパイクまたはレイテンシ増加"
- order: 2
action: "関連サービスのログを確認"
command: |
kubectl logs -l app=payment-service --tail=100 -n production
expected: "エラーメッセージから原因を特定"
decision_tree:
question: "エラーの種類は?"
options:
- condition: "DB接続エラー"
goto: "remediation_db"
- condition: "外部APIタイムアウト"
goto: "remediation_external"
- condition: "メモリ不足(OOM)"
goto: "remediation_oom"
remediation:
remediation_db:
steps:
- action: "DB接続数を確認"
command: "kubectl exec -it postgres-0 -- psql -c 'SELECT count(*) FROM pg_stat_activity;'"
- action: "接続プールの再起動"
command: "kubectl rollout restart deployment/payment-service -n production"
remediation_external:
steps:
- action: "外部APIのステータスページを確認"
command: "curl -s https://status.stripe.com/api/v2/status.json | jq '.status'"
- action: "サーキットブレーカーの状態を確認"
command: "curl http://payment-service:8080/actuator/health"
remediation_oom:
steps:
- action: "メモリ使用量の確認"
command: "kubectl top pods -n production -l app=payment-service"
- action: "Podの再起動"
command: "kubectl rollout restart deployment/payment-service -n production"
escalation:
when: "上記の手順で解決しない場合"
contact: "SREリード → エンジニアリングマネージャー"
post_resolution:
- "Slackの #incidents チャンネルに解決報告を投稿"
- "PagerDutyのインシデントをResolvedにする"
- "ポストモーテムの要否を判断(SEV1/SEV2は必須)"
決定木(Decision Tree)の設計
障害診断の決定木
graph TD
A["アラート: API応答時間がSLO超過"] --> B{"エラー率も<br/>上昇している?"}
B -->|"はい"| C{"エラーの種類は?"}
C -->|"5xx"| D{"特定エンドポイント<br/>のみ?"}
D -->|"はい"| E["依存サービスを確認"]
D -->|"いいえ"| F["アプリケーション全体の問題<br/>→ 最新デプロイを確認<br/>→ ロールバック検討"]
C -->|"5xx + DB接続エラー"| G{"DB接続エラーが<br/>含まれる?"}
G -->|"はい"| H["DB接続プール/DB負荷を確認"]
G -->|"いいえ"| I["アプリケーションログを確認"]
C -->|"429"| J["外部APIのレート制限<br/>→ バックオフ設定を確認"]
B -->|"いいえ"| K["レイテンシのみ上昇"]
K --> L{"全エンドポイント<br/>で上昇?"}
L -->|"はい"| M["インフラ(CPU/メモリ/ネットワーク)を確認"]
L -->|"いいえ"| N["スロークエリログ/トレースを確認"]
K --> O{"特定の時間帯のみ?"}
O -->|"はい"| P["トラフィックパターン確認<br/>→ スケーリング検討"]
A --> Q{"最近のデプロイ<br/>がある?"}
Q -->|"はい"| R["デプロイ前後のメトリクスを比較<br/>→ ロールバック実行"]
Q -->|"いいえ"| S["インフラ変更・外部要因を調査"]
TypeScriptでの決定木表現
interface DecisionNode {
question: string;
options: DecisionOption[];
}
interface DecisionOption {
condition: string;
action?: string; // 末端ノードの場合
command?: string; // 実行コマンド
nextNode?: DecisionNode; // 次の判断ノード
}
const apiLatencyRunbook: DecisionNode = {
question: 'エラー率も上昇しているか?',
options: [
{
condition: 'はい',
nextNode: {
question: 'エラーの種類は?',
options: [
{
condition: '5xx サーバーエラー',
nextNode: {
question: '最新デプロイから30分以内か?',
options: [
{
condition: 'はい',
action: 'ロールバックを実行',
command: 'kubectl rollout undo deployment/api-server -n production',
},
{
condition: 'いいえ',
action: 'アプリケーションログを確認し根本原因を特定',
command: 'kubectl logs -l app=api-server --tail=200 -n production | grep ERROR',
},
],
},
},
{
condition: 'DB接続エラー',
action: 'DB接続プールの状態を確認し、必要に応じて再起動',
command: 'kubectl rollout restart deployment/api-server -n production',
},
],
},
},
{
condition: 'いいえ(レイテンシのみ上昇)',
action: 'CPU/メモリ使用率とスロークエリを確認',
command: 'kubectl top pods -n production && kubectl logs -l app=api-server --tail=50 | grep "slow query"',
},
],
};
自動化ランブック
手動ランブックから自動化ランブックへ
| 段階 | 内容 | 例 |
|---|---|---|
| Level 0 | ドキュメントなし | 属人的対応 |
| Level 1 | 手動ランブック | Markdownの手順書 |
| Level 2 | 半自動ランブック | 診断コマンドのスクリプト化 |
| Level 3 | 自動ランブック | アラートトリガーで自動診断・復旧 |
| Level 4 | 自己修復 | システムが自動的に問題を検知し修復 |
自動診断スクリプトの例
// automated-runbook/diagnose-api-latency.ts
import { execSync } from 'child_process';
interface DiagnosisResult {
timestamp: Date;
checks: CheckResult[];
recommendation: string;
autoRemediationPossible: boolean;
}
interface CheckResult {
name: string;
status: 'ok' | 'warning' | 'critical';
value: string;
threshold: string;
}
async function diagnoseApiLatency(): Promise<DiagnosisResult> {
const checks: CheckResult[] = [];
// 1. Pod のリソース使用量チェック
const podMetrics = execSync(
'kubectl top pods -l app=api-server -n production --no-headers'
).toString();
const cpuUsage = parseCpuUsage(podMetrics);
checks.push({
name: 'CPU使用率',
status: cpuUsage > 80 ? 'critical' : cpuUsage > 60 ? 'warning' : 'ok',
value: `${cpuUsage}%`,
threshold: '80%',
});
// 2. DB接続数チェック
const dbConnections = execSync(
"kubectl exec postgres-0 -n production -- psql -t -c \"SELECT count(*) FROM pg_stat_activity WHERE state = 'active';\""
).toString().trim();
const connCount = parseInt(dbConnections, 10);
checks.push({
name: 'DB Active Connections',
status: connCount > 80 ? 'critical' : connCount > 50 ? 'warning' : 'ok',
value: `${connCount}`,
threshold: '80',
});
// 3. 最新デプロイの確認
const lastDeploy = execSync(
'kubectl rollout history deployment/api-server -n production --revision=0'
).toString();
const isRecentDeploy = checkRecentDeploy(lastDeploy, 30); // 30分以内
checks.push({
name: '直近デプロイ(30分以内)',
status: isRecentDeploy ? 'warning' : 'ok',
value: isRecentDeploy ? 'あり' : 'なし',
threshold: '-',
});
// 推奨アクションの決定
const criticalChecks = checks.filter(c => c.status === 'critical');
let recommendation: string;
let autoRemediationPossible: boolean;
if (isRecentDeploy && criticalChecks.length > 0) {
recommendation = 'デプロイのロールバックを推奨';
autoRemediationPossible = true;
} else if (connCount > 80) {
recommendation = 'DB接続プールの再起動を推奨';
autoRemediationPossible = true;
} else {
recommendation = '詳細なログ調査が必要';
autoRemediationPossible = false;
}
return {
timestamp: new Date(),
checks,
recommendation,
autoRemediationPossible,
};
}
ランブックの品質チェックリスト
良いランブックの条件:
| チェック項目 | 基準 |
|---|---|
| 前提知識 | システム専門家でなくても理解できるか |
| コマンドの正確性 | コピペで実行できるか(パスや変数が正確か) |
| 判断基準 | 「正常」と「異常」の判断基準が数値で示されているか |
| 分岐 | 状況に応じた分岐が網羅されているか |
| エスカレーション | 手順で解決しない場合の次のアクションが明記されているか |
| 最終更新日 | 3ヶ月以内に更新されているか |
| テスト済み | 実際のインシデントまたは訓練で検証済みか |
ランブックが陳腐化する原因と対策:
- システム構成の変更 → デプロイパイプラインにランブックレビューを組み込む
- コマンドの変更 → CI/CDでランブック内のコマンドを自動テスト
- 新しい障害パターン → ポストモーテムのアクションアイテムに「ランブック更新」を含める
まとめ
| ポイント | 内容 |
|---|---|
| ランブックの目的 | 障害対応の標準化、属人性の排除、MTTRの短縮 |
| テンプレート | 概要→診断→判断ツリー→対処→エスカレーション→事後対応 |
| 決定木 | 状況に応じた分岐で適切な対処を誘導する |
| 自動化 | 手動→半自動→全自動→自己修復の段階的進化 |
| 継続的更新 | ポストモーテム後のランブック更新を必須プロセスにする |
チェックリスト
- ランブックの構成要素と目的を説明できる
- テンプレートに従ったランブックを作成できる
- 決定木を使った障害診断フローを設計できる
- ランブック自動化の段階を理解した
- ランブックの品質維持プロセスを把握した
次のステップへ
次は「カオスエンジニアリング入門」を学びます。ランブックが実際に機能するか、意図的に障害を注入して検証する手法 — カオスエンジニアリングの基礎を学びましょう。
推定読了時間: 40分