# 通知設計書 74-FailedValidation

## 概要

本ドキュメントは、KubernetesクラスタにおいてPod名の重複等のバリデーションエラーが検出された際に発行されるFailedValidation通知の設計を定義する。

### 本通知の処理概要

FailedValidation通知は、kubeletのPod Config（config.go）がPodの設定ソースから受け取ったPod一覧をフィルタリングする際、同一ソース内でPod名が重複していることを検出した場合にWarningイベントとして発行される。重複するPodは無視され、最初に検出されたPodのみが有効となる。

**業務上の目的・背景**：kubeletは複数のソース（API Server、Static Pod用のファイル/HTTP等）からPod定義を受け取る。同一ソース内でPod名が重複している場合、どちらのPodを採用すべきか曖昧になるため、重複を検出して警告を発行し、後から検出されたPodを無視する。これにより設定ミスの早期発見と意図しない動作の防止を実現する。

**通知の送信タイミング**：PodConfig（podStorage）がソースからのPod一覧をマージ（merge）する際、filterInvalidPods()関数内で重複Pod名が検出された時点で発行される。

**通知の受信者**：Kubernetes Event APIを通じてPodオブジェクトに紐付くイベントとして記録される。kubectl describe podやイベント監視ツールを通じてPod所有者やクラスタ管理者が受信する。

**通知内容の概要**：「Error validating pod {Pod名} from {ソース名} due to duplicate pod name "{Pod名}", ignoring」というメッセージで、重複が検出されたPodの名前とソースが通知される。

**期待されるアクション**：クラスタ管理者は該当するPodソース（Static Podの設定ファイルディレクトリ等）を確認し、重複するPod定義を修正または削除する。

## 通知種別

Kubernetes Event（Warning）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Pod設定マージ処理内で即座に発行） |
| 優先度 | 中（重複Podが無視されるため影響あり） |
| リトライ | なし（次回のPod設定更新時に再チェック） |

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

バリデーションに失敗したPodオブジェクト自体を送信先として使用する。イベントはPodオブジェクトに紐付けられる。

## 通知テンプレート

### Kubernetes Eventの場合

| 項目 | 内容 |
|-----|------|
| 送信元コンポーネント | kubelet |
| EventType | Warning |
| Reason | FailedValidation |
| 対象オブジェクト | Pod |

### 本文テンプレート

```
Error validating pod {pod} from {source} due to duplicate pod name "{podName}", ignoring
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| pod | Pod識別子（format.Pod形式） | format.Pod(pod) | Yes |
| source | Pod設定ソース名 | source引数 | Yes |
| podName | 重複しているPod名 | pod.Name | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| Pod設定更新 | podStorage.merge()の実行 | 同一ソース内でPod名が重複 | filterInvalidPods()で検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Pod名が一意 | 同一ソース内でPod名の重複がない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ソースからPod一覧受信] --> B[podStorage.Merge呼び出し]
    B --> C[podStorage.merge内部処理]
    C --> D[filterInvalidPods実行]
    D --> E{Pod名重複?}
    E -->|No| F[Podを有効リストに追加]
    E -->|Yes| G[FailedValidation Event発行]
    G --> H[Podを無視してスキップ]
    F --> I[マージ処理続行]
    H --> I
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | インメモリでのPod名重複チェック | sets.Set[string]を使用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Events (etcd) | INSERT | Kubernetes Eventオブジェクトが作成される |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Pod名重複 | 同一ソース内で同名のPodが存在 | 重複Podを無視し、Event発行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | Pod設定ソースの更新タイミングに依存 |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- Pod名とソース名が通知に含まれるが、機密情報ではない

## 備考

- filterInvalidPods()関数では個別のPodバリデーションは行わず、名前の重複チェックのみを実施する
- 各ソースからのPodは個別にバリデーション済みという前提
- イベントの定数 `FailedValidation` は `pkg/kubelet/events/event.go` の行108で定義

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/kubelet/events/event.go` | 行107-109: FailedValidation定数の定義（Config event reason list） |
| 1-2 | config.go | `pkg/kubelet/config/config.go` | 行43-53: PodConfig構造体（pods, mux, updates, sources） |
| 1-3 | config.go | `pkg/kubelet/config/config.go` | 行106-124: podStorage構造体 |

**読解のコツ**: PodConfigは複数のソースからのPod設定を統合するmuxパターンを使用している。podStorageが実際のPod管理とバリデーションを担当する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.go | `pkg/kubelet/config/config.go` | 行142-175: podStorage.Merge()メソッド（ソースからの更新をマージ） |
| 2-2 | config.go | `pkg/kubelet/config/config.go` | 行177-248: podStorage.merge()内部メソッド |

**主要処理フロー**:
1. **行196-197**: updatePodsFunc内でfilterInvalidPodsを呼び出し
2. **行231**: update.Podsに対してupdatePodsFuncを実行

#### Step 3: バリデーション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | config.go | `pkg/kubelet/config/config.go` | 行262-279: filterInvalidPods()関数 |

**主要処理フロー**:
- **行263**: names := sets.Set[string]{} で名前セットを初期化
- **行264-277**: 各Podについて名前の重複をチェック
- **行267**: kubecontainer.GetPodFullName(pod) でフルネームを取得
- **行268**: names.Has(name) で重複チェック
- **行269-270**: 重複時: ログ出力 + FailedValidation Event発行
- **行271**: continue で重複Podをスキップ
- **行273**: 重複なし: names.Insert(name) で名前を登録

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

```
kubelet
    |
    +-- PodConfig.mux (各ソースから更新受信)
           |
           +-- podStorage.Merge(source, update)  [行142]
                  |
                  +-- podStorage.merge(source, update)  [行177]
                         |
                         +-- filterInvalidPods(pods, source, recorder)  [行197]
                                |
                                +-- GetPodFullName(pod)  [行267]
                                +-- names.Has(name) チェック  [行268]
                                +-- recorder.Eventf(FailedValidation)  [行270]
```

### データフロー図

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

Pod設定ソース              podStorage.merge()
(API Server,              |
Static Pod等) ----------> filterInvalidPods()
                           |
                           +-- 重複なし --> 有効Podリスト
                           |                (adds/updates/deletes)
                           +-- 重複あり --> FailedValidation Event
                                            (Warning, Pod)
                                            + Podを無視
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | FailedValidation定数定義 |
| config.go | `pkg/kubelet/config/config.go` | ソース | PodConfig / podStorage / filterInvalidPods実装（通知発行元） |
| format/pod.go | `pkg/kubelet/util/format/` | ソース | Pod表示フォーマット関数 |
