# 通知設計書 110-TaintManagerEviction

## 概要

本ドキュメントは、KubernetesのTaint Evictionコントローラーが発行する「TaintManagerEviction」イベント通知の設計を記述する。TaintManagerがNoExecute Taintに基づいてPodの削除をマークまたはキャンセルした際にNormalイベントとして発行される。

### 本通知の処理概要

Taint Evictionコントローラー（旧TaintManager）がノードのNoExecute Taintとそれに対するPodのToleration設定を評価し、Podを削除対象としてマークする場合、または削除予定をキャンセルする場合に発行されるNormalイベントである。

**業務上の目的・背景**：NoExecute TaintはノードからPodを退避させるための仕組みである。ノード障害やメンテナンス時にノードにNoExecute Taintが追加されると、そのTaintをTolerateしていないPodは削除される。この通知により、運用者がPodの削除/削除キャンセルの状況をリアルタイムに把握でき、ノード障害時のワークロード移行状況を監視できる。

**通知の送信タイミング**：2つのタイミングで発行される。(1) deletePodHandler内でPodの削除が実行される直前（emitPodDeletionEvent、600行目）、(2) 削除予定がキャンセルされる際（emitCancelPodDeletionEvent、613行目）。

**通知の受信者**：Kubernetes Event APIを通じてPodオブジェクトに関連付けられるため、`kubectl get events`やモニタリングツールを通じてクラスタ管理者が受信する。

**通知内容の概要**：削除時は「Marking for deletion Pod {namespace}/{name}」、キャンセル時は「Cancelling deletion of Pod {namespace}/{name}」というメッセージが含まれる。

**期待されるアクション**：削除マーク時は、Pod が他のノードに再スケジュールされることを確認する。キャンセル時は特段のアクションは不要だが、ノードのTaint状態の変化を把握する材料として活用する。

## 通知種別

Kubernetes Event（Normal）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（TimedWorkerQueueからの実行時に発行） |
| 優先度 | 中（Normal） |
| リトライ | Pod削除自体は最大5回リトライ |

### 送信先決定ロジック

Podオブジェクトへの参照（ObjectReference）がイベントの対象（InvolvedObject）となる。

## 通知テンプレート

### Kubernetes Eventの場合

| 項目 | 内容 |
|-----|------|
| EventType | Normal |
| Reason | TaintManagerEviction |
| 発行元コンポーネント | taint-eviction controller |

### 本文テンプレート（削除マーク）

```
Marking for deletion Pod %s
```

### 本文テンプレート（削除キャンセル）

```
Cancelling deletion of Pod %s
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| %s | Pod のNamespacedName（namespace/name形式） | nsName.String() | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| Pod削除実行 | TimedWorkerQueueからのdeletePodHandler実行 | Podの削除が実行される | emitPodDeletionEvent |
| 削除キャンセル | cancelWorkWithEvent呼び出し | 予定されていた削除がキャンセルされる | emitCancelPodDeletionEvent |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| recorderがnil | recorderが設定されていない場合 |
| cancelWork失敗 | taintEvictionQueue.CancelWorkがfalseを返した場合（削除予定がなかった場合） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ノードTaint変更検知] --> B[handleNodeUpdate]
    B --> C[ノードのNoExecute Taint取得]
    C --> D[ノード上の全Pod取得]
    D --> E{各Podについて}
    E --> F[processPodOnNode]
    F --> G{全Taintをtolerate?}
    G -->|No| H[既存の削除予定キャンセル]
    H --> I[TaintManagerEviction Event - Cancel]
    I --> J[即座に削除をスケジュール]
    G -->|Yes| K{tolerationSeconds制限あり?}
    K -->|Yes| L[時限付き削除をスケジュール]
    K -->|No/無限| M[削除予定キャンセル]
    M --> N[TaintManagerEviction Event - Cancel]
    J --> O[deletePodHandler実行]
    L --> O
    O --> P[TaintManagerEviction Event - Marking]
    P --> Q[Pod削除実行]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Nodeオブジェクト | NoExecute Taintの取得 | informer経由 |
| Podオブジェクト | Tolerationの確認、削除対象の特定 | informer経由 |

### テーブル別参照項目詳細

#### Nodeオブジェクト

| 参照項目（フィールド名） | 用途 | 取得条件 |
|-------------------|------|---------|
| spec.taints | NoExecute Taintのフィルタリング | handleNodeUpdate時 |

#### Podオブジェクト

| 参照項目（フィールド名） | 用途 | 取得条件 |
|-------------------|------|---------|
| spec.tolerations | Taintに対するToleration判定 | processPodOnNode時 |
| spec.nodeName | ノード割り当ての確認 | handlePodUpdate時 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Podオブジェクト | UPDATE/DELETE | DisruptionTarget条件の追加後に削除 |
| Eventオブジェクト | INSERT | TaintManagerEvictionイベントの記録 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Pod取得失敗 | APIサーバーエラー | utilruntime.HandleErrorでログ出力 |
| Pod削除失敗 | APIサーバーエラー | 最大5回リトライ（10ms間隔） |
| Event発行失敗 | APIサーバー接続エラー | EventBroadcasterの内部リトライに依存 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Pod削除: 5回（retries定数）、Event: 内部リトライ |
| リトライ間隔 | Pod削除: 10ms |
| リトライ対象エラー | Pod削除時の全エラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Kubernetes Event APIのレート制限に依存 |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし。ノードのTaint変更やPodのToleration変更時に即座に処理される。

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

本イベントにはPodのNamespace/名前のみが含まれ、機密情報は含まれない。

## 備考

- Taint Evictionコントローラーはノード更新をPod更新よりも優先的に処理する（worker関数、357-386行目）
- Pod削除前にDisruptionTarget条件が追加される（addConditionAndDeletePod、129-148行目）
- tolerationSecondsが設定されたTolerationの場合、指定秒数後に削除がスケジュールされる
- UpdateWorkerSizeは8で、nodeName のハッシュによりワーカーに分散される

---

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

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

### 推奨読解順序

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

Taint/Tolerationのマッチングとコントローラーの内部状態を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | Controller構造体（83-105行目）のtaintedNodesマップ |

**読解のコツ**: taintedNodesマップはnodeName -> []Taintのマッピングで、NoExecute Taintのみを保持する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | Run関数（279-355行目）でワーカー起動 |
| 2-2 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | worker関数（357-386行目）でノード/Pod更新処理 |

#### Step 3: ノード更新処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | handleNodeUpdate関数（533-588行目） |
| 3-2 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | processPodOnNode関数（451-490行目） |

**主要処理フロー**:
- **551行目**: getNoExecuteTaintsでNoExecute Taintを抽出
- **566行目**: getPodsAssignedToNodeでノード上のPod取得
- **586行目**: processPodOnNodeで各Podを処理
- **463行目**: GetMatchingTolerationsでToleration判定
- **464行目**: allToleratedがfalseの場合、即座に削除をスケジュール

#### Step 4: イベント発行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | emitPodDeletionEvent関数（590-601行目） |
| 4-2 | taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | emitCancelPodDeletionEvent関数（603-614行目） |

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

```
Controller.Run (279行目)
    |
    +-- worker (357行目)
            |
            +-- handleNodeUpdate (533行目)
            |       |
            |       +-- getNoExecuteTaints (551行目)
            |       +-- getPodsAssignedToNode (566行目)
            |       +-- processPodOnNode (586行目)
            |               |
            |               +-- GetMatchingTolerations (463行目)
            |               +-- cancelWorkWithEvent (467行目)
            |               |       |
            |               |       +-- emitCancelPodDeletionEvent (603行目)
            |               +-- taintEvictionQueue.AddWork (468行目)
            |
            +-- handlePodUpdate (492行目)
                    |
                    +-- processPodOnNode (530行目)

deletePodHandler (107行目)
    |
    +-- emitPodDeletionEvent (113行目, 590行目)
    +-- addConditionAndDeletePod (117行目, 129行目)
```

### データフロー図

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

Node.spec.taints          --> handleNodeUpdate
                              getNoExecuteTaints
                              taintedNodes更新

Pod.spec.tolerations      --> processPodOnNode
Pod.spec.nodeName             GetMatchingTolerations

allTolerated=false        --> cancelWorkWithEvent           --> Event "Cancelling deletion"
                          --> AddWork(即座)                  --> deletePodHandler
                                                            --> Event "Marking for deletion"
                                                            --> Pod削除

allTolerated=true
  tolerationSeconds有限   --> AddWork(遅延)                 --> deletePodHandler
  tolerationSeconds無限   --> cancelWorkWithEvent           --> Event "Cancelling deletion"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| taint_eviction.go | `pkg/controller/tainteviction/taint_eviction.go` | ソース | Taint Evictionコントローラーのメインロジック |
| timed_workers.go | `pkg/controller/tainteviction/timed_workers.go` | ソース | 時限付きワーカーキューの実装 |
| metrics/metrics.go | `pkg/controller/tainteviction/metrics/metrics.go` | ソース | メトリクス定義 |
