# 機能設計書 58-Eviction管理

## 概要

本ドキュメントは、Kubeletのノードリソース（メモリ、ディスク等）の逼迫時にPodの退避判定と実行を行うEviction管理機能の設計を記載する。

### 本機能の処理概要

KubeletのEviction管理機能は、ノードのリソース使用量を定期的に監視し、事前定義された閾値を超えた場合にPodを退避（Evict）してノードの安定性を維持する。メモリ、ディスク、PID等の各リソースに対して、ソフト閾値（猶予期間付き）とハード閾値（即時）を設定でき、QoSクラスに基づくPod退避優先順位を制御する。

**業務上の目的・背景**：ノードのメモリやディスクが枯渇するとOOMKillerやカーネルパニックによりノード全体が不安定になる。Eviction管理により、リソース逼迫時に低優先度のPodを計画的に退避し、クリティカルなワークロードとノード自体の安定性を保護する。

**機能の利用シーン**：メモリ使用量がノード容量の95%を超えた場合のPod退避、ディスク使用量が閾値を超えた場合のイメージGC/コンテナGC実行、PID枯渇時のPod退避。

**主要な処理内容**：
1. リソース使用量の定期監視（synchronizeループ）
2. 閾値判定（ソフト閾値/ハード閾値）と猶予期間管理
3. ノード条件（MemoryPressure、DiskPressure、PIDPressure）の設定
4. Pod退避の優先順位決定（QoSクラス、リソース使用量に基づくランキング）
5. ノードレベルリソース回収（イメージGC、コンテナGC）
6. Kernel memcg通知による即時メモリ閾値検知
7. Pod Admission制御（リソース逼迫時のPod受入拒否）

**関連システム・外部連携**：cAdvisor（リソース統計）、cgroup（memcg通知）、イメージGC/コンテナGC（リソース回収）、API Server（ノード条件更新）。

**権限による制御**：Critical Pod（system-node-critical、system-cluster-critical）はリソース逼迫時でもEviction対象外。MemoryPressure時はBestEffort以外のPodはAdmitされる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Kubelet内部機能のため画面関連なし |

## 機能種別

監視処理 / リソース管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Thresholds | []evictionapi.Threshold | Yes | Eviction閾値設定 | シグナル名と閾値の組み合わせ |
| PressureTransitionPeriod | time.Duration | Yes | 条件解除猶予期間 | 0以上 |
| MaxPodGracePeriodSeconds | int64 | Yes | ソフトEviction時の最大猶予期間 | 0以上 |
| KernelMemcgNotification | bool | No | カーネルmemcg通知使用フラグ | - |
| monitoringInterval | time.Duration | Yes | 監視間隔 | 1秒以上推奨 |

### 入力データソース

- cAdvisor/SummaryProvider: ノードおよびPodのリソース使用統計
- Kubelet設定: Eviction閾値設定（--eviction-hard、--eviction-soft等）
- cgroup: カーネルmemcg通知（KernelMemcgNotification有効時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nodeConditions | []v1.NodeConditionType | ノード条件（MemoryPressure等） |
| evictedPods | []*v1.Pod | 退避されたPod一覧 |

### 出力先

- API Server（ノード条件更新、Pod削除/ステータス更新）
- Kubernetesイベント
- Prometheusメトリクス

## 処理フロー

### 処理シーケンス

```
1. Eviction Manager起動
   └─ memcg通知の設定（有効時）、synchronizeループ開始
2. synchronizeループ
   └─ リソース統計取得 → 閾値判定 → ノード条件設定 → リソース回収 → Pod退避
3. 閾値判定
   └─ ソフト/ハード閾値チェック、猶予期間判定
4. ノードレベルリソース回収
   └─ イメージGC、コンテナGCの実行
5. Pod退避
   └─ QoSランキングに基づく退避対象選定 → killPodFunc呼び出し
6. Pod退避後のクリーンアップ待機
   └─ 30秒以内にPodリソースが回収されるのを待機
```

### フローチャート

```mermaid
flowchart TD
    A[synchronize開始] --> B[リソース統計取得]
    B --> C[閾値判定]
    C --> D{閾値超過?}
    D -->|No| E[ノード条件クリア]
    D -->|Yes| F[ノード条件設定]
    F --> G[ノードレベルリソース回収]
    G --> H{回収成功?}
    H -->|Yes| I{閾値解消?}
    I -->|Yes| E
    I -->|No| J[Pod退避ランキング]
    H -->|No| J
    J --> K[最低ランクPod退避]
    K --> L[クリーンアップ待機]
    L --> M{30秒以内に完了?}
    M -->|Yes| N[次回synchronize]
    M -->|No| N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | Critical Pod保護 | system-node-critical、system-cluster-criticalなPodはEviction対象外 | 常時 |
| BR-58-02 | QoS優先順位 | BestEffort → Burstable → Guaranteedの順で退避優先 | リソース逼迫時 |
| BR-58-03 | ソフト閾値猶予 | ソフト閾値は指定された猶予期間後にEvictionをトリガー | ソフト閾値設定時 |
| BR-58-04 | ハード閾値即時 | ハード閾値超過時は即座にEvictionをトリガー（gracePeriod=1秒） | ハード閾値設定時 |
| BR-58-05 | MemoryPressure Admission | MemoryPressure時、BestEffort PodはTolerationなければ拒否 | Pod Admission時 |
| BR-58-06 | 条件遷移期間 | PressureTransitionPeriod中は条件が維持される | 閾値回復後 |
| BR-58-07 | ローカルストレージ閾値 | エフェメラルストレージ/emptyDirの使用量も監視 | localStorageCapacityIsolation有効時 |

### 計算ロジック

- immediateEvictionGracePeriodSeconds = 1（ハード閾値超過時）
- podCleanupTimeout = 30秒
- podCleanupPollFreq = 1秒

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 閾値観察 | thresholdsFirstObservedAt（インメモリ） | INSERT/UPDATE | 閾値初回検出時刻 |
| ノード条件 | nodeConditions（インメモリ） | UPDATE | ノード条件の設定/解除 |
| 統計キャッシュ | lastObservations（インメモリ） | UPDATE | 前回の観測結果 |

### テーブル別操作詳細

#### thresholdsFirstObservedAt（インメモリMap）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | threshold → 検出時刻 | 初回閾値超過時 | ソフト閾値の猶予期間計算に使用 |
| DELETE | threshold | 閾値回復時 | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SummaryProviderError | 一時エラー | リソース統計取得失敗 | 次回synchronizeで再試行 |
| KillPodError | 一時エラー | Pod退避失敗 | 次回synchronizeで再試行 |
| InvalidDiskCapacity | 設定エラー | ディスク容量が0 | ファイルシステムを確認 |

### リトライ仕様

- synchronizeループはmonitoringInterval間隔で継続実行
- Pod退避後はpodCleanupTimeout（30秒）以内にリソース回収を待機
- リソース回収後に再度synchronizeを実行

## トランザクション仕様

managerImplはsync.RWMutexで保護。nodeConditionsの読み取りはRLock、更新はLockで排他制御。

## パフォーマンス要件

- 監視間隔: monitoringInterval（Kubelet設定で指定、デフォルト10秒）
- memcg通知: カーネルレベルでの即時メモリ閾値検知（KernelMemcgNotification有効時）
- Pod退避後のクリーンアップ待機: 最大30秒

## セキュリティ考慮事項

- Evictionはノードの安定性維持が目的であり、DDoS等の悪意のある攻撃への対処ではない
- Critical PodのEviction保護によりシステムコンポーネントの安定性を確保

## 備考

- KubeletSeparateDiskGCフィーチャーゲートによりコンテナFSとイメージFSの分離ディスクGCをサポート
- Windows環境でもメモリ閾値通知をサポート
- signalEphemeralContainerFsLimit、signalEphemeralPodFsLimit、signalEmptyDirFsLimitによるエフェメラルストレージ監視

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `pkg/kubelet/eviction/types.go` | Managerインターフェース、Config、各種関数型 |
| 1-2 | api/ | `pkg/kubelet/eviction/api/` | Threshold、Signal等のAPI定義 |

**読解のコツ**: types.goには多くの関数型（KillPodFunc、ActivePodsFunc、rankFunc等）が定義されており、これらを理解することでeviction_manager.goの実装が読みやすくなる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | eviction_manager.go | `pkg/kubelet/eviction/eviction_manager.go` | managerImpl構造体、NewManager、Start、synchronize |

**主要処理フロー**:
- **66-109行目**: managerImpl構造体 - 主要フィールド（config、killPodFunc、nodeConditions等）
- **114-143行目**: NewManager - マネージャーの初期化
- **146-185行目**: Admit - Pod Admission制御（リソース逼迫時の拒否判定）
- **188-223行目**: Start - 制御ループの開始（memcg通知、synchronizeループ）
- **248-320行目**: synchronize - メイン制御ループ（閾値判定、ランキング構築）

#### Step 3: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | helpers.go | `pkg/kubelet/eviction/helpers.go` | 閾値判定、シグナル観測、ランキング構築 |

### プログラム呼び出し階層図

```
Kubelet
    |
    +-- Eviction Manager.Start()
    |       +-- memcg ThresholdNotifier.Start() [有効時]
    |       +-- synchronize() [monitoringInterval間隔]
    |               +-- summaryProvider.Get()
    |               +-- thresholdsMet()
    |               +-- signalToNodeReclaimFuncs
    |               |       +-- imageGC.DeleteUnusedImages()
    |               |       +-- containerGC.DeleteAllUnusedContainers()
    |               +-- rankFunc (QoSランキング)
    |               +-- killPodFunc()
    |               +-- waitForPodsCleanup()
    |
    +-- Eviction Manager.Admit()
            +-- nodeConditionsチェック
            +-- CriticalPod判定
            +-- QoS/Toleration判定
```

### データフロー図

```
[入力]                      [処理]                         [出力]

SummaryProvider        ──▶  makeSignalObservations() ──▶  signalObservations
(ノード/Pod統計)

閾値設定              ──▶  thresholdsMet()          ──▶  超過閾値一覧
(eviction-hard/soft)

超過閾値              ──▶  signalToRankFunc         ──▶  Pod退避ランキング
                            |
                            +-- signalToNodeReclaimFuncs
                            |       ──▶ イメージGC/コンテナGC
                            |
                            +-- killPodFunc()       ──▶  Pod退避実行

ノード条件            ──▶  Admit()                  ──▶  Pod Admission判定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| eviction_manager.go | `pkg/kubelet/eviction/eviction_manager.go` | ソース | Evictionマネージャー主実装 |
| types.go | `pkg/kubelet/eviction/types.go` | ソース | インターフェース・型定義 |
| helpers.go | `pkg/kubelet/eviction/helpers.go` | ソース | 閾値判定、ランキング等のヘルパー |
| api/ | `pkg/kubelet/eviction/api/` | ソース | Eviction API定義（Threshold、Signal） |
| memory_threshold_notifier.go | `pkg/kubelet/eviction/memory_threshold_notifier.go` | ソース | メモリ閾値通知 |
| defaults_linux.go | `pkg/kubelet/eviction/defaults_linux.go` | ソース | Linuxデフォルト設定 |
