# 通知設計書 72-FreeDiskSpaceFailed

## 概要

本ドキュメントは、Kubernetesクラスタにおいてイメージガベージコレクションが十分なディスク空き容量を確保できなかった際に発行されるFreeDiskSpaceFailed通知の設計を定義する。

### 本通知の処理概要

FreeDiskSpaceFailed通知は、kubeletのImage GC Manager（イメージガベージコレクションマネージャ）がディスク使用率の高閾値を超えた状態を検知し、未使用イメージの削除を試みたが、低閾値まで空き容量を確保できなかった場合にWarningイベントとして発行される。この通知はノードのディスク容量が逼迫していることを示す重要な警告である。

**業務上の目的・背景**：ノードのイメージファイルシステムの使用率がHighThresholdPercentを超えた場合、Image GC ManagerはLowThresholdPercentまで空き容量を確保するよう試みる。しかし、使用中のイメージが多い、ログやボリュームデータが大量にある等の理由で十分な容量を確保できない場合がある。この通知により管理者は即座にディスク容量の問題を認識し、対応を取ることができる。

**通知の送信タイミング**：GarbageCollect()が定期的に実行される際、ディスク使用率がHighThresholdPercentを超え、かつ未使用イメージの削除によって解放された容量が目標値に達しなかった場合に発行される。

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

**通知内容の概要**：ディスク使用率、ファイルシステム容量、解放されたバイト数を含む詳細なメッセージが送信される。ディスク使用がアクティブイメージ、ログ、ボリューム、その他のデータによる可能性があることを示唆する。

**期待されるアクション**：クラスタ管理者はノードのディスク使用状況を調査し、不要なログの削除、未使用ボリュームのクリーンアップ、またはディスク容量の拡張を検討する。必要に応じてPodの再配置やノードの追加も検討する。

## 通知種別

Kubernetes Event（Warning）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（GarbageCollect処理内で即座に発行） |
| 優先度 | 高（ノードのディスク容量不足はPodの起動やイメージプルに影響） |
| リトライ | なし（次回のGCサイクルで再度チェックされる） |

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

kubeletが保持するnodeRef（ノードのObjectReference）を送信先として使用する。イベントはNodeオブジェクトに紐付けられ、Kubernetes Event APIを通じて記録される。

## 通知テンプレート

### Kubernetes Eventの場合

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

### 本文テンプレート

```
Insufficient free disk space on the node's image filesystem ({usagePercent}% of {capacity} used). Failed to free sufficient space by deleting unused images (freed {freedBytes} bytes). Investigate disk usage, as it could be used by active images, logs, volumes, or other data.
```

### 添付ファイル

該当なし（Kubernetes Eventには添付ファイルの概念はない）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| usagePercent | ディスク使用率（%） | 100 - available*100/capacity から算出 | Yes |
| capacity | ファイルシステム総容量 | StatsProvider.ImageFsStats().CapacityBytes | Yes |
| freedBytes | 解放されたバイト数 | freeSpace()の返却値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 定期処理 | Image GC Manager の GarbageCollect() 実行 | usagePercent >= HighThresholdPercent かつ freed < amountToFree | GCサイクルでディスク使用率が高閾値超過、かつ十分な空き容量確保に失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| usagePercent < HighThresholdPercent | ディスク使用率が高閾値未満の場合はGC不要 |
| freed >= amountToFree | 十分な空き容量を確保できた場合は成功 |
| capacity == 0 | 容量0の場合はInvalidDiskCapacityが先に発行される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[GarbageCollect呼び出し] --> B[ImageFsStats取得]
    B --> C[使用率計算]
    C --> D{usagePercent >= HighThreshold?}
    D -->|No| E[GC不要・終了]
    D -->|Yes| F[amountToFree計算]
    F --> G[freeSpace実行]
    G --> H{freed >= amountToFree?}
    H -->|Yes| I[GC成功・終了]
    H -->|No| J[FreeDiskSpaceFailed Event発行]
    J --> K[エラーを返却]
    K --> L[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | Kubernetes Eventとして記録 | etcdに格納される |

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| FreeDiskSpaceFailed | freed < amountToFree | Event発行、エラー返却。次回GCサイクルで再試行 |
| freeSpace実行エラー | イメージ削除中のエラー（例: 読み取り専用ファイルシステム） | freeSpaceがエラーを返却し、FreeDiskSpaceFailedイベントは発行されない |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（次回GCサイクルで再実行） |
| リトライ間隔 | 約5分（GCサイクル間隔） |
| リトライ対象エラー | 全てのGCエラー |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（GCサイクルに基づいて発行される）

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

- 通知にはディスク使用率と容量情報が含まれるが、機密性は低い
- ノードのストレージ構成情報は運用情報として扱う

## 備考

- メッセージにはformatSize()関数で人間可読な容量表記（GiB, MiB等）が使用される
- freed < amountToFree の状況は、使用中のイメージが多い場合やイメージ以外のデータがディスクを占有している場合に発生する
- イベントの定数 `FreeDiskSpaceFailed` は `pkg/kubelet/events/event.go` で定義

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/kubelet/events/event.go` | 行91-93: FreeDiskSpaceFailed定数の定義 |
| 1-2 | image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | 行88-106: ImageGCPolicy構造体のHighThresholdPercent/LowThresholdPercent |
| 1-3 | image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | 行637-640: evictionInfo構造体 |

**読解のコツ**: HighThresholdPercentがGC発動条件、LowThresholdPercentがGCの目標となる。amountToFree = capacity * (100 - LowThresholdPercent) / 100 - available で計算される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | 行348-417: GarbageCollect()メソッド |

**主要処理フロー**:
1. **行365**: StatsProvider.ImageFsStats()でディスク統計取得
2. **行391**: usagePercent = 100 - int(available*100/capacity) で使用率計算
3. **行392**: usagePercent >= HighThresholdPercent の判定
4. **行393**: amountToFree の計算
5. **行395**: freeSpace() で未使用イメージ削除
6. **行403**: freed < amountToFree のチェック
7. **行407-411**: メッセージ構築とFreeDiskSpaceFailed Event発行

#### Step 3: freeSpace処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | 行482-521: freeSpace()メソッド |
| 3-2 | image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | 行523-545: freeImage()メソッド |

**主要処理フロー**:
- **行488-514**: 未使用イメージを順に削除し、bytesToFreeに達するまで繰り返す
- **行491**: 最近使用されたイメージはスキップ
- **行499**: MinAge未満のイメージはスキップ

#### Step 4: formatSize関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | 行594-617: formatSize()関数 |

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

```
kubelet (定期実行)
    |
    +-- realImageGCManager.GarbageCollect()  [行348]
           |
           +-- imagesInEvictionOrder()  [行354]
           |
           +-- freeOldImages()  [行359]
           |
           +-- statsProvider.ImageFsStats()  [行365]
           |
           +-- 使用率計算 (usagePercent)  [行391]
           |
           +-- freeSpace(amountToFree)  [行395]
           |       |
           |       +-- freeImage() (各イメージに対して)  [行505]
           |               +-- runtime.RemoveImage()  [行529]
           |
           +-- freed < amountToFree チェック  [行403]
                   +-- recorder.Eventf(FreeDiskSpaceFailed)  [行411]
                   +-- formatSize(capacity)  [行410]
```

### データフロー図

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

StatsProvider              GarbageCollect()
(ImageFsStats) ---------> 使用率計算
                           |
Container Runtime          v
(ListImages) -----------> freeSpace()
                           |
                           v
                           freed < amountToFree
                           |
                           +---------> FreeDiskSpaceFailed Event
                                       (Warning, 使用率・容量・解放量を含む)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベントReason定数定義 |
| image_gc_manager.go | `pkg/kubelet/images/image_gc_manager.go` | ソース | Image GC Managerの実装（通知発行元） |
| image_gc_manager_test.go | `pkg/kubelet/images/image_gc_manager_test.go` | テスト | FreeDiskSpaceFailedのテストケースを含む |
