# 通知設計書 121-MultiplePodDisruptionBudgets

## 概要

本ドキュメントは、Kubernetes の disruption-controller が発行する `MultiplePodDisruptionBudgets` イベント通知の設計を記述する。Podが複数のPodDisruptionBudget（PDB）に一致した場合に発行される警告イベントである。

### 本通知の処理概要

本通知は、PodDisruptionBudget コントローラ（disruption-controller）がPodに対応するPDBを検索した際に、1つのPodが複数のPDBに一致するケースを検出して警告イベントを発行する処理である。

**業務上の目的・背景**：PodDisruptionBudgetはPodの可用性を保護するための重要なリソースであり、1つのPodが複数のPDBに該当する場合、どのPDBが適用されるかが不定（任意の1つが選択される）となる。この状態はクラスタ管理者にとって意図しない動作を引き起こす可能性があるため、早期に検知し対処する必要がある。

**通知の送信タイミング**：disruption-controller がPodの変更イベント（追加・更新・削除）を処理する際に、`getPdbForPod` 関数が呼ばれ、Podに一致するPDBが2つ以上見つかった時点でイベントが記録される。

**通知の受信者**：Kubernetes Event として Pod オブジェクトに対して記録される。`kubectl describe pod` や `kubectl get events` で確認でき、クラスタ管理者やアプリケーション運用者が参照する。

**通知内容の概要**：どのPodが複数のPDBに一致しているか、どのPDBが任意に選択されたかを含むメッセージが記録される。

**期待されるアクション**：クラスタ管理者はPDBのセレクタ設定を見直し、1つのPodが1つのPDBにのみ一致するようにセレクタを修正する必要がある。

## 通知種別

Kubernetes Event（Warning イベント）

## 送信仕様

### 基本情報

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

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

Podオブジェクトに対してイベントが記録される。イベントの参照先はPodリソースそのものであり、当該Podの Namespace/Name を基に関連付けられる。

## 通知テンプレート

### メール通知の場合

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

### 本文テンプレート

```
Pod "<Namespace>"/"<PodName>" matches multiple PodDisruptionBudgets.  Chose "<PDBName>" arbitrarily.
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Namespace | Podの名前空間 | pod.Namespace | Yes |
| PodName | Pod名 | pod.Name | Yes |
| PDBName | 任意に選択されたPDB名 | pdbs[0].Name | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コントローラ処理 | Pod追加・更新・削除イベント | Podが2つ以上のPDBに一致 | getPdbForPod関数内でPDB一覧を取得し、len(pdbs) > 1 の場合に発行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| PDBが0件 | PDBが見つからない場合はイベント自体が発行されない |
| PDBが1件 | 正常ケースのためイベントは発行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Pod変更イベント発生] --> B[getPdbForPod呼び出し]
    B --> C[pdbLister.GetPodPodDisruptionBudgets]
    C --> D{一致するPDB数}
    D -->|0件| E[nilを返却 - イベントなし]
    D -->|1件| F[正常 - PDB返却]
    D -->|2件以上| G[Warning Eventf MultiplePodDisruptionBudgets]
    G --> H[pdbs 0 を任意選択して返却]
    E --> I[終了]
    F --> I
    H --> I
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| PodDisruptionBudget（API リソース） | Podに一致するPDBの検索 | pdbLister経由でキャッシュから取得 |
| Pod（API リソース） | 対象Podの情報取得 | podLister経由でキャッシュから取得 |

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

#### PodDisruptionBudget

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| metadata.name | イベントメッセージ内のPDB名 | Podのラベルに一致するSelector |
| spec.selector | Podとのマッチング | ラベルセレクタ照合 |

### 更新テーブル一覧

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

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

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| PDB取得失敗 | pdbLister.GetPodPodDisruptionBudgets がエラーを返した場合 | nilを返却し、PDB同期をスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

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

### 配信時間帯

特に制限なし。コントローラループの実行タイミングに依存する。

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

本イベントにはPod名、Namespace名、PDB名が含まれるが、機密情報は含まれない。Kubernetes RBAC によりイベントの閲覧権限が制御される。

## 備考

- 複数PDBが一致した場合、最初のPDB（pdbs[0]）が任意に選択される
- この動作は非決定的であり、本番環境では避けるべき構成である

---

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

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

### 推奨読解順序

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

PodDisruptionBudget リソースとPodの関係を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | disruption.go | `pkg/controller/disruption/disruption.go` | DisruptionController構造体（81-120行目）でコントローラの主要フィールドを確認 |

**読解のコツ**: `pdbLister` と `podLister` がインフォーマーキャッシュからのリスト取得を担っている点に注目する。

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

Pod変更イベントのハンドラが処理の起点となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | disruption.go | `pkg/controller/disruption/disruption.go` | getPdbForPod関数（609-625行目）がPodからPDBを検索するロジック |

**主要処理フロー**:
1. **609行目**: getPdbForPod関数の定義開始
2. **613行目**: pdbLister.GetPodPodDisruptionBudgets(pod) でPDB一覧取得
3. **619行目**: len(pdbs) > 1 の条件チェック
4. **620行目**: 警告メッセージの構築
5. **622行目**: recorder.Event で MultiplePodDisruptionBudgets イベント発行
6. **624行目**: pdbs[0] を返却

#### Step 3: コントローラ初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | disruption.go | `pkg/controller/disruption/disruption.go` | NewDisruptionController関数（133-160行目）でコントローラの初期化処理を確認 |

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

```
DisruptionController.Run
    |
    +-- worker (queue consumer)
    |      +-- sync
    |             +-- getPdbForPod (609行目)
    |                    +-- pdbLister.GetPodPodDisruptionBudgets
    |                    +-- recorder.Event("MultiplePodDisruptionBudgets") (622行目)
    |
    +-- trySync (735行目)
```

### データフロー図

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

Pod変更イベント ───> getPdbForPod ───> pdbLister照合 ───> Event記録
                                                          (MultiplePodDisruptionBudgets)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| disruption.go | `pkg/controller/disruption/disruption.go` | ソース | DisruptionControllerの本体、イベント発行ロジック |
| disruption_test.go | `pkg/controller/disruption/disruption_test.go` | テスト | DisruptionControllerのテスト |
