# 通知設計書 13-ResizeDeferred

## 概要

本ドキュメントは、KubernetesのkubeletがPodのインプレースリサイズ要求を延期した際に発行されるイベント通知「ResizeDeferred」の設計を記述する。

### 本通知の処理概要

InPlacePodVerticalScaling機能の一部として、Podのリソースリサイズ要求がノードのリソース制約により即座に実行できない場合に、リサイズを延期（Deferred）としてマークし、本通知を発行する。リソースが利用可能になった時点で再評価される。

**業務上の目的・背景**：InPlacePodVerticalScaling（Pod Vertical Autoscaling）では、Podを再作成せずにリソース（CPU/メモリ）を変更できる。しかし、ノードの利用可能リソースが不足している場合、即座にリサイズを実行することはできない。この通知は、リサイズ要求が受け付けられたが一時的に延期されていることをユーザーに伝え、リソースが空き次第自動的にリサイズが実行されることを示す。

**通知の送信タイミング**：allocation_managerのhandlePodResourcesResize処理中、canResizePodがリサイズ不可と判定し、その理由がDeferred（一時的なリソース不足）の場合に発行される。statusManagerのSetPodResizePendingConditionが新しい状態を設定した場合のみ発行される（重複発行を防止）。

**通知の受信者**：Pod作成を要求したユーザー、Namespace管理者。Kubernetes Eventとして記録される。

**通知内容の概要**：「Pod resize Deferred: {リソースサマリーJSON}」という形式で、延期理由と要求リソースの詳細が通知される。

**期待されるアクション**：ユーザーはリサイズが一時的に延期されていることを認識し、ノードのリソース利用状況を確認する。他のPodが終了してリソースが空けば自動的にリサイズが再試行される。

## 通知種別

Kubernetes Event（クラスタ内部イベント通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（allocation_managerの処理フロー内で即時発行） |
| 優先度 | 中（Warning） |
| リトライ | 有（PendingResizesの再評価で自動リトライ） |

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

イベントの対象オブジェクトは、リサイズが延期されたPodリソースである。allocation_managerの `recorder.Eventf()` により、対象Podに紐づくEventオブジェクトがAPI Serverに記録される。

## 通知テンプレート

### Kubernetes Eventの場合

| 項目 | 内容 |
|-----|------|
| EventType | Warning |
| Reason | ResizeDeferred |
| Regarding | 対象Pod |
| 発行元 | kubelet |

### 本文テンプレート

```
Pod resize Deferred: {"initContainers":[...],"containers":[...],"generation":N,"error":"message"}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| reason | 延期理由（"Deferred"） | canResizePodの判定結果 | Yes |
| message | 延期の詳細メッセージ | canResizePodの判定結果 | Yes |
| generation | Podのgeneration | pod.Generation | Yes |
| containers | コンテナ別のリソース要求 | pod.Spec.Containers | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | handlePodResourcesResize | canResizePodがDeferred理由を返却 かつ SetPodResizePendingConditionがtrueを返却 | ノードリソース不足による一時延期 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 既にDeferred状態の場合 | SetPodResizePendingConditionがfalseを返す（既に同じ状態が設定済み）場合、イベントは発行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[PendingResize検出] --> B[handlePodResourcesResize]
    B --> C[UpdatePodFromAllocation]
    C --> D{リソース変更あり?}
    D -->|なし| E[ClearPodResizePendingCondition]
    D -->|あり| F[IsInPlacePodVerticalScalingAllowed]
    F -->|不可| G[SetPodResizePendingCondition Infeasible]
    F -->|可| H[canResizePod]
    H -->|fit=true| I[リサイズ実行]
    H -->|fit=false, reason=Deferred| J[SetPodResizePendingCondition]
    J --> K{状態が変更された?}
    K -->|Yes| L[Event発行: ResizeDeferred]
    K -->|No| M[イベント発行スキップ]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| etcd (Pod) | Pod Specのリソース要求確認 | リサイズ対象のリソース比較 |
| etcd (Node) | ノードのAllocatable確認 | リサイズ可否判定 |

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

#### Pod リソース

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| spec.containers[].resources | リサイズ後のリソース要求 | リサイズ対象のPod |
| metadata.generation | Pod世代番号 | イベントメッセージに含める |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| etcd (Event) | INSERT | Eventオブジェクトの作成 |
| statusManager (内部) | UPDATE | PodResizePendingConditionの設定 |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | reason | "ResizeDeferred" | イベント理由 |
| INSERT | message | "Pod resize Deferred: {JSON}" | リソースサマリー |
| INSERT | type | "Warning" | イベントタイプ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ノードリソース不足 | 要求リソースがノードのAllocatable超過 | 他のPodの終了を待つ、またはリソース要求を減らす |
| CPU不足 | CPU要求がノードの利用可能CPUを超過 | 他のPodのCPU使用量減少を待つ |
| メモリ不足 | メモリ要求がノードの利用可能メモリを超過 | 他のPodのメモリ使用量減少を待つ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 無制限（リソースが利用可能になるまで） |
| リトライ間隔 | RetryPendingResizesのトリガーに依存 |
| リトライ対象エラー | Deferred状態のリサイズ要求 |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。

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

- イベントメッセージにはPodのリソース要求（CPU/メモリ）のJSON表現が含まれる。これはPodのリソース設定情報であり、機密性は低い。

## 備考

- InPlacePodVerticalScaling機能ゲートが有効な場合のみ本通知は発生する。
- ResizeDeferredイベントはリソース不足による一時的な延期を示し、ResizeInfeasible（永続的に不可能）とは区別される。
- Deferred状態のPodは `podsWithPendingResizes` リストに保持され（allocation_manager.go:276-277行目）、定期的に再評価される。
- 再評価の結果リソースが利用可能になった場合、メトリクス `PodDeferredAcceptedResizes` がインクリメントされる（allocation_manager.go:284行目）。

---

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

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

### 推奨読解順序

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

イベント定数とリサイズメッセージ生成の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | event.go | `pkg/kubelet/events/event.go` | 37行目: `ResizeDeferred = "ResizeDeferred"` 定数 |
| 1-2 | resize.go | `pkg/kubelet/events/resize.go` | 58-59行目: PodResizePendingMsg関数 |
| 1-3 | resize.go | `pkg/kubelet/events/resize.go` | 29-40行目: podResourceSummary構造体 |

**読解のコツ**: resize.goのPodResizePendingMsg関数はJSON形式でPodのリソースサマリーを生成する。このJSONがイベントメッセージの一部となる。

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

allocation_managerのリサイズ処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | allocation_manager.go | `pkg/kubelet/allocation/allocation_manager.go` | 260-286行目: RetryPendingResizesメインループ |

**主要処理フロー**:
1. **260行目**: `podsWithPendingResizes` を走査
2. **268行目**: 現在のDeferred状態を確認
3. **270行目**: `handlePodResourcesResize` を呼び出し
4. **275-276行目**: Deferred判定時にリストに再追加

#### Step 3: リサイズ判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | allocation_manager.go | `pkg/kubelet/allocation/allocation_manager.go` | 584-646行目: handlePodResourcesResize関数 |
| 3-2 | allocation_manager.go | `pkg/kubelet/allocation/allocation_manager.go` | 634-643行目: Deferred/Infeasibleイベント発行 |
| 3-3 | allocation_manager.go | `pkg/kubelet/allocation/allocation_manager.go` | 709行目以降: canResizePod関数 |

**主要処理フロー**:
- **636行目**: `eventType := events.ResizeDeferred` でイベントタイプを設定
- **637-638行目**: Infeasibleの場合はeventTypeを上書き
- **640行目**: PodResizePendingMsgでメッセージ生成
- **641行目**: recorder.Eventfでイベント発行

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

```
allocation_manager.RetryPendingResizes (allocation_manager.go:260)
    |
    +-- handlePodResourcesResize (allocation_manager.go:584)
    |       |
    |       +-- UpdatePodFromAllocation
    |       +-- IsInPlacePodVerticalScalingAllowed
    |       +-- canResizePod (allocation_manager.go:709)
    |       |       |
    |       |       +-- (ノードリソース比較)
    |       |
    |       +-- statusManager.SetPodResizePendingCondition
    |       +-- events.PodResizePendingMsg (resize.go:58)
    |       +-- recorder.Eventf
```

### データフロー図

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

Pod Spec (desired resources) -> handlePodResourcesResize -> Event (Warning/ResizeDeferred)
                                    |                           |
Node Allocatable ------------> canResizePod判定           statusManager更新
                                    |
                                    +-> PodResizePendingMsg -> JSON形式のリソースサマリー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| event.go | `pkg/kubelet/events/event.go` | ソース | イベント理由定数の定義 |
| resize.go | `pkg/kubelet/events/resize.go` | ソース | リサイズイベントメッセージ生成 |
| allocation_manager.go | `pkg/kubelet/allocation/allocation_manager.go` | ソース | リサイズ処理のメインロジック |
| status_manager.go | `pkg/kubelet/status/status_manager.go` | ソース | PodResizePendingConditionの管理 |
