# 通知設計書 40-FailedMount

## 概要

本ドキュメントは、Kubernetesクラスタにおいてボリュームのマウントに失敗した際に発行されるFailedMountイベント通知の設計を記述する。kubeletのvolume operation generatorがボリュームのマウント操作に失敗した場合にこの通知が発行される。

### 本通知の処理概要

FailedMount通知は、kubeletがPodに必要なボリュームをコンテナにマウントする処理が失敗した際に発行されるWarningイベントである。マウント操作にはデバイスマウント（MountDevice）とボリュームセットアップ（SetUp）の2段階があり、いずれの失敗時にもこのイベントが発行される。また、ブロックボリュームのノードアフィニティチェック失敗時にも発行される。

**業務上の目的・背景**：ボリュームのマウント失敗はコンテナが必要なデータにアクセスできないことを意味し、Podの起動失敗に直結する。ファイルシステムの破損、権限問題、ストレージバックエンドのエラー、ノードアフィニティの不一致など多様な原因が考えられるため、詳細なエラー情報を含む通知が運用上重要である。

**通知の送信タイミング**：ボリュームマウント操作（MountVolume）が実行され、MountDevice、SetUp、またはNodeAffinityチェックでエラーが発生した時点で発行される。eventRecorderFunc内で操作完了後に発行される。

**通知の受信者**：イベントはPodオブジェクトに紐づけられる。Podの所有者、クラスタ管理者、モニタリングシステムが受信者となる。

**通知内容の概要**：マウント失敗のエラーメッセージが含まれる。メッセージは「MountVolume.MountDevice failed」「MountVolume.SetUp failed」「MountVolume.NodeAffinity check failed」のプレフィックスとエラー詳細の組み合わせで構成される。

**期待されるアクション**：クラスタ管理者はエラーメッセージに基づいて原因を特定する。ファイルシステムエラーの場合はノードの手動修復、権限問題の場合はSecurityContextの見直し、ノードアフィニティ不一致の場合はPVのnodeAffinityまたはPodのスケジューリング設定の見直しが必要。

## 通知種別

Kubernetes Event（Warning）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（ボリューム操作完了コールバック内で発行） |
| 優先度 | 高（Warning EventType） |
| リトライ | ボリューム操作自体のリトライに含まれる |

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

イベントはボリュームを必要としているPodオブジェクトに対して記録される。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A（Kubernetes Event） |
| 送信元名称 | kubelet |
| 件名 | N/A |
| 形式 | Kubernetes Event Object |

### 本文テンプレート

```
# eventRecorderFunc経由（一般的なマウント失敗）
{err.Error() の内容}

# MountDevice失敗時（操作関数内部）
MountVolume.MountDevice failed for volume "{volumeName}" (UniqueName: "{uniqueName}") pod "{podName}" (UID: "{podUID}") : {error}

# SetUp失敗時（操作関数内部）
MountVolume.SetUp failed for volume "{volumeName}" (UniqueName: "{uniqueName}") pod "{podName}" (UID: "{podUID}") : {error}

# NodeAffinity失敗時
MountVolume.NodeAffinity check failed for volume "{volumeName}" (UniqueName: "{uniqueName}") pod "{podName}" (UID: "{podUID}") : {error}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| err | マウント操作のエラー | MountDevice/SetUp/NodeAffinityチェックの戻り値 | Yes |
| volumeName | ボリューム名 | volumeToMount.VolumeName | Yes |
| uniqueName | ユニーク名 | volumeToMount.UniqueName | Yes |
| podName | Pod名 | volumeToMount.Pod.Name | Yes |
| podUID | Pod UID | volumeToMount.Pod.UID | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ボリューム操作 | MountDevice失敗 | デバイスマウント操作がエラーを返した場合 | volumeDeviceMounter.MountDevice() |
| ボリューム操作 | SetUp失敗 | ボリュームセットアップ操作がエラーを返した場合 | volumeMounter.SetUp() |
| ボリューム操作 | NodeAffinity check失敗 | ノードアフィニティチェックがエラーを返した場合 | checkNodeAffinity() |
| 操作完了コールバック | eventRecorderFunc | err != nil | 操作全体の失敗時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| マウント成功 | 正常にマウントが完了した場合はWarningイベントは発行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ボリュームマウント要求] --> B[NodeAffinityチェック]
    B -->|失敗| C[Warning Event: NodeAffinity check failed]
    B -->|成功| D{デバイスマウント必要?}
    D -->|Yes| E[MountDevice実行]
    E -->|失敗| F[checkForFailedMount + エラー状態マーク]
    E -->|成功| G[ボリュームSetUp実行]
    D -->|No| G
    G -->|失敗| H[checkForFailedMount + エラー状態マーク]
    G -->|成功| I[マウント完了記録]
    F --> J[eventRecorderFunc: Warning Event]
    H --> J
    C --> K[return error]
    J --> K
    I --> L[SuccessfulMountVolume Event]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| VolumeSpec | ボリューム仕様 | Podのvolume定義 |
| PersistentVolume | PVのNodeAffinity | checkNodeAffinity用 |
| Node | ノードラベル | NodeAffinityチェック用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Events | INSERT | FailedMountイベントの記録 |
| actualStateOfWorld | UPDATE | マウントエラー状態のマーク |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Reason | "FailedMount" | Kubernetes Eventオブジェクト |
| INSERT | Event.Type | "Warning" | EventTypeWarning |
| INSERT | Event.Message | エラーメッセージ | 失敗した操作に応じたプレフィックス付き |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| MountDevice失敗 | デバイスパスの問題、ファイルシステムエラー | ボリューム操作リトライで再試行 |
| SetUp失敗 | 権限問題、ストレージバックエンドエラー | ボリューム操作リトライで再試行 |
| NodeAffinity不一致 | PVのnodeAffinityとノードが不一致 | ユーザアクション必要 |
| ファイルシステム不一致 | マウント時のFS mismatch | checkForFailedMountでPVにもイベント記録 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | ボリューム操作のリトライ機構に依存 |
| リトライ間隔 | Exponential Backoff |
| リトライ対象エラー | 一般的なマウントエラー（NodeAffinityエラーは除く） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | ボリューム操作のリトライ頻度に依存 |
| 1日あたり上限 | 制限なし |

### 配信時間帯

時間帯の制限なし。

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

- エラーメッセージにボリューム名、Pod名、UIDが含まれる
- ファイルシステムエラーの詳細が含まれる可能性がある
- イベントはKubernetes RBACにより閲覧権限が制御される

## 備考

- checkForFailedMount関数により、ファイルシステム不一致エラーの場合はPersistentVolumeオブジェクトに対してもFailedMountOnFilesystemMismatchイベントが記録される
- マウントエラーの状態はactualStateOfWorldにmarkVolumeErrorState/markDeviceErrorStateとして記録され、後続の再試行判定に使用される
- ブロックボリューム（MapVolume）のNodeAffinityチェック失敗時にもFailedMountVolumeイベントが発行される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/kubelet/events/event.go` | 64行目: `FailedMountVolume = "FailedMount"` 定数定義 |

**読解のコツ**: 定数名は`FailedMountVolume`だが、イベントReason文字列は`"FailedMount"`である点に注意。

#### Step 2: eventRecorderFuncを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | operation_generator.go | `pkg/volume/util/operationexecutor/operation_generator.go` | 647-651行目: eventRecorderFunc定義 |

**主要処理フロー**:
1. **647行目**: `eventRecorderFunc := func(err *error)` - エラー時イベント記録関数定義
2. **649行目**: `og.recorder.Eventf(volumeToMount.Pod, v1.EventTypeWarning, kevents.FailedMountVolume, (*err).Error())` - イベント記録

#### Step 3: マウント操作フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | operation_generator.go | `pkg/volume/util/operationexecutor/operation_generator.go` | 542-551行目: MountDevice処理とエラーハンドリング |
| 3-2 | operation_generator.go | `pkg/volume/util/operationexecutor/operation_generator.go` | 594-607行目: SetUp処理とエラーハンドリング |
| 3-3 | operation_generator.go | `pkg/volume/util/operationexecutor/operation_generator.go` | 661-671行目: checkForFailedMount関数 |

**主要処理フロー**:
- **542-548行目**: MountDevice呼び出しとエラー時のcheckForFailedMount
- **601-602行目**: SetUp失敗時のcheckForFailedMountとmarkVolumeErrorState
- **661-671行目**: ファイルシステム不一致検出時のPVへのイベント記録

#### Step 4: ブロックボリュームのNodeAffinityチェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | operation_generator.go | `pkg/volume/util/operationexecutor/operation_generator.go` | 939-943行目: MapVolumeのNodeAffinityチェック失敗時 |

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

```
operationGenerator.GenerateMountVolumeFunc()
    |
    +-- mountVolumeFunc (操作関数)
    |      |
    |      +-- checkNodeAffinity()
    |      |      +-- [失敗] recorder.Eventf(pod, Warning, "FailedMount", ...)
    |      |
    |      +-- volumeDeviceMounter.MountDevice()
    |      |      +-- [失敗] checkForFailedMount()
    |      |      |           +-- [FS mismatch] recorder.Eventf(pv, Warning, "FailedMountOnFilesystemMismatch")
    |      |      +-- [失敗] markDeviceErrorState()
    |      |
    |      +-- volumeMounter.SetUp() / SetUpAt()
    |             +-- [失敗] checkForFailedMount()
    |             +-- [失敗] markVolumeErrorState()
    |
    +-- eventRecorderFunc (操作完了コールバック)
           +-- [err != nil] recorder.Eventf(pod, Warning, "FailedMount", err)
```

### データフロー図

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

Pod.Spec.Volumes             operationGenerator                   Kubernetes Event (Pod)
(ボリューム定義)     ----->   GenerateMountVolumeFunc        ----> (Reason: "FailedMount",
                              (operation_generator.go)              Type: Warning)
VolumeSpec           ----->   MountDevice / SetUp              |
                              checkNodeAffinity                +--> Kubernetes Event (PV)
PersistentVolume     ----->                                        (Reason: "FailedMount
.Spec.NodeAffinity                                                  OnFilesystemMismatch")
                                                               |
                                                               +--> actualStateOfWorld
                                                                    エラー状態マーク
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベント定数定義（FailedMountVolume） |
| operation_generator.go | `pkg/volume/util/operationexecutor/operation_generator.go` | ソース | マウント操作の生成・実行とイベント記録 |
| kubelet.go | `pkg/kubelet/kubelet.go` | ソース | ボリュームマネージャの初期化 |
