<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Runbook on AI2CORE - AI技術ブログ</title>
    <link>https://www.ai2core.com/tags/runbook/</link>
    <description>Recent content in Runbook on AI2CORE - AI技術ブログ</description>
    <generator>Hugo -- 0.146.4</generator>
    <language>ja</language>
    <lastBuildDate>Sun, 01 Mar 2026 09:05:00 +0900</lastBuildDate>
    <atom:link href="https://www.ai2core.com/tags/runbook/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Kubernetes障害対応ランブック実践編：15分で切り分け、60分で復旧するための現場手順</title>
      <link>https://www.ai2core.com/posts/2026-03-01-kubernetes-incident-response-runbook/</link>
      <pubDate>Sun, 01 Mar 2026 09:05:00 +0900</pubDate>
      <guid>https://www.ai2core.com/posts/2026-03-01-kubernetes-incident-response-runbook/</guid>
      <description>Kubernetes本番障害を短時間で切り分け・復旧するための実践ランブック。初動、調査コマンド、復旧判断、再発防止まで具体例付きで解説。</description>
      <content:encoded><![CDATA[<h1 id="kubernetes障害対応ランブック実践編15分で切り分け60分で復旧するための現場手順">Kubernetes障害対応ランブック実践編：15分で切り分け、60分で復旧するための現場手順</h1>
<p>Kubernetes で障害が起きたとき、技術力より先に問われるのは「順序」です。順序が崩れると、正しいコマンドを打っていても復旧が遅れます。逆に、判断フレームが決まっていれば、難しい障害でも被害を最小化できます。</p>
<p>本記事では、実運用で使える障害対応ランブックを、<strong>初動 15 分・復旧 60 分</strong>を目安に具体化します。対象は EKS/GKE/AKS を含む一般的な Kubernetes 本番環境です。</p>
<h2 id="1-最初の5分人と情報の交通整理">1. 最初の5分：人と情報の交通整理</h2>
<p>まずやるべきは技術調査ではなく、交通整理です。</p>
<ul>
<li>インシデントの指揮者（IC）を1人決める</li>
<li>ログ担当、メトリクス担当、アプリ担当を分ける</li>
<li>Slack/Discord の専用チャンネルを作る</li>
<li>5分ごとの時系列ログ（タイムライン）を残す</li>
</ul>
<p>この段階で「誰が何を見ているか」が曖昧だと、同じ調査を3人で繰り返し、誰も復旧判断をしない状態になります。ICは手を動かさず、意思決定に集中するのが基本です。</p>
<h2 id="2-515分影響範囲の特定">2. 5〜15分：影響範囲の特定</h2>
<p>次に「どのユーザーに、どの機能で、何%の影響があるか」を確定します。</p>
<h3 id="2-1-まず全体の健康状態">2-1. まず全体の健康状態</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl get nodes
</span></span><span style="display:flex;"><span>kubectl get pods -A --field-selector<span style="color:#f92672">=</span>status.phase!<span style="color:#f92672">=</span>Running
</span></span><span style="display:flex;"><span>kubectl get events -A --sort-by<span style="color:#f92672">=</span>.lastTimestamp | tail -n <span style="color:#ae81ff">50</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>見るポイント:</p>
<ul>
<li>Node が <code>NotReady</code> になっていないか</li>
<li>特定 namespace だけで <code>CrashLoopBackOff</code> が増えていないか</li>
<li>直近イベントに <code>FailedScheduling</code> や <code>Back-off restarting failed container</code> がないか</li>
</ul>
<h3 id="2-2-slosliから影響を数値化">2-2. SLO/SLIから影響を数値化</h3>
<p>「遅い気がする」ではなく、以下を数値で押さえます。</p>
<ul>
<li>エラー率（5xx / total）</li>
<li>p95 / p99 レイテンシ</li>
<li>リクエスト成功率</li>
<li>影響時間（何時何分から）</li>
</ul>
<p>復旧優先順位は「売上影響」「決済影響」「ログイン影響」で並べると迷いにくいです。</p>
<h2 id="3-典型障害ごとの切り分けテンプレート">3. 典型障害ごとの切り分けテンプレート</h2>
<h3 id="3-1-podが再起動ループする">3-1. Podが再起動ループする</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl describe pod &lt;pod-name&gt; -n &lt;ns&gt;
</span></span><span style="display:flex;"><span>kubectl logs &lt;pod-name&gt; -n &lt;ns&gt; --previous
</span></span></code></pre></td></tr></table>
</div>
</div><p>判断軸:</p>
<ol>
<li><strong>アプリ起因</strong>（例: マイグレーション失敗、環境変数不足）</li>
<li><strong>リソース起因</strong>（OOMKill, CPU スロットリング）</li>
<li><strong>依存先起因</strong>（DB接続失敗、外部APIタイムアウト）</li>
</ol>
<p>OOMKill が見えたら、即座に requests/limits の見直し候補です。緊急回避として replicas を増やすより、まずメモリリークや一時的負荷スパイクの切り分けを優先します。</p>
<h3 id="3-2-podは生きているのに503が増える">3-2. Podは生きているのに503が増える</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl get endpoints -n &lt;ns&gt;
</span></span><span style="display:flex;"><span>kubectl describe svc &lt;service&gt; -n &lt;ns&gt;
</span></span><span style="display:flex;"><span>kubectl get deploy &lt;deploy&gt; -n &lt;ns&gt; -o yaml | grep -n <span style="color:#e6db74">&#34;readinessProbe\|livenessProbe&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>よくある原因:</p>
<ul>
<li>readinessProbe が厳しすぎて endpoint から外れ続ける</li>
<li>依存先劣化で app は起動しているが実処理が詰まる</li>
<li>HPA は増えているが、DB 接続プールが上限で飽和</li>
</ul>
<p>このケースでは「Pod数が多いのにエラーが減らない」ので、アプリ外（DB、キュー、外部API）を疑うのが早いです。</p>
<h3 id="3-3-特定ノードでのみ障害">3-3. 特定ノードでのみ障害</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl describe node &lt;node&gt;
</span></span><span style="display:flex;"><span>kubectl top node
</span></span><span style="display:flex;"><span>kubectl get pods -A -o wide | grep &lt;node&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>ノード隔離が必要なら、以下で新規スケジュールを止めます。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl cordon &lt;node&gt;
</span></span><span style="display:flex;"><span>kubectl drain &lt;node&gt; --ignore-daemonsets --delete-emptydir-data
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>drain</code> は影響が大きい操作なので、IC の明示承認を挟むのが安全です。</p>
<h2 id="4-復旧アクションの優先順位実務向け">4. 復旧アクションの優先順位（実務向け）</h2>
<p>障害中は「恒久対策」を始めないこと。順番は固定します。</p>
<ol>
<li><strong>被害抑制</strong>: feature flag で重い機能を止める</li>
<li><strong>暫定復旧</strong>: 直前の安定リビジョンへロールバック</li>
<li><strong>性能確保</strong>: replicas/HPA 一時調整、キュー消化速度調整</li>
<li><strong>恒久対策</strong>: 根本修正は障害収束後にPRで実施</li>
</ol>
<h3 id="4-1-ロールバックの型を決めておく">4-1. ロールバックの型を決めておく</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl rollout history deployment/&lt;deploy&gt; -n &lt;ns&gt;
</span></span><span style="display:flex;"><span>kubectl rollout undo deployment/&lt;deploy&gt; -n &lt;ns&gt; --to-revision<span style="color:#f92672">=</span>&lt;rev&gt;
</span></span><span style="display:flex;"><span>kubectl rollout status deployment/&lt;deploy&gt; -n &lt;ns&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>ポイントは「戻す判断に迷わない基準」を事前に定義しておくことです。</p>
<ul>
<li>5分間で 5xx &gt; 2% 継続</li>
<li>p95 が通常比 2倍超を 10分継続</li>
<li>ログイン/決済失敗が監視閾値超え</li>
</ul>
<p>基準がないと、誰も責任を取りたくなくて引き延ばしになります。</p>
<h2 id="5-事後対応postmortemで必ず残すべきもの">5. 事後対応（Postmortem）で必ず残すべきもの</h2>
<p>障害対応の価値は、復旧速度だけではありません。再発率を下げて初めて完了です。</p>
<p>最低限残す項目:</p>
<ul>
<li>発生時刻、検知時刻、復旧時刻</li>
<li>ユーザー影響（件数、売上影響）</li>
<li>技術的原因（直接原因 / 背景要因）</li>
<li>うまくいった対応、失敗した判断</li>
<li>再発防止のアクション（担当者・期限付き）</li>
</ul>
<h3 id="5-1-アクションを監視に落とす">5-1. アクションを「監視」に落とす</h3>
<p>「次は気をつける」は効果ゼロです。必ず機械化します。</p>
<p>例:</p>
<ul>
<li><code>CrashLoopBackOff &gt; N件</code> を5分継続で即アラート</li>
<li>DB接続待ち時間の p95 をダッシュボード化</li>
<li>リリース直後30分は自動で高感度監視モード</li>
</ul>
<h2 id="6-そのまま使える障害対応チェックリスト">6. そのまま使える障害対応チェックリスト</h2>
<h3 id="初動チェック015分">初動チェック（0〜15分）</h3>
<ul>
<li><input disabled="" type="checkbox"> IC決定、連絡チャンネル作成</li>
<li><input disabled="" type="checkbox"> 影響範囲（機能・ユーザー・売上）を数値化</li>
<li><input disabled="" type="checkbox"> Node / Pod / Event の全体確認</li>
<li><input disabled="" type="checkbox"> 直近デプロイ有無の確認</li>
</ul>
<h3 id="復旧チェック1560分">復旧チェック（15〜60分）</h3>
<ul>
<li><input disabled="" type="checkbox"> 被害抑制（feature flag / トラフィック制御）</li>
<li><input disabled="" type="checkbox"> ロールバック判断基準を満たすか確認</li>
<li><input disabled="" type="checkbox"> 復旧後 15 分の再監視（再発確認）</li>
<li><input disabled="" type="checkbox"> ユーザー向けステータス更新</li>
</ul>
<h3 id="事後チェック24時間以内">事後チェック（24時間以内）</h3>
<ul>
<li><input disabled="" type="checkbox"> Postmortem 作成</li>
<li><input disabled="" type="checkbox"> 再発防止チケット発行</li>
<li><input disabled="" type="checkbox"> 監視ルール・Runbook 更新</li>
</ul>
<h2 id="まとめ">まとめ</h2>
<p>Kubernetes 障害対応は、個人技で勝つゲームではありません。<strong>誰でも同じ順序で動ける運用設計</strong>が最も効きます。特に「初動の交通整理」「ロールバック基準の明文化」「事後の監視自動化」の3点は、復旧時間と再発率を同時に改善します。</p>
<p>次の障害が来たときに迷わないよう、今日のうちにこのランブックを自チーム用に1ページ化しておくことを強くおすすめします。</p>
<h2 id="7-障害を早く終わらせるための役割分担テンプレート">7. 障害を早く終わらせるための役割分担テンプレート</h2>
<p>実際の現場では、技術調査よりコミュニケーションで詰まることが多いです。そこで、あらかじめ役割を固定しておくと復旧が速くなります。</p>
<ul>
<li><strong>IC（Incident Commander）</strong>: 優先順位決定、Go/No-Go判断、対外連絡承認</li>
<li><strong>Ops Lead</strong>: クラスタ状態確認、ロールバック実行、インフラ変更の安全確認</li>
<li><strong>App Lead</strong>: アプリログ解析、機能フラグ切り替え、暫定パッチ判断</li>
<li><strong>Comms</strong>: 社内・顧客向けステータス更新、問い合わせ窓口統一</li>
</ul>
<p>この分担があると、「調査担当が勝手に危険操作を実施する」「連絡が多重化して混乱する」といった二次被害を防げます。</p>
<h2 id="8-よくあるアンチパターンと回避策">8. よくあるアンチパターンと回避策</h2>
<h3 id="アンチパターン1-まず再デプロイしてしまう">アンチパターン1: まず再デプロイしてしまう</h3>
<p>原因が不明なまま再デプロイすると、証拠ログを失い再現不能になります。最低限 <code>events</code> と <code>previous logs</code> を保存してから操作します。</p>
<h3 id="アンチパターン2-たぶん直ったでクローズする">アンチパターン2: 「たぶん直った」でクローズする</h3>
<p>復旧後 15 分の監視を省くと、同じ障害が波状的に再発します。復旧宣言は「指標が閾値内で安定した」ことを条件にします。</p>
<h3 id="アンチパターン3-障害後の改善が担当者依存">アンチパターン3: 障害後の改善が担当者依存</h3>
<p>改善をドキュメント化せず担当者の記憶に任せると、同じ夜間障害を繰り返します。Runbook への反映までをインシデント完了条件に含めるべきです。</p>
]]></content:encoded>
      <category>Tech</category>
      <category>Kubernetes</category>
      <category>SRE</category>
      <category>Incident Response</category>
      <category>Runbook</category>
    </item>
  </channel>
</rss>
