# 通知設計書 124-UnmanagedPods

## 概要

本ドキュメントは、Kubernetes の disruption-controller が発行する `UnmanagedPods` イベント通知の設計を記述する。PodDisruptionBudget（PDB）が選択したPodの中に、コントローラによって管理されていないPod（unmanaged pods）が含まれている場合に発行される警告イベントである。

### 本通知の処理概要

本通知は、PDB の同期処理（trySync）中に、PDBのセレクタに一致するPodの中にコントローラ（Deployment, ReplicaSet, StatefulSet等）に管理されていないPodが検出された場合に発行される。管理されていないPodが存在するとPDBのステータス計算が正確に行えない。

**業務上の目的・背景**：PDBはPodのコントローラのスケール情報を基に可用性保護を計算する。コントローラに管理されていないPodがPDBのセレクタに一致している場合、expectedCountの計算が不正確になり、PDBの保護が不完全になる可能性がある。この状態を管理者に通知し、適切な対処を促す。

**通知の送信タイミング**：trySync関数内でgetExpectedPodCountが呼ばれ、戻り値のunmanagedPodsリストが空でない場合に発行される。

**通知の受信者**：Kubernetes Event として PDB オブジェクトに対して記録される。クラスタ管理者が参照する。

**通知内容の概要**：PDBのセレクタに一致するPodの中に管理されていないPodが存在すること、その結果PDBのステータスが正確に計算できないこと、対処方法（minAvailableを整数値に設定する）が記載される。

**期待されるアクション**：クラスタ管理者は、管理されていないPodをPDBのセレクタ範囲外にするか、PDBの `.spec.minAvailable` を整数値に設定して対処する。

## 通知種別

Kubernetes Event（Warning イベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（イベント記録） |
| 優先度 | 中（Warning） |
| リトライ | なし |

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

PDBオブジェクトに対してイベントが記録される。

## 通知テンプレート

### メール通知の場合

本通知はKubernetes Eventであり、メール送信は行わない。

### 本文テンプレート

```
Pods selected by this PodDisruptionBudget (selector: <selector>) were found to be unmanaged. As a result, the status of the PDB cannot be calculated correctly, which may result in undefined behavior. To account for these pods please set ".spec.minAvailable" field of the PDB to an integer value.
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| selector | PDBのラベルセレクタ | pdb.Spec.Selector | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コントローラ処理 | PDB同期（trySync） | len(unmanagedPods) > 0 | getExpectedPodCountが管理されていないPodを検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| unmanagedPodsが0件 | すべてのPodがコントローラに管理されている場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[PDB同期トリガー] --> B[trySync開始]
    B --> C[getPodsForPdb]
    C --> D[getExpectedPodCount]
    D --> E{unmanagedPods}
    E -->|空でない| F[Warning Eventf UnmanagedPods]
    E -->|空| G[正常処理続行]
    F --> H[処理は続行 - エラーではない]
    G --> I[updatePdbStatus]
    H --> I
    I --> J[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| PodDisruptionBudget（API リソース） | PDB情報・セレクタ取得 | pdbLister経由 |
| Pod（API リソース） | Podのコントローラ情報確認 | podLister経由 |

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

#### Pod

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| metadata.ownerReferences | Podのコントローラ有無判定 | PDBセレクタに一致するPod |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Event（API リソース） | INSERT | Warning イベントの記録 |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event | Warning / UnmanagedPods | Kubernetes Event APIを通じて記録 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| N/A | 本イベントはエラーではなく警告 | ログ記録と処理続行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A（本イベントはエラーではない） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

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

### 配信時間帯

特に制限なし。

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

本イベントにはPDBのセレクタ情報が含まれるが、機密情報は含まれない。

## 備考

- UnmanagedPodsイベントはエラーではなく警告であり、処理は続行される（752行目のコメント参照）
- 対処方法としてminAvailableを整数値に設定することが推奨される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | disruption.go | `pkg/controller/disruption/disruption.go` | getExpectedPodCountの戻り値（expectedCount, desiredHealthy, unmanagedPods, err）を確認（818行目） |

**読解のコツ**: unmanagedPods は文字列スライスで、管理されていないPodの名前リストが返される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | disruption.go | `pkg/controller/disruption/disruption.go` | trySync関数の751-758行目がUnmanagedPodsイベントの発行箇所 |

**主要処理フロー**:
1. **746行目**: getExpectedPodCount(ctx, pdb, pods) 呼び出し
2. **752行目**: len(unmanagedPods) > 0 チェック
3. **754-757行目**: recorder.Eventf で UnmanagedPods イベント発行
4. **760行目**: 処理は続行される（エラーではない）

#### Step 3: 管理状態判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | disruption.go | `pkg/controller/disruption/disruption.go` | getExpectedPodCount関数（818行目以降）とgetExpectedScale内の管理状態判定 |

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

```
DisruptionController.trySync (735行目)
    |
    +-- getExpectedPodCount (746行目)
    |      +-- getExpectedScale
    |             +-- podControllerFinder (各Pod のownerReferencesを確認)
    |
    +-- recorder.Eventf("UnmanagedPods") (754行目)
    |
    +-- buildDisruptedPodMap (761行目) [処理続行]
```

### データフロー図

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

PDB + Pods ───> getExpectedPodCount ───> ownerRefs確認 ───> Event記録
                                                             (UnmanagedPods)
                                            |
                                            v
                                         処理続行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| disruption.go | `pkg/controller/disruption/disruption.go` | ソース | trySync, getExpectedPodCount のロジック |
| disruption_test.go | `pkg/controller/disruption/disruption_test.go` | テスト | UnmanagedPods イベントのテスト |
