# 通知設計書 53-VolumeMismatch

## 概要

本ドキュメントは、PersistentVolumeClaim（PVC）とPersistentVolume（PV）の間に不一致が検出された際に発行されるイベント通知「VolumeMismatch」の設計について記述する。

### 本通知の処理概要

**業務上の目的・背景**：PVCがPVにバインドされる際、容量・アクセスモード・ボリュームモードなどの要件が一致している必要がある。不一致がある場合、バインドは行われずPodはストレージを利用できない。この通知は、PVCとPVの間の具体的な不一致理由をクラスタ管理者に伝達し、ストレージ設定の修正を促す。特にvolumeModeの不一致（Block vs Filesystem）は頻出する問題であり、この通知による早期検知が重要である。

**通知の送信タイミング**：PV Controllerの同期処理において、(1) PVCが特定のPV名を指定しているが `checkVolumeSatisfyClaim` チェックに失敗した場合、(2) PVとPVCの間にvolumeModeの不一致がある場合に発行される。

**通知の受信者**：PVCオブジェクトおよび/またはPVオブジェクトに対するKubernetes Eventとして発行される。`kubectl describe pvc` や `kubectl describe pv` で監視しているクラスタ管理者、ストレージ管理者が受信者となる。

**通知内容の概要**：「Cannot bind to requested volume: {不一致理由}」または「Cannot bind PersistentVolume to requested PersistentVolumeClaim due to incompatible volumeMode」というメッセージで不一致の具体的理由が含まれる。

**期待されるアクション**：受信者は、PVCとPVの仕様（容量、アクセスモード、ボリュームモード、ノードアフィニティ等）を比較確認し、適合するPVを用意するか、PVCの要件を修正する。

## 通知種別

Kubernetes Event（EventType: Warning）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（PV Controller同期ループ内） |
| 優先度 | 高（ストレージバインド不可はPod起動を阻害） |
| リトライ | コントローラの同期ループにより自動再試行 |

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

PVCオブジェクトに対してEventを発行する場合と、PVオブジェクトに対して発行する場合がある。volumeMode不一致の場合はPVとPVC両方にEventが発行される。

## 通知テンプレート

### Kubernetes Event

| 項目 | 内容 |
|-----|------|
| 送信元コンポーネント | pv controller |
| EventType | Warning |
| Reason | VolumeMismatch |
| 関連オブジェクト | PersistentVolumeClaim / PersistentVolume |

### 本文テンプレート

PVC指定PVの要件不一致：
```
Cannot bind to requested volume "%s": %s
```

PV側のvolumeMode不一致：
```
Cannot bind PersistentVolume to requested PersistentVolumeClaim "%s" due to incompatible volumeMode.
```

PVC側のvolumeMode不一致：
```
Cannot bind PersistentVolume "%s" to requested PersistentVolumeClaim due to incompatible volumeMode.
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| volume.Name | PV名 | PV.ObjectMeta.Name | Yes |
| claim.Name | PVC名 | PVC.ObjectMeta.Name | Yes |
| err | 不一致の詳細理由 | checkVolumeSatisfyClaim()の戻り値 | Yes（要件不一致時） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| PV Controller同期 | syncUnboundClaim | PVC指定PVが要件を満たさない | pv_controller.go 437-441行目 |
| PV Controller同期 | syncVolume | volumeMode不一致が検出された | pv_controller.go 691-697行目 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| PVCにVolumeName未指定 | VolumeName未指定の場合、checkVolumeSatisfyClaimは呼ばれず、findBestMatchForClaimで適合PVが検索される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[PVC同期開始] --> B{PVCにVolumeName指定あり?}
    B -->|Yes| C{指定PVは存在するか?}
    C -->|Yes| D{PVは未バインド?}
    D -->|Yes| E[checkVolumeSatisfyClaim]
    E --> F{要件一致?}
    F -->|No| G[Event: VolumeMismatch<br/>Cannot bind to requested volume]
    F -->|Yes| H[バインド処理]

    I[PV同期開始] --> J{PVCのVolumeName未指定?}
    J -->|Yes| K[volumeMode一致チェック]
    K --> L{volumeMode一致?}
    L -->|No| M[Event: VolumeMismatch<br/>incompatible volumeMode<br/>PV・PVC両方に発行]
    L -->|Yes| N[通常処理継続]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| PersistentVolumeClaims | PVCの要件確認 | コントローラキャッシュ経由 |
| PersistentVolumes | PVの仕様確認 | コントローラキャッシュ経由 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Events | INSERT | VolumeMismatchイベントの記録 |
| PersistentVolumeClaims | UPDATE | ステータスをPendingに更新 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 容量不足 | PVの容量がPVCの要求を満たさない | 十分な容量のPVを用意 |
| アクセスモード不一致 | PVのアクセスモードがPVC要求と不一致 | アクセスモードを確認・修正 |
| volumeMode不一致 | Block/Filesystemの不一致 | PVCまたはPVのvolumeModeを統一 |
| ノードアフィニティ不一致 | PVのノードアフィニティがスケジュール先と不一致 | ノードアフィニティを確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | コントローラ同期ループにより無制限 |
| リトライ間隔 | PV Controllerの再同期間隔に依存 |
| リトライ対象エラー | 全不一致エラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Kubernetes Event APIのレート制限に準拠 |
| 1日あたり上限 | 同一理由のイベントは集約される |

### 配信時間帯

制限なし

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

- イベントメッセージにはPV名、PVC名、不一致理由が含まれるが、ストレージの接続情報や機密データは含まれない
- Kubernetes RBACによりEventの読み取り権限が制御される

## 備考

- volumeMode不一致の場合、PVとPVCの両方にイベントが発行される点が特徴的
- `checkVolumeSatisfyClaim` は容量、アクセスモード、ノードアフィニティ等の複数の観点でチェックを行う

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/controller/volume/events/event.go` | 22行目: `VolumeMismatch` 定数定義 |

**読解のコツ**: ボリューム関連のイベント定数は `pkg/controller/volume/events/event.go` に集約されている。

#### Step 2: syncUnboundClaimでのVolumeMismatch発行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pv_controller.go | `pkg/controller/volume/persistentvolume/pv_controller.go` | 436-441行目: VolumeName指定時のcheckVolumeSatisfyClaim失敗によるVolumeMismatch発行 |

**主要処理フロー**:
1. **436行目**: PVが未バインドであることを確認
2. **437行目**: `checkVolumeSatisfyClaim(volume, claim)` を呼び出し
3. **438行目**: エラー時のログ出力
4. **440行目**: メッセージ構築 `Cannot bind to requested volume "%s": %s`
5. **441行目**: `eventRecorder.Event(claim, Warning, VolumeMismatch, msg)`

#### Step 3: syncVolumeでのvolumeMode不一致検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pv_controller.go | `pkg/controller/volume/persistentvolume/pv_controller.go` | 690-697行目: volumeMode不一致時のVolumeMismatch発行（PVとPVC両方） |

**主要処理フロー**:
- **691行目**: `CheckVolumeModeMismatches(&claim.Spec, &volume.Spec)` の呼び出し
- **695行目**: PVに対するVolumeMismatchイベント発行
- **697行目**: PVCに対するVolumeMismatchイベント発行

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

```
PersistentVolumeController.syncClaim()
    |
    +-- syncUnboundClaim(claim)
    |       |
    |       +-- checkVolumeSatisfyClaim(volume, claim)
    |               |
    |               +-- (error) eventRecorder.Event(claim, Warning, VolumeMismatch, ...)
    |
    +-- syncVolume(volume)
            |
            +-- CheckVolumeModeMismatches(&claim.Spec, &volume.Spec)
                    |
                    +-- (true) eventRecorder.Event(volume, Warning, VolumeMismatch, ...)
                    +-- (true) eventRecorder.Event(claim, Warning, VolumeMismatch, ...)
```

### データフロー図

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

PVC Spec             ---->  checkVolumeSatisfyClaim()   ---->  Kubernetes Event
(VolumeName,                (容量/アクセスモード/                (VolumeMismatch on PVC)
 Resources,                  ノードアフィニティ比較)
 AccessModes)

PV Spec              ---->  CheckVolumeModeMismatches() ---->  Kubernetes Event
(VolumeMode)                (volumeMode比較)                    (VolumeMismatch on PV & PVC)
PVC Spec
(VolumeMode)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/controller/volume/events/event.go` | ソース | VolumeMismatch定数定義（22行目） |
| pv_controller.go | `pkg/controller/volume/persistentvolume/pv_controller.go` | ソース | VolumeMismatch発行ロジック（441, 695, 697行目） |
| binder_test.go | `pkg/controller/volume/persistentvolume/binder_test.go` | テスト | バインドロジックのユニットテスト |
