# 機能設計書 55-デバイス管理

## 概要

本ドキュメントは、KubeletのDevice Pluginフレームワークを通じたGPU等のハードウェアデバイスの管理機能の設計を記載する。

### 本機能の処理概要

Kubeletのデバイス管理機能は、Device Plugin APIを通じてノード上のハードウェアデバイス（GPU、FPGA、SR-IOV NIC等）を検出・管理し、Podへの割り当てを制御する。デバイスプラグインは独立したプロセスとして動作し、gRPCでKubeletと通信してデバイスのライフサイクルを管理する。

**業務上の目的・背景**：Kubernetesクラスターでは、汎用CPU/メモリだけでなくGPU等の特殊ハードウェアリソースを管理する必要がある。Device Pluginフレームワークにより、ベンダー固有のデバイスドライバーをKubernetesの標準リソース管理に統合し、スケジューラーによる適切なデバイス割り当てとPodへのデバイスマッピングを実現する。

**機能の利用シーン**：GPU計算ワークロードの実行、FPGAアクセラレーターの利用、SR-IOVネットワークインターフェースの割り当て、カスタムハードウェアリソースの管理。

**主要な処理内容**：
1. デバイスプラグインの登録とgRPCサーバーの管理
2. デバイスの健全性監視（Healthy/Unhealthy状態追跡）
3. Pod作成時のデバイス割り当て（Allocate RPC呼び出し）
4. デバイスのNUMAトポロジーヒント提供（TopologyManager連携）
5. チェックポイントによる割り当て状態の永続化
6. Reconcileループによる割り当て状態の整合性維持

**関連システム・外部連携**：Device Plugin（gRPC API）、TopologyManager（NUMAアフィニティ）、Kubelet Plugin Manager（プラグイン登録）。

**権限による制御**：デバイスリソースはPodのresources.requestsで指定し、スケジューラーがノードの空きデバイス数に基づいてスケジューリングする。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Kubelet内部機能のため画面関連なし |

## 機能種別

リソース管理 / デバイス連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| resourceName | string | Yes | デバイスリソース名（例: nvidia.com/gpu） | 拡張リソース名形式 |
| deviceIDs | []string | Yes | 割り当てるデバイスID一覧 | プラグイン登録済みのID |

### 入力データソース

- Device Plugin: ListAndWatch RPCによるデバイス一覧と状態
- Pod仕様: コンテナのresources.requests/limitsでのデバイスリソース指定
- チェックポイントファイル: 前回の割り当て状態

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| AllocateResponse | *pluginapi.AllocateResponse | デバイス割り当て結果（envs、mounts、devices、annotations） |
| TopologyHints | map[string][]TopologyHint | デバイスのNUMAアフィニティヒント |
| Node.Status.Capacity | v1.ResourceList | ノードのデバイスリソース容量 |

### 出力先

- コンテナ仕様（環境変数、デバイスマウント、cgroup devices設定）
- ノードステータス（デバイスリソース容量・割り当て可能量）
- チェックポイントファイル

## 処理フロー

### 処理シーケンス

```
1. デバイスプラグイン登録
   └─ Plugin Managerからの通知でgRPCエンドポイント確立
2. デバイス検出・監視（ListAndWatch）
   └─ プラグインからのストリーミングRPCでデバイス状態追跡
3. Pod Admission時のデバイス割り当て
   └─ 空きデバイス選択 → Allocate RPC → 結果キャッシュ
4. コンテナ起動時のデバイスマッピング
   └─ Allocate結果に基づくenvs/mounts/devicesの設定
5. Reconcileループ
   └─ 割り当て済みデバイスの整合性確認
6. コンテナ削除時のデバイス解放
```

### フローチャート

```mermaid
flowchart TD
    A[Device Plugin起動] --> B[Register RPC]
    B --> C[Kubelet: エンドポイント確立]
    C --> D[ListAndWatch RPC開始]
    D --> E[デバイス一覧受信]
    E --> F[Healthy/Unhealthy追跡]
    F --> G[ノードCapacity更新]

    H[Pod作成] --> I{デバイスリソース要求?}
    I -->|Yes| J[空きデバイス選択]
    J --> K[Allocate RPC]
    K --> L[結果キャッシュ]
    L --> M[チェックポイント保存]
    M --> N[コンテナ起動時適用]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-01 | デバイス排他割り当て | デバイスは1つのコンテナにのみ割り当てられる | Allocate時 |
| BR-55-02 | Unhealthyデバイス除外 | Unhealthy状態のデバイスは新規割り当て対象外 | Allocate時 |
| BR-55-03 | チェックポイント復元 | Kubelet再起動時に前回の割り当て状態を復元 | Kubelet起動時 |
| BR-55-04 | NUMA親和性 | TopologyManager連携時、NUMAノードに基づくデバイス選択 | TopologyManager有効時 |
| BR-55-05 | Capacity更新 | デバイスの登録/削除時にノードCapacityを更新 | デバイス状態変更時 |

### 計算ロジック

- 割り当て可能デバイス数 = Healthy デバイス数 - 割り当て済みデバイス数

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 割り当て状態 | checkpoint（ファイル） | INSERT/UPDATE | デバイス割り当てのチェックポイント |
| デバイス追跡 | allDevices（インメモリ） | INSERT/UPDATE/DELETE | 全デバイスの状態追跡 |
| Pod割り当て | podDevices（インメモリ） | INSERT/DELETE | Pod → デバイスのマッピング |

### テーブル別操作詳細

#### podDevices（インメモリ）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | podUID → containerName → resourceName → deviceIDs | Allocate結果 | デバイス割り当て時 |
| DELETE | podUID | Pod削除時 | コンテナ削除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| PluginNotRegistered | 設定エラー | 要求リソースのプラグイン未登録 | デバイスプラグインの起動を確認 |
| InsufficientDevices | リソース不足 | 空きデバイス不足 | ノードのデバイス数を確認 |
| AllocateError | プラグインエラー | Allocate RPC失敗 | デバイスプラグインのログを確認 |
| CheckpointError | 状態エラー | チェックポイント読み書き失敗 | ファイルシステム権限を確認 |

### リトライ仕様

- ListAndWatch RPC切断時は自動再接続
- Allocate失敗時はPod Admissionで拒否、再スケジューリング

## トランザクション仕様

ManagerImplはsync.Mutexで排他制御。チェックポイントへの書き込みは割り当て状態変更ごとに実行。

## パフォーマンス要件

- ListAndWatch はストリーミングRPCで低レイテンシーのデバイス状態更新
- Reconcileループで定期的な整合性確認

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

- Device Plugin APIはUnix Domainソケットで通信（ノードローカル）
- デバイスのcgroupアクセス制御により、コンテナから割り当てられたデバイスのみアクセス可能

## 備考

- Device Plugin APIはv1beta1（安定前のAPI）
- PreferredAllocationメソッドにより、プラグインが好ましいデバイス選択を提案可能
- nodeWithoutTopology = -1 はNUMAトポロジー情報がないデバイスを示す

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `pkg/kubelet/cm/devicemanager/types.go` | デバイス管理のインターフェース定義 |
| 1-2 | manager.go | `pkg/kubelet/cm/devicemanager/manager.go` | ManagerImpl構造体、主要フィールド |

**読解のコツ**: ManagerImplはendpoints map（リソース名 → エンドポイント情報）、allDevices（全デバイス状態）、healthyDevices/unhealthyDevices（状態別デバイス）、podDevices（Pod割り当て）など複数のmapを持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | manager.go | `pkg/kubelet/cm/devicemanager/manager.go` | ManagerImpl構造体のメソッド群 |

**主要処理フロー**:
- **62-100行目**: ManagerImpl構造体 - 主要フィールド（endpoints、allDevices、healthyDevices等）
- **56行目**: nodeWithoutTopology = -1 定数

#### Step 3: エンドポイント管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | endpoint.go | `pkg/kubelet/cm/devicemanager/endpoint.go` | デバイスプラグインとのgRPC通信 |

#### Step 4: トポロジーヒントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | topology_hints.go | `pkg/kubelet/cm/devicemanager/topology_hints.go` | TopologyManagerへのヒント提供 |

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

```
Kubelet
    |
    +-- PluginManager
    |       +-- DeviceManager.PluginConnected()
    |               +-- endpoint.ListAndWatch() [gRPC streaming]
    |
    +-- DeviceManager.Allocate()
    |       +-- endpoint.Allocate() [gRPC unary]
    |       +-- podDevices.insert()
    |       +-- writeCheckpoint()
    |
    +-- DeviceManager.GetTopologyHints()
    |       +-- NUMAアフィニティ計算
    |
    +-- DeviceManager.GetDeviceRunContainerOptions()
            +-- Allocate結果からenvs/mounts/devices取得
```

### データフロー図

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

Device Plugin          ──▶  ListAndWatch()        ──▶  healthyDevices/unhealthyDevices
(gRPC streaming)                                        Node.Status.Capacity

Pod仕様               ──▶  Allocate()            ──▶  AllocateResponse
(resources.requests)        |                           (envs/mounts/devices)
                            v
                      endpoint.Allocate() [gRPC]  ──▶  チェックポイント保存
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| manager.go | `pkg/kubelet/cm/devicemanager/manager.go` | ソース | デバイスマネージャー主実装 |
| endpoint.go | `pkg/kubelet/cm/devicemanager/endpoint.go` | ソース | デバイスプラグインとのgRPC通信 |
| types.go | `pkg/kubelet/cm/devicemanager/types.go` | ソース | インターフェース・型定義 |
| pod_devices.go | `pkg/kubelet/cm/devicemanager/pod_devices.go` | ソース | Pod-デバイスマッピング管理 |
| topology_hints.go | `pkg/kubelet/cm/devicemanager/topology_hints.go` | ソース | TopologyManagerヒント |
| checkpoint/ | `pkg/kubelet/cm/devicemanager/checkpoint/` | ソース | チェックポイント管理 |
| plugin/ | `pkg/kubelet/cm/devicemanager/plugin/` | ソース | プラグインサーバー実装 |
