# 機能設計書 67-プラグイン管理

## 概要

本ドキュメントは、Kubeletにおけるプラグインの動的検出・登録・解除を管理するPlugin Manager機能の設計を記述する。

### 本機能の処理概要

Plugin Managerは、Kubeletプラグイン（CSI Driver、Device Pluginなど）の動的な登録・解除を管理するコンポーネントである。Unixソケットベースのプラグイン検出機構（Plugin Watcher）と、Desired/Actual State of Worldモデルに基づくReconcilerで構成される。

**業務上の目的・背景**：Kubernetesではストレージドライバ（CSI）やデバイスプラグインなど、ノードレベルのプラグインを動的に登録・管理する必要がある。Plugin Managerは、プラグインがUnixソケットを通じて自動的に検出・登録される仕組みを提供し、手動設定を不要にする。

**機能の利用シーン**：(1) CSI Driverのノードプラグイン登録、(2) Device Pluginの登録、(3) プラグインの動的なアンインストール検出。

**主要な処理内容**：
1. Plugin Watcher（Desired State of World Populator）がソケットディレクトリを監視し、新しいプラグインソケットを検出する
2. 検出されたプラグインをDesired State of Worldに登録する
3. Reconcilerが1秒間隔でDesired StateとActual Stateの差分を検出し、登録・解除操作を実行する
4. OperationExecutorがプラグインタイプ別のHandlerを呼び出して実際の登録・解除を行う

**関連システム・外部連携**：CSI Node Driver、Device Plugin、ファイルシステム（Unixソケット監視）。

**権限による制御**：プラグインソケットへのアクセスはファイルシステムパーミッションで制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はCLI画面との直接的な関連はなく、Kubelet内部コンポーネントとして動作する |

## 機能種別

プラグイン管理（動的検出・登録・解除）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sockDir | string | Yes | プラグインソケットの監視ディレクトリ | 有効なディレクトリパス |
| recorder | record.EventRecorder | Yes | イベント記録インターフェース | - |
| pluginType | string | Yes (AddHandler) | プラグインタイプ（例："CSIPlugin"） | - |
| pluginHandler | cache.PluginHandler | Yes (AddHandler) | プラグインタイプ別のハンドラ | - |

### 入力データソース

- ファイルシステム: ソケットディレクトリ内のUnixソケットファイル
- プラグインgRPC API: GetInfo()によるプラグイン情報取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| プラグイン登録 | cache.ActualStateOfWorld | 登録済みプラグインの実際の状態 |
| イベント | v1.Event | プラグイン登録/解除イベント |
| メトリクス | Prometheus形式 | プラグイン登録状態メトリクス |

### 出力先

- Actual State of World: 登録済みプラグインの管理
- Kubernetes Events: プラグイン登録/解除のイベント記録
- メトリクスエンドポイント: プラグイン管理メトリクス

## 処理フロー

### 処理シーケンス

```
1. Plugin Manager初期化 (NewPluginManager)
   └─ ActualStateOfWorld/DesiredStateOfWorld作成 → Reconciler/Watcher初期化
2. Run開始
   └─ Plugin Watcher起動 → Reconciler起動 → メトリクス登録
3. Plugin Watcher（ソケット監視）
   └─ fsnotify/定期スキャンでソケットファイルを検出 → DesiredStateOfWorldに登録
4. Reconciler（1秒間隔ループ）
   └─ Desired vs Actual差分検出 → OperationExecutor経由で登録/解除
```

### フローチャート

```mermaid
flowchart TD
    A[Plugin Manager起動] --> B[Plugin Watcher起動]
    A --> C[Reconciler起動]
    B --> D[ソケットディレクトリ監視]
    D --> E{新ソケット検出?}
    E -->|Yes| F[DesiredStateOfWorld登録]
    E -->|No| D
    C --> G[1秒間隔ループ]
    G --> H{Desired != Actual?}
    H -->|No| G
    H -->|登録必要| I[OperationExecutor.RegisterPlugin]
    H -->|解除必要| J[OperationExecutor.UnregisterPlugin]
    I --> K[Handler.RegisterPlugin]
    J --> L[Handler.DeRegisterPlugin]
    K --> M[ActualStateOfWorld更新]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-67-01 | Reconciler間隔 | ReconcilerはloopSleepDuration（1秒）間隔で実行される | 常時 |
| BR-67-02 | プラグインタイプ別Handler | 各プラグインタイプに対して専用のHandlerが登録される | AddHandler呼び出し時 |
| BR-67-03 | Desired/Actual State モデル | プラグインの目標状態と実際の状態を分離して管理する | 常時 |

### 計算ロジック

- Reconciler間隔: `loopSleepDuration = 1 * time.Second`

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

本機能はデータベースを直接操作しない。内部のキャッシュ（ActualStateOfWorld/DesiredStateOfWorld）で状態を管理する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Watcher起動エラー | ソケットディレクトリ監視の初期化失敗 | エラーログ出力しPlugin Manager起動中断 |
| - | 登録エラー | プラグインのgRPC接続/GetInfo失敗 | エラーログ出力、次回Reconcilerサイクルでリトライ |
| - | 解除エラー | プラグイン解除処理の失敗 | エラーログ出力、次回Reconcilerサイクルでリトライ |

### リトライ仕様

Reconcilerは1秒間隔で継続的に実行されるため、登録/解除の失敗は次サイクルで自動リトライされる。

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

該当なし。ActualStateOfWorldとDesiredStateOfWorldはin-memoryキャッシュで管理される。

## パフォーマンス要件

- Reconciler間隔1秒で低レイテンシのプラグイン検出を実現
- fsnotifyによるイベント駆動の検出で定期スキャンの負荷を軽減

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

- プラグインソケットはファイルシステムパーミッションで保護
- プラグインのgRPC通信はUnixソケット（ローカル通信）のみ

## 備考

- Desired/Actual State of WorldパターンはVolume Managerと同様のアーキテクチャ
- メトリクスはActualStateOfWorldとDesiredStateOfWorldの両方から収集される

---

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

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

### 推奨読解順序

#### Step 1: インターフェースとデータ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | plugin_manager.go | `pkg/kubelet/pluginmanager/plugin_manager.go` | PluginManagerインターフェース（36-45行目）: Run/AddHandlerの公開API |
| 1-2 | plugin_manager.go | `pkg/kubelet/pluginmanager/plugin_manager.go` | pluginManager構造体（84-105行目）: 内部状態定義 |
| 1-3 | types.go | `pkg/kubelet/pluginmanager/cache/types.go` | PluginHandlerインターフェース: プラグインタイプ別ハンドラ |

**読解のコツ**: desiredStateOfWorldPopulatorがPlugin Watcher、reconcilerがReconcilerに対応する。Actual/Desired State of Worldパターンは、「あるべき姿」と「現在の姿」の差分をReconcilerが解消するデザインパターンである。

#### Step 2: 初期化と起動を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | plugin_manager.go | `pkg/kubelet/pluginmanager/plugin_manager.go` | NewPluginManager（55-81行目）: 初期化処理 |
| 2-2 | plugin_manager.go | `pkg/kubelet/pluginmanager/plugin_manager.go` | Run（109-127行目）: 起動シーケンス |

**主要処理フロー**:
- **58-59行目**: ActualStateOfWorldとDesiredStateOfWorldの作成
- **60-69行目**: Reconciler（OperationExecutor, OperationGenerator含む）の初期化
- **72-76行目**: Plugin Watcher（desiredStateOfWorldPopulator）の初期化
- **114行目**: Plugin Watcher起動
- **122行目**: Reconciler起動
- **124行目**: メトリクス登録

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

```
PluginManager
    │
    ├─ Run()
    │      ├─ desiredStateOfWorldPopulator.Start() [Plugin Watcher]
    │      │      └─ fsnotify/定期スキャン → DesiredStateOfWorld更新
    │      │
    │      ├─ reconciler.Run()
    │      │      └─ 1秒間隔ループ
    │      │             ├─ Desired - Actual → RegisterPlugin
    │      │             │      └─ OperationExecutor
    │      │             │             └─ OperationGenerator
    │      │             │                    └─ Handler.RegisterPlugin()
    │      │             └─ Actual - Desired → UnregisterPlugin
    │      │                    └─ OperationExecutor
    │      │                           └─ OperationGenerator
    │      │                                  └─ Handler.DeRegisterPlugin()
    │      │
    │      └─ metrics.Register()
    │
    └─ AddHandler()
           └─ reconciler.AddHandler(pluginType, handler)
```

### データフロー図

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

Unixソケットファイル ──▶ Plugin Watcher ──────────▶ DesiredStateOfWorld
                              │
DesiredState差分 ─────▶ Reconciler ──────────────▶ OperationExecutor
                              │
プラグインgRPC GetInfo ▶ OperationGenerator ──────▶ Handler.RegisterPlugin()
                              │
Handler結果 ──────────▶ ActualStateOfWorld更新 ───▶ メトリクス/イベント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| plugin_manager.go | `pkg/kubelet/pluginmanager/plugin_manager.go` | ソース | PluginManager中核実装 |
| cache/types.go | `pkg/kubelet/pluginmanager/cache/types.go` | ソース | キャッシュインターフェース定義 |
| cache/actual_state_of_world.go | `pkg/kubelet/pluginmanager/cache/actual_state_of_world.go` | ソース | 実際の状態キャッシュ |
| cache/desired_state_of_world.go | `pkg/kubelet/pluginmanager/cache/desired_state_of_world.go` | ソース | 目標状態キャッシュ |
| pluginwatcher/plugin_watcher.go | `pkg/kubelet/pluginmanager/pluginwatcher/plugin_watcher.go` | ソース | プラグインソケット監視 |
| reconciler/reconciler.go | `pkg/kubelet/pluginmanager/reconciler/reconciler.go` | ソース | 状態一致化ループ |
| operationexecutor/ | `pkg/kubelet/pluginmanager/operationexecutor/` | ソース | 登録/解除操作の実行 |
| metrics/ | `pkg/kubelet/pluginmanager/metrics/` | ソース | プラグイン管理メトリクス |
