Skip to content

7. リスクと状況

7.1 リスク

#リスク緩和策
R1コントローラーのクラッシュ / リーダー喪失replicas=2 + リーダー選出; backstop 保持; 失敗アラート
R2ウィンドウがすべての候補に不足§3.2 スループットチェックが警告; 候補持続でアラート
R3surge キャパシティ不可(AZ 不足 / limits)ヘッドルーム事前チェック(§5.2); readyTimeout ロールバック; マルチ AZ / マルチインスタンスタイプ
R4ドレインが設定ミスの PDB でブロックterminationGracePeriod が強制ドレイン; PDB レビューはアプリオーナーの責務
R5クリティカル期間中の freeze 忘れ宣言的に管理(GitOps)、アドホックではなく
R6テストクラスターが定常的にターンオーバーageThreshold を超える soak 期間中はシャットダウンを無効化
  • R3 ゾーンの注意: surge は候補の AZ に固定(§3.7)。同一 AZ の不足は他のゾーンにフォールバックできない — ゾーン PV NodePool では AZ ごとのヘッドルームを確保すべき。

7.2 検証済み前提

検証サマリー

検証済み(20+ シナリオ): コア surge、同一 AZ ゾーン PV リバインド、ロールバック、limits ゲーティング、マルチプールの閉じ込め、PDB ドレイン、do-not-disrupt マーカー、force-expiry 検出、キャパシティ吸収、placeholder プリエンプション、ウィンドウ境界、リーダー変更再開、forceful fallback、earliest-deadline ソート、オペレーターオプトアウト、12 時間 tight-race soak。

未決: 真の同一 AZ キャパシティ不足(ICE)によるリアルクラウドでのロールバック(issue #109)。

コアメカニズム

前提ステータス日付
スタンドアロン NodeClaim が Auto Mode でプロビジョニング可能検証済み2026-05-29
placeholder Pod surge が make-before-break を完了検証済み2026-06-22
同一 AZ surge で EBS 再アタッチ(ゾーン PV リバインド)検証済み2026-06-22
readyTimeout ミスがクリーンにロールバック検証済み2026-06-22
NodePool limits 消費が surge をゲート検証済み2026-06-22
required karpenter.sh/nodepool が surge をプールに閉じ込め検証済み2026-06-22
明示的 NodeClaim 削除が voluntary パスでドレイン(PDB)検証済み2026-06-22
do-not-disrupt を両ノードに適用、完了時に削除検証済み2026-06-22
pending 中の force-expiry が expired を記録(success/failure ではない)検証済み2026-06-22

応用シナリオ

前提ステータス日付
キャパシティ吸収パス(空きにビンパック、新ノードなし)検証済み2026-06-23
リーダー変更がアノテーションのみから再開検証済み2026-06-23
進行中のローテーションがウィンドウ境界を超えて完了検証済み2026-06-23
placeholder がプリエンプション犠牲者; 敵対的プリエンプション → ロールバック検証済み2026-06-23
do-not-disrupt が Drift に対して有効検証済み2026-06-23

v0.4 以降の追加

前提ステータス日付
Forceful fallback(12 ノードバッチ、graceful + surge なしミックス)検証済み2026-07-04
earliest-deadline 候補ソート検証済み2026-07-04
オペレーター do-not-disrupt が選定から除外検証済み2026-07-04

soak テスト

前提ステータス日付
12h tight-race soak: 71/71 graceful、0 expired、0 failure検証済み2026-07-15
Forceful fallback が制限された claim に対して決定的に発動検証済み2026-07-15
完全な検証エビデンス — クリックで展開

スタンドアロン NodeClaim(能力確認、surge メカニズムではない)

nodeClassRef + requirements のみの NodeClaim が Ready に到達(~30s、実 EC2); admission が --dry-run=server を受け入れ; graceful な finalizer ドリブン削除を確認。K8s 1.35、karpenter.sh/v1(2026-05-29)。

placeholder Pod surge(2026-06-22)

低優先度 placeholder が NodePool 所有の surge NodeClaim を誘導し Ready に到達(~30s)。旧 NodeClaim 削除前に完了; ドレインは voluntary パスに従い; ワークロードが surge ノードに再スケジュール; noderotation_completed_total{outcome="success"} がインクリメント。

同一 AZ ゾーン PV リバインド(2026-06-22)

StatefulSet gp3 PVC が us-west-2a でバインド; ローテーションを跨いで matchNodeRequirements のゾーンパリティがすべての surge ノードを us-west-2a に維持; 同一 PV が再アタッチ(再プロビジョニングではない); センチネルデータ生存。

タイムアウトロールバック(2026-06-22)

readyTimeout をノード ready 時間未満に設定 → タイムアウト → surge claim reap、placeholder 削除、候補保持 + uncordon、outcome="failure" インクリメント。

Limits ゲーティング(2026-06-22)

spec.limits.cpu にヘッドルームなし: 適格候補は surge されず; insufficient limits headroom; cannot surge をログ; in_progress は 0 のまま。

マルチプールの閉じ込め(2026-06-22)

同一 AZ の空きを持つ別プール: surge は候補のプールに留まる(karpenter.sh/nodepool=nrc-poc); 別プール変更なし。

PDB 準拠ドレイン(2026-06-22)

ブロッキング PDB(minAvailable=2、2 レプリカ)がドレインを停滞; minAvailable=1 に緩和で 1 つずつマイグレーション完了。

do-not-disrupt マーカー(2026-06-22)

旧ノードと surge ノードの両方が do-not-disrupt=true + do-not-disrupt-owned を保持; 完了時の unfreeze で両方を削除。

force-expiry 検出(2026-06-22)

プールを freeze + pending 候補の NodeClaim を削除 → state=expired、anchor クリア、surge 残留なし、outcome="expired" インクリメント。

キャパシティ吸収パス(2026-06-23)

若い(ageThreshold 未満、非候補)同一 AZ スペアノードが ~1970m free で 250m placeholder を吸収(新 NodeClaim 誘導なし); プールは 2 claim のまま; outcome="success" インクリメント。

リーダー変更再開(2026-06-23)

ローテーション中(state=pending)にリーダー Pod を kill; 新レプリカが Lease を取得し同じローテーションをアノテーションから継続 — 同一 surge-claim、同一 started-at、リスタートなしで完了。

ウィンドウ境界動作(2026-06-23)

ウィンドウ内でローテーション開始; ウィンドウクローズ後も中止せず完了; 第 2 の適格候補は開始しない(window_active=0)。

placeholder プリエンプション(2026-06-23)

高優先度 Pod が placeholder をプリエンプト; placeholder は何もプリエンプトしない(preemptionPolicy=Never); limits でリプロビジョンブロック下で Pending のまま readyTimeout まで → クリーンロールバック。

do-not-disrupt vs Drift(2026-06-23)

Drifted ノードに do-not-disrupt=true → 3 分以上置換されず; アノテーション除去で即座に drift-replace。

Forceful fallback — 12 ノードバッチ(2026-07-04)

12 ノード、固定 2h expireAfterN=12 > K·C=2: 最初の 6 は graceful、余剰 6 は surge なし。rotation-mode=forceful-fallback; ForcefulFallback Warning Events; forceful 候補に placeholder なし; noderotation_forceful_fallback_total0→6 にクリーンに上昇; PDB は維持; expired ゼロ。

earliest-deadline ソート(2026-07-04)

12 ノードバッチが 1 つの creationTimestamp を共有 → ソートは Name タイブレークに退化: claim は昇順で消費(2rvd5 < 6ssql < dtkgz < ...)。

オペレーター do-not-disrupt 除外(2026-07-04)

候補の Node に do-not-disrupt=true(owned マーカーなし)をアノテート → candidates ゲージが 4→3 にドロップ; 除去で復元。

12h tight-race soak(2026-07-15)

E=2h12mleadTime=1h12m、48 ウィンドウ/日、5 ノードプール。71/71 ローテーション graceful(~12m ケイデンス)。最小マージン 68.3m、中央値 70.3m、最大 71.2m。expired ゼロ、failure ゼロ、forceful_fallback_total=0(armed だが不要)。コントローラー restartCount=0、909 スクレイプ、連続 seq。詳細記録: test/e2e/eks-automode/VALIDATION.md

Forceful fallback 境界(2026-07-15)

別の単一ノードミニプール、候補状態になるまで freeze。解放後 graceful surge が期限内に収まらない → surge なしブランチ: forceful_fallback_total 0→1; claim が解放 56 秒後に削除(期限の 10m04s 前); 当該 claim で placeholder は一切なし; expired は 0 のまま。

未決事項

真の同一 AZ キャパシティ不足(ICE) によるロールバック — 短い readyTimeout で代替(オンデマンドで決定的に誘発不可)。issue #109 で追跡。

注記

  • スタンドアロン NodeClaim の結果はプロジェクトのリスクを低減するが surge メカニズムではない(§3.3 — スタンドアロンノードは NodePool アカウンティングを破壊)
  • RBAC の十分性と karpenter.sh/v1 CRD デコードはすべてのシナリオで暗黙的に検証

7.3 未決事項

  1. 祝日対応スケジューリング — ウィンドウ日が祝日に当たる場合にローテーションをスキップ。v1 では意図的に祝日を無視。
  2. pre-pull イメージソース — Karpenter NodeClass のイメージプル機能を使うか専用 Job か(v2)。
  3. マルチクラウド検証 — EKS Auto Mode を超えた互換性を主張する前に AKS NAP、GKE をテスト。

解決済み

CRD ベースのポリシー移行NodePool ごとのメンテナンスウィンドウRotationPolicy CRD で提供(issue #119、§5.4)。