# 機能設計書 39-スケジューラーフレームワーク

## 概要

本ドキュメントは、Kubernetesスケジューラーフレームワーク（Scheduling Framework）の機能設計を記述する。スケジューラーの拡張ポイント（Extension Points）を定義し、プラグインベースのスケジューリングアルゴリズムを実現する基盤を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesスケジューラーフレームワークは、スケジューリングロジックをプラグイン化することで拡張性と保守性を実現する。各スケジューリング段階（PreFilter、Filter、Score等）がプラグインインターフェースとして定義され、in-treeおよびout-of-treeのプラグインを統一的に管理する。

**機能の利用シーン**：スケジューラーの初期化時にプロファイルに基づいてプラグインが登録され、各スケジューリングサイクルでプラグインチェーンが実行される。

**主要な処理内容**：
1. Extension Points（拡張ポイント）インターフェースの定義と管理
2. CycleState（サイクル状態）によるプラグイン間のデータ共有
3. NodeToStatus / NodeToStatusによるフィルタリング結果の効率的管理
4. PodsToActivateによる再キューイング対象Podの管理
5. Framework / Handle インターフェースの実装
6. プラグインの並列実行制御

**関連システム・外部連携**：kube-scheduler本体、スケジューリングプラグイン（in-tree/out-of-tree）、Extender

**権限による制御**：フレームワーク自体は権限管理を行わない。個別プラグインが必要なリソースアクセス権限を持つ。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | KubeSchedulerConfiguration | 設定 | スケジューラープロファイルでプラグイン有効化・無効化を設定 |

## 機能種別

フレームワーク / プラグインアーキテクチャ

## 入力仕様

### Extension Points一覧

| Extension Point | インターフェース | 実行タイミング | 説明 |
|----------------|----------------|---------------|------|
| PreEnqueue | PreEnqueuePlugin | キュー追加前 | キュー追加前のフィルタリング |
| PreFilter | PreFilterPlugin | フィルタリング前 | Pod固有の前処理・ノード候補絞り込み |
| Filter | FilterPlugin | フィルタリング | ノードがPodをホスト可能か判定 |
| PostFilter | PostFilterPlugin | フィルタリング後 | Preemption等のフォールバック処理 |
| PreScore | PreScorePlugin | スコアリング前 | スコアリング用の前処理 |
| Score | ScorePlugin | スコアリング | ノードのスコア計算 |
| Reserve | ReservePlugin | リソース予約 | スケジューリング成功時のリソース予約 |
| Permit | PermitPlugin | 許可判定 | 最終的なスケジューリング許可（待機可能） |
| PreBind | PreBindPlugin | バインド前 | バインド前の準備処理 |
| Bind | BindPlugin | バインド | 実際のPod-ノードバインディング |
| PostBind | PostBindPlugin | バインド後 | バインド後の後処理 |

### CycleState

| パラメータ名 | 型 | 説明 |
|-------------|-----|------|
| CycleState | fwk.CycleState | プラグイン間の状態共有ストア |
| PodsToActivate | *PodsToActivate | 再キューイング対象Podのマップ |

## 出力仕様

### NodeToStatus

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nodeToStatus | map[string]*fwk.Status | ノード名→ステータスのマップ |
| absentNodesStatus | *fwk.Status | マップに存在しないノードのデフォルトステータス |

### Status

| フィールド | 型 | 説明 |
|-----------|-----|------|
| Code | fwk.Code | Success, Error, Unschedulable, UnschedulableAndUnresolvable, Wait, Skip |
| Message | string | ステータスメッセージ |

## 処理フロー

### プラグイン実行フロー

```
1. PreFilter: 各PreFilterPluginを順次実行
   └─ PreFilterResult.NodeNamesで候補ノードを絞り込み可能
   └─ StatusがSkipの場合、対応するFilterをスキップ
2. Filter: 各FilterPluginを並列実行（ノードごと）
   └─ 各ノードに対してRunFilterPluginsを実行
   └─ UnschedulableAndUnresolvableはPreemptionでも解決不能を示す
3. PostFilter: フィルタリングで全ノード除外された場合に実行
   └─ 通常はDefaultPreemptionプラグインが実行
4. PreScore: 各PreScorePluginを順次実行
   └─ StatusがSkipの場合、対応するScoreをスキップ
5. Score: 各ScorePluginを並列実行（ノードごと）
   └─ NormalizeScoreで0-100に正規化
   └─ Weight（重み）を乗算
6. Reserve: 各ReservePluginを順次実行
   └─ 失敗時はUnreserveで巻き戻し
7. Permit: 各PermitPluginを順次実行
   └─ Wait可能（WaitOnPermitで待機）
   └─ タイムアウトでUnschedule扱い
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-39-01 | プラグインチェーン | Extension Pointごとにプラグインリストを順次実行する | 各フェーズ実行時 |
| BR-39-02 | Skip伝搬 | PreFilter/PreScoreがSkipを返した場合、対応するFilter/Scoreはスキップされる | PreFilter/PreScore実行後 |
| BR-39-03 | NodeToStatus最適化 | 全ノードが同一ステータスの場合、absentNodesStatusで一括管理する | フィルタリング結果管理時 |
| BR-39-04 | PodsToActivate | 再キューイング対象PodをCycleStateに格納し、サイクル終了時に活性化する | スケジューリング/バインディングサイクル成功時 |
| BR-39-05 | MaxNodeScore | スコアの最大値は100（fwk.MaxNodeScore） | スコアリング時 |

### 計算ロジック

- ノードスコア合計: `sum(plugin.Score(node) * plugin.Weight)` for all ScorePlugins
- NormalizeScore: 最大値/最小値に基づく0-100正規化

## データベース操作仕様

フレームワーク自体はデータベース操作を行わない。個別プラグインがAPI Serverへの操作を実行する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Unschedulable | フィルタ失敗 | ノードがPod要件を満たさない | 別ノードを試行、PostFilter実行 |
| UnschedulableAndUnresolvable | 解決不能 | Preemptionでも解決不能 | エラーステータスとして記録 |
| Error | 内部エラー | プラグイン実行エラー | スケジューリング失敗として処理 |
| Wait | Permit待機 | Permitプラグインが待機を要求 | タイムアウトまで待機 |

## パフォーマンス要件

- Filter/Scoreは並列実行（parallelismで制御）
- NodeToStatusのabsentNodesStatusにより、全ノード分のメモリ割り当てを回避
- CycleStateのRead/Writeは並行安全

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

- プラグインはHandleインターフェース経由でのみリソースアクセス可能
- CycleStateのデータはスケジューリングサイクル内でのみ有効

## 備考

- フレームワークインターフェースは`k8s.io/kube-scheduler/framework`パッケージで公開APIとして定義
- 内部実装は`pkg/scheduler/framework/`パッケージに配置
- QueueingHintによりイベント駆動の効率的な再キューイングを実現

---

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

### 推奨読解順序

#### Step 1: インターフェース定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | interface.go | `pkg/scheduler/framework/interface.go` | NodeToStatus構造体（32-38行目）、PodsToActivate（140-144行目） |

**読解のコツ**: `pkg/scheduler/framework/interface.go`はフレームワーク内部の補助型を定義。公開APIインターフェース（Plugin, FilterPlugin, ScorePlugin等）は`k8s.io/kube-scheduler/framework/interface.go`に定義されている。

#### Step 2: NodeToStatusの最適化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | interface.go | `pkg/scheduler/framework/interface.go` | NewDefaultNodeToStatus（42-44行目）、Get（55-60行目）、NodesForStatusCode（99-130行目） |

**主要処理**:
- **42-44行目**: デフォルトではabsentNodesStatus = UnschedulableAndUnresolvable
- **55-60行目**: Get()でマップにない場合はabsentNodesStatusを返す
- **99-130行目**: NodesForStatusCode()でabsentNodesStatusのコード一致時は全ノード列挙

#### Step 3: PodsToActivateの仕組みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | interface.go | `pkg/scheduler/framework/interface.go` | PodsToActivateKey（137行目）、PodsToActivate構造体（140-144行目） |

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

```
[Framework Runtime]
frameworkruntime.NewFramework
    ├─ プラグインレジストリからプラグインインスタンス化
    ├─ Extension Pointごとにプラグインリストを構築
    └─ Handle実装の提供

RunPreFilterPlugins
    └─ for each PreFilterPlugin: plugin.PreFilter()

RunFilterPlugins
    └─ for each FilterPlugin: plugin.Filter() [並列実行]

RunScorePlugins
    ├─ for each ScorePlugin: plugin.PreScore()
    └─ for each ScorePlugin: plugin.Score() [並列実行]
        └─ plugin.NormalizeScore()

RunReservePluginsReserve / RunReservePluginsUnreserve
RunPermitPlugins / WaitOnPermit
RunPreBindPlugins / RunBindPlugins / RunPostBindPlugins
```

### データフロー図

```
[入力]                      [フレームワーク]                     [出力]

Pod + Nodes  ──▶  CycleState                              ──▶  ScheduleResult
                      │
                  PreFilter ──▶ PreFilterResult
                      │         (NodeNames絞り込み)
                  Filter   ──▶ NodeToStatus
                      │         (各ノードの可否)
                  PostFilter ──▶ NominatingInfo
                      │          (Preemption)
                  Score    ──▶ NodeScoreList
                      │         (加重スコア)
                  Reserve  ──▶ リソース予約
                      │
                  Permit   ──▶ Allow/Wait/Deny
                      │
                  Bind     ──▶ Binding
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| interface.go | `pkg/scheduler/framework/interface.go` | ソース | 内部補助型定義（NodeToStatus等） |
| types.go | `pkg/scheduler/framework/types.go` | ソース | QueuedPodInfo等の型定義 |
| cycle_state.go | `pkg/scheduler/framework/cycle_state.go` | ソース | CycleState実装 |
| runtime/ | `pkg/scheduler/framework/runtime/` | ソース | Framework Runtime実装 |
| plugins/ | `pkg/scheduler/framework/plugins/` | ソース | ビルトインプラグイン群 |
| parallelize/ | `pkg/scheduler/framework/parallelize/` | ソース | 並列実行ユーティリティ |
| interface.go | `k8s.io/kube-scheduler/framework/interface.go` | 公開API | プラグインインターフェース定義 |
