# 機能設計書 149-Dynamic Resource Allocation

## 概要

本ドキュメントは、Kubernetes Dynamic Resource Allocation（DRA）フレームワークの設計について記述する。DRAはGPU、FPGA、SR-IOV NICなどのカスタムハードウェアリソースを動的に割り当てるための拡張可能なフレームワークを提供するライブラリである。

### 本機能の処理概要

**業務上の目的・背景**：従来のDevice Plugin APIでは、カスタムハードウェアリソースの割り当てに柔軟性が不足していた。DRAはResourceClaimリソースを通じて、リソースの要求・割り当て・準備・解放のライフサイクルを管理し、より複雑なリソース割り当てシナリオ（構造化パラメータ、Gang Scheduling等）をサポートする。

**機能の利用シーン**：GPUワークロードの実行時にResourceClaimを通じてGPUデバイスを要求する場合、FPGAアクセラレーターの動的割り当て、SR-IOV仮想ファンクションの割り当て、DRAドライバー（Kubelet側プラグイン）の開発時。

**主要な処理内容**：
1. ResourceClaim名前解決: PodResourceClaimからResourceClaim名を解決
2. ResourceClaim所有権検証: テンプレートから生成されたClaimのPod所有権を確認
3. Kubeletプラグインフレームワーク: DRAドライバーのKubelet側プラグイン実装を支援
4. ResourceSlice管理: ノード上の利用可能リソースの情報公開
5. デバイスToleration管理: デバイスに関するToleration処理
6. リーダーエレクション: DRAコントローラーのリーダーエレクション

**関連システム・外部連携**：Kubelet、API Server、DRAドライバー（外部プラグイン）、スケジューラー（DynamicResourcesプラグイン）

**権限による制御**：ResourceClaimはNamespaceスコープリソースであり、RBAC制御の対象。DRAドライバーはKubeletプラグインとして登録される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | kubectl get resourceclaims | 参照画面 | ResourceClaimの一覧表示 |
| - | kubectl describe resourceclaim | 参照画面 | ResourceClaimの詳細表示 |

## 機能種別

ライブラリ / フレームワーク / リソース管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| PodResourceClaim.ResourceClaimName | *string | No | 直接参照するResourceClaim名 | 有効な名前 |
| PodResourceClaim.ResourceClaimTemplateName | *string | No | テンプレートから生成するResourceClaim名 | 有効なテンプレート名 |
| DRAPlugin.PrepareResourceClaims | func | Yes | リソース準備コールバック | DRAPlugin実装 |
| DRAPlugin.UnprepareResourceClaims | func | Yes | リソース解放コールバック | DRAPlugin実装 |

### 入力データソース

- Pod.spec.resourceClaims（PodResourceClaim配列）
- Pod.status.resourceClaimStatuses（生成されたClaim名の参照）
- API Server（ResourceClaim、ResourceSlice等のリソース）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ResourceClaim名 | *string | 解決されたResourceClaim名 |
| mustCheckOwner | bool | 所有権チェックが必要かどうか |
| NodePrepareResourcesResponse | gRPC Response | デバイス準備結果 |
| ResourceSlice | ResourceSlice | ノード上の利用可能リソース情報 |

### 出力先

Kubelet（リソース準備結果）、API Server（ResourceSlice更新）。

## 処理フロー

### 処理シーケンス

```
1. Pod作成時にResourceClaimを要求
   └─ PodResourceClaimでResourceClaimを参照またはテンプレートから生成
2. ResourceClaim名の解決
   └─ resourceclaim.Name()でClaim名を取得
3. スケジューラーがResourceClaimの割り当てを実行
   └─ DynamicResourcesプラグインによるスケジューリング
4. Kubelet上でDRAプラグインがリソースを準備
   └─ NodePrepareResources gRPC呼び出し
5. Pod実行
   └─ 割り当てられたリソースを使用してコンテナを起動
6. Pod終了時にリソースを解放
   └─ NodeUnprepareResources gRPC呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[Pod作成] --> B{ResourceClaim参照方法}
    B -->|直接参照| C[ResourceClaimNameを使用]
    B -->|テンプレート| D[ResourceClaimStatusから名前を取得]
    C --> E[ResourceClaim取得]
    D --> F{Claim生成済み?}
    F -->|Yes| G[所有権チェック]
    F -->|No| H[ErrClaimNotFound]
    G --> E
    E --> I[スケジューラーによる割り当て]
    I --> J[DRAプラグイン.PrepareResourceClaims]
    J --> K[Pod実行]
    K --> L[DRAプラグイン.UnprepareResourceClaims]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-149-01 | Claim名解決 | ResourceClaimNameが指定されている場合はそれを直接使用、テンプレートの場合はStatusから取得 | ResourceClaim参照時 |
| BR-149-02 | 所有権検証 | テンプレートから生成されたClaimはOwnerReferenceでPod所有権を検証する必要がある | テンプレート使用時 |
| BR-149-03 | べき等性 | PrepareResourceClaimsはべき等でなければならない（Kubeletの再起動に対応） | DRAプラグイン実装 |
| BR-149-04 | デバイス排他性 | DRAドライバーは同じデバイスが複数のClaimに割り当てられていないことを検証すべき | PrepareResourceClaims時 |
| BR-149-05 | プラグインディレクトリ | KubeletPluginsDir=/var/lib/kubelet/plugins | DRAプラグイン登録時 |
| BR-149-06 | 登録ディレクトリ | KubeletRegistryDir=/var/lib/kubelet/plugins_registry | DRAプラグイン登録時 |

### 計算ロジック

ResourceClaim名の解決:
- ResourceClaimNameが非nil: そのまま使用（所有権チェック不要）
- ResourceClaimTemplateNameが非nil: Pod.Status.ResourceClaimStatusesから対応するClaim名を検索

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ResourceSlice更新 | etcd /registry/resourceslices/ | UPDATE | ノード上の利用可能リソース情報の更新 |
| ResourceClaim参照 | etcd /registry/resourceclaims/{ns}/{name} | SELECT | ResourceClaimの取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrAPIUnsupported | ResourceClaimNameもResourceClaimTemplateNameも未設定 | PodResourceClaim定義を修正 |
| - | ErrClaimNotFound | テンプレートからのClaim生成がまだ完了していない | Claimの生成を待つ |
| - | OwnershipError | Claimの所有者がPodと一致しない | Claim参照を確認 |

### リトライ仕様

Kubelet側でPodの同期ループにより自動的に再試行される。

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

ResourceClaimの割り当てはAPI Serverの楽観的並行制御に基づく。DRAプラグインのPrepare/Unprepareはべき等性により一貫性を保証。

## パフォーマンス要件

DRAプラグインのPrepareResourceClaims呼び出しはPodの起動遅延に直接影響するため、低レイテンシが求められる。

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

- DRAプラグインはKubeletプラグインディレクトリへのアクセスが必要（root権限）
- ResourceClaimのNamespaceスコーピングによりマルチテナント環境でのリソース隔離を実現
- デバイス排他性チェックによる不正なリソース共有の防止

## 備考

- DRAは`staging/src/k8s.io/dynamic-resource-allocation`に格納
- kubeletpluginパッケージはDRAドライバー開発者向けのヘルパーライブラリを提供
- gRPCシリアライゼーション、ログ出力、リクエストID付与などの横断的関心事が自動処理される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | resourceclaim.go | `staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim.go` | ResourceClaim名前解決ロジック |

**読解のコツ**: Name()関数の3つの戻り値パターン（エラー、nil名前、名前+所有権チェックフラグ）に注目。switch文でResourceClaimNameとResourceClaimTemplateNameを分岐している。

**主要処理フロー**:
- **37-45行目**: ErrAPIUnsupported, ErrClaimNotFound定数定義
- **65-79行目**: Name()関数 -- PodResourceClaimからResourceClaim名を解決
- **67-68行目**: ResourceClaimNameが設定されている場合 -- 直接返却、所有権チェック不要
- **69-75行目**: ResourceClaimTemplateNameの場合 -- StatusからClaim名を検索
- **76-78行目**: どちらも未設定 -- ErrAPIUnsupported

#### Step 2: Kubeletプラグインフレームワークを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | draplugin.go | `staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go` | DRAPluginインターフェースとKubeletプラグイン登録 |

**主要処理フロー**:
- **46-51行目**: KubeletPluginsDir, KubeletRegistryDir定数
- **56-80行目**: DRAPluginインターフェース -- PrepareResourceClaims, UnprepareResourceClaims

#### Step 3: ResourceSlice管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | resourceslice/ | `staging/src/k8s.io/dynamic-resource-allocation/resourceslice/` | ResourceSlice情報の公開 |

#### Step 4: デバイスToleration管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | devicetoleration.go | `staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/devicetoleration.go` | デバイスToleration処理 |

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

```
Kubelet / スケジューラー
    |
    +-- resourceclaim.Name(pod, podClaim) → (*string, bool, error)
    |       +-- ResourceClaimName参照
    |       +-- ResourceClaimTemplateName → Status検索
    |
    +-- kubeletplugin.Start(driverName, plugin, opts...)
    |       +-- gRPCサーバー起動
    |       +-- Kubelet Plugin Registration
    |       |
    |       +-- DRAPlugin.PrepareResourceClaims(ctx, claims)
    |       +-- DRAPlugin.UnprepareResourceClaims(ctx, claims)
    |
    +-- resourceslice.Controller
    |       +-- ResourceSliceのAPI Server同期
    |
    +-- resourceclaim.IsForPod(pod, claim) → bool
            +-- OwnerReference検証
```

### データフロー図

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

Pod Spec ──────> resourceclaim.Name() ──> ResourceClaim名 ──> API Server
(PodResourceClaim)                                              (Claim取得)
                                                                    |
Scheduler ──────────> DRA割り当て ──────────────────> ResourceClaim更新
                                                                    |
Kubelet ──────────> DRAPlugin.PrepareResourceClaims ──> デバイス準備
                                                                    |
                    DRAPlugin.UnprepareResourceClaims ──> デバイス解放
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| resourceclaim.go | `staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/resourceclaim.go` | ソース | ResourceClaim名前解決 |
| pod.go | `staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/pod.go` | ソース | Pod関連ユーティリティ |
| devicetoleration.go | `staging/src/k8s.io/dynamic-resource-allocation/resourceclaim/devicetoleration.go` | ソース | デバイスToleration |
| draplugin.go | `staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go` | ソース | DRAPluginインターフェース |
| endpoint.go | `staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/endpoint.go` | ソース | gRPCエンドポイント |
| noderegistrar.go | `staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/noderegistrar.go` | ソース | ノード登録 |
| registrationserver.go | `staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/registrationserver.go` | ソース | 登録サーバー |
| resourceslice/ | `staging/src/k8s.io/dynamic-resource-allocation/resourceslice/` | ソース | ResourceSlice管理 |
| structured/ | `staging/src/k8s.io/dynamic-resource-allocation/structured/` | ソース | 構造化パラメータ |
| leaderelection/ | `staging/src/k8s.io/dynamic-resource-allocation/leaderelection/` | ソース | リーダーエレクション |
