# 機能設計書 142-PersistentVolumeClaim管理

## 概要

本ドキュメントは、KubernetesにおけるPersistentVolumeClaim（PVC）リソースのレジストリ層での管理機能について記述する。PVCの作成、取得、更新、削除およびステータス管理のREST APIエンドポイントの設計を対象とする。

### 本機能の処理概要

**業務上の目的・背景**：PersistentVolumeClaimはユーザーがストレージを要求するためのNamespaceスコープのリソースである。PVCを通じてユーザーはPersistentVolumeにバインドされた永続ストレージを取得し、Podにマウントして利用する。動的プロビジョニングにおいてはPVCの作成がトリガーとなりPVが自動作成される。

**機能の利用シーン**：ユーザーがアプリケーションに永続ストレージを提供する際にPVCを作成する。StatefulSetではPVCテンプレートを用いて各レプリカに固有のストレージを提供する。ボリューム拡張時にはPVCのリソースリクエストを増やすことでストレージのリサイズが行われる。

**主要な処理内容**：
1. PVCリソースのCRUD操作をREST APIとして提供（etcdストレージへの永続化）
2. 作成時のステータス初期化とDataSource正規化（dataSource/dataSourceRefの同期）
3. 更新時のSpec/Statusフィールド分離保護
4. DataSourceの後方互換性処理（KEP 1495準拠）
5. 読み取り時のデフォルト値設定（defaultOnRead）
6. バリデーションの実行（PVCスペックの検証）

**関連システム・外部連携**：PVコントローラー（PV-PVCバインディング）、CSIドライバー（動的プロビジョニング/ボリューム拡張）、StatefulSetコントローラー（PVCテンプレート）、API Server

**権限による制御**：PVCはNamespaceスコープのリソースであり、Namespace内のRole/RoleBindingにより操作制限が行われる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | kubectl get pvc | 参照画面 | PVCリソースの一覧取得・詳細表示 |
| - | kubectl create/apply | 操作画面 | PVCリソースの作成・更新 |

## 機能種別

CRUD操作 / リソースライフサイクル管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| metadata.name | string | Yes | PVC名（Namespace内で一意） | DNS Subdomain Name形式 |
| metadata.namespace | string | Yes | PVCが属するNamespace | 有効なNamespace名 |
| spec.accessModes | []PersistentVolumeAccessMode | Yes | アクセスモード（RWO/ROX/RWX） | 有効なアクセスモード値 |
| spec.resources.requests.storage | Quantity | Yes | 要求するストレージ容量 | 正の値 |
| spec.storageClassName | *string | No | ストレージクラス名 | 存在するStorageClassを参照 |
| spec.volumeMode | *PersistentVolumeMode | No | ボリュームモード（Filesystem/Block） | 有効なモード値 |
| spec.volumeName | string | No | 特定PVへのバインド指定 | 存在するPV名 |
| spec.selector | *LabelSelector | No | PVをラベルで選択 | 有効なラベルセレクタ |
| spec.dataSource | *TypedLocalObjectReference | No | データソース（VolumeSnapshot/PVC） | 有効な参照 |
| spec.dataSourceRef | *TypedObjectReference | No | データソース参照（拡張版） | 有効な参照 |

### 入力データソース

API ServerへのHTTPリクエスト（REST API）。PVCマニフェスト（YAML/JSON）がリクエストボディとして送信される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| metadata | ObjectMeta | リソースメタデータ |
| spec | PersistentVolumeClaimSpec | PVCのスペック情報 |
| status.phase | PersistentVolumeClaimPhase | PVCのフェーズ（Pending/Bound/Lost） |
| status.accessModes | []PersistentVolumeAccessMode | バインドされたPVのアクセスモード |
| status.capacity | ResourceList | バインドされたPVの実容量 |
| status.conditions | []PersistentVolumeClaimCondition | PVCの状態条件 |

### 出力先

etcdストレージへの永続化、APIレスポンスとしてクライアントに返却。

## 処理フロー

### 処理シーケンス

```
1. REST APIリクエスト受信
   └─ API ServerがHTTPリクエストを受け付け、認証・認可を通過
2. リソースオブジェクトのデシリアライズ
   └─ リクエストボディをPersistentVolumeClaimオブジェクトに変換
3. PrepareForCreate / PrepareForUpdate実行
   └─ 作成時: Status初期化、DataSource正規化
   └─ 更新時: Status保護、DataSource正規化
   └─ フィーチャーゲートに基づく無効フィールドのドロップ
4. バリデーション実行
   └─ PVC固有バリデーション
5. etcdへの永続化
   └─ genericregistry.Storeを通じてetcdに保存
6. レスポンス返却（読み取り時にdefaultOnRead適用）
```

### フローチャート

```mermaid
flowchart TD
    A[REST APIリクエスト受信] --> B{操作種別}
    B -->|Create| C[PrepareForCreate]
    B -->|Update| D[PrepareForUpdate]
    B -->|Status Update| E[Status PrepareForUpdate]
    B -->|Read| F[Get/List]
    C --> G[Status初期化]
    G --> H[DropDisabledFields]
    H --> I[EnforceDataSourceBackwardsCompatibility]
    I --> J[NormalizeDataSources]
    J --> K[Validate]
    K --> L[etcdへ永続化]
    D --> M[Status復元]
    M --> N[DropDisabledFields]
    N --> O[DataSource正規化]
    O --> P[ValidateUpdate]
    P --> L
    E --> Q[Spec復元]
    Q --> R[DropDisabledFieldsFromStatus]
    R --> S[ValidateStatusUpdate]
    S --> L
    F --> T[etcdから取得]
    T --> U[defaultOnRead]
    U --> V[NormalizeDataSources]
    V --> W[レスポンス返却]
    L --> W
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-142-01 | NamespaceScoped=true | PVCはNamespaceスコープリソースである | 常時 |
| BR-142-02 | Status保護（作成時） | 作成時にユーザー指定のStatusはリセットされる | PVC作成時 |
| BR-142-03 | DataSource正規化 | dataSourceとdataSourceRefが一方のみ設定されている場合、もう一方に自動コピーされる | 作成・更新・読み取り時 |
| BR-142-04 | DataSource後方互換性 | PVC/VolumeSnapshot以外の不正なdataSource値はドロップされる（KEP 1495） | 作成・更新時 |
| BR-142-05 | 読み取り時デフォルト設定 | 古いバージョンで保存されたPVCの読み取り時にdataSourceRefの自動補完が行われる | PVC読み取り時 |
| BR-142-06 | Status保護（更新時） | Spec更新APIではStatusフィールドは旧オブジェクトの値が維持される | PVCのSpec更新時 |
| BR-142-07 | Spec保護（ステータス更新時） | ステータス更新APIではSpecフィールドは旧オブジェクトの値が維持される | PVCのStatus更新時 |
| BR-142-08 | 無条件更新許可 | AllowUnconditionalUpdate=trueである | PVC更新時 |

### 計算ロジック

DataSource正規化ロジック（NormalizeDataSources）:
- dataSourceがnil, dataSourceRefが非nil: dataSourceRef -> dataSourceにコピー（互換性のあるフィールドのみ）
- dataSourceが非nil, dataSourceRefがnil: dataSource -> dataSourceRefにコピー

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| PVC作成 | etcd /registry/persistentvolumeclaims/{ns}/{name} | INSERT | PVCオブジェクトの新規作成 |
| PVC取得 | etcd /registry/persistentvolumeclaims/{ns}/{name} | SELECT | PVCオブジェクトの取得 |
| PVC一覧 | etcd /registry/persistentvolumeclaims/{ns}/ | SELECT | PVCオブジェクト一覧の取得 |
| PVC更新 | etcd /registry/persistentvolumeclaims/{ns}/{name} | UPDATE | PVCオブジェクトのSpec更新 |
| PVCステータス更新 | etcd /registry/persistentvolumeclaims/{ns}/{name} | UPDATE | PVCオブジェクトのStatus更新 |
| PVC削除 | etcd /registry/persistentvolumeclaims/{ns}/{name} | DELETE | PVCオブジェクトの削除 |

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

#### etcd: persistentvolumeclaims

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | 全フィールド | PrepareForCreate後のオブジェクト | Status=空、DataSource正規化済み |
| UPDATE (spec) | spec.* | 新しいSpec、Status=旧Status | DataSource正規化済み |
| UPDATE (status) | status.* | 新しいStatus、Spec=旧Spec | Spec変更不可 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | BadRequest | バリデーションエラー | エラーメッセージに基づきマニフェストを修正 |
| 404 | NotFound | 指定PVCが存在しない | PVC名とNamespaceを確認 |
| 409 | Conflict | resourceVersionの競合 | 最新を取得して再試行 |
| 422 | UnprocessableEntity | 更新時のバリデーションエラー | エラー内容に基づき修正 |

### リトライ仕様

resourceVersion競合（409）の場合、クライアント側でGet -> Modify -> Updateのパターンで再試行する。

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

etcdの楽観的並行制御（Optimistic Concurrency Control）に基づく。resourceVersionフィールドによりCAS操作が行われる。

## パフォーマンス要件

API Serverのレスポンス時間に準拠。単一オブジェクト操作は数ミリ秒以内、大量のPVCリスト取得時はページネーションの利用を推奨。

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

- PVCはNamespaceスコープであり、RBAC Role/RoleBindingによるNamespace単位のアクセス制御が可能
- dataSource/dataSourceRefにより他のPVCやVolumeSnapshotのデータクローンが可能であるため、ソースリソースへのアクセス権限確認が必要
- PVCの削除はバインド中のPVに影響するため、FinalizerによるProtectionが適用される

## 備考

- PVCの短縮名は「pvc」であり、`kubectl get pvc`で一覧取得可能
- defaultOnRead機能により、古いバージョンで保存されたPVCも最新のAPI仕様に準拠した形で返却される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `pkg/apis/core/types.go` | PersistentVolumeClaim, PersistentVolumeClaimSpec, PersistentVolumeClaimStatus構造体 |

**読解のコツ**: dataSourceとdataSourceRefの2つのフィールドの関係に注目。KEP 1495により、dataSourceRefが拡張版として導入され、後方互換性のために両方が維持されている。

#### Step 2: ストラテジーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | strategy.go | `pkg/registry/core/persistentvolumeclaim/strategy.go` | PVCのCRUD操作に関するストラテジーの全体像 |

**主要処理フロー**:
1. **39-46行目**: Strategy構造体と変数の定義
2. **48-50行目**: NamespaceScoped()=true -- PVCはNamespaceスコープ
3. **65-79行目**: PrepareForCreate -- Status初期化、DropDisabledFields、DataSource正規化
4. **70-78行目**: DataSource処理 -- EnforceDataSourceBackwardsCompatibility, NormalizeDataSources
5. **101-119行目**: PrepareForUpdate -- Status保護、DataSource正規化（新旧両方）
6. **137-161行目**: StatusStrategy -- ステータスサブリソースのストラテジー
7. **156-161行目**: StatusStrategy.PrepareForUpdate -- Spec保護、DropDisabledFieldsFromStatus

#### Step 3: RESTストレージを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | storage.go | `pkg/registry/core/persistentvolumeclaim/storage/storage.go` | REST/StatusREST構造体、defaultOnRead機能 |

**主要処理フロー**:
- **42-71行目**: NewREST関数 -- Store設定、statusStore分離、Decorator設定
- **68行目**: store.Decorator = rest.defaultOnRead -- 読み取り時のデフォルト処理登録
- **86-119行目**: defaultOnRead -- PVCリスト/単体のDataSource正規化
- **110-119行目**: defaultOnReadPvc -- NormalizeDataSourcesの呼び出し

#### Step 4: ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | util.go | `pkg/api/persistentvolumeclaim/util.go` | DropDisabledFields, NormalizeDataSources, EnforceDataSourceBackwardsCompatibility |

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

```
API Server HTTP Handler
    |
    +-- genericregistry.Store (etcd操作の汎用実装)
    |       |
    |       +-- persistentvolumeclaim.Strategy (ビジネスロジック)
    |       |       +-- PrepareForCreate()
    |       |       |       +-- pvcutil.DropDisabledFields()
    |       |       |       +-- pvcutil.EnforceDataSourceBackwardsCompatibility()
    |       |       |       +-- pvcutil.NormalizeDataSources()
    |       |       +-- Validate()
    |       |       +-- PrepareForUpdate()
    |       |       |       +-- pvcutil.DropDisabledFields()
    |       |       |       +-- pvcutil.EnforceDataSourceBackwardsCompatibility()
    |       |       |       +-- pvcutil.NormalizeDataSources() (新旧両方)
    |       |       +-- ValidateUpdate()
    |       |
    |       +-- persistentvolumeclaim.StatusStrategy
    |       |       +-- PrepareForUpdate() [Spec保護]
    |       |       |       +-- pvcutil.DropDisabledFieldsFromStatus()
    |       |       +-- ValidateUpdate()
    |       |
    |       +-- REST.defaultOnRead (Decorator)
    |               +-- defaultOnReadPvc()
    |                       +-- pvcutil.NormalizeDataSources()
    |
    +-- persistentvolumeclaim.GetAttrs() (フィルタリング)
```

### データフロー図

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

PVCマニフェスト ──────> API Server ───> Strategy.PrepareForCreate ──> etcd永続化
(YAML/JSON)          (認証/認可)      DataSource正規化              (PVCオブジェクト)
                                      Strategy.Validate
                                      |
PVC読み取り要求 ──> API Server ───> etcd取得 ───> defaultOnRead ──> クライアント
                   (認証/認可)                    NormalizeDataSources
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| strategy.go | `pkg/registry/core/persistentvolumeclaim/strategy.go` | ソース | PVCのCRUDストラテジー |
| storage.go | `pkg/registry/core/persistentvolumeclaim/storage/storage.go` | ソース | REST/StatusRESTエンドポイント、defaultOnRead |
| doc.go | `pkg/registry/core/persistentvolumeclaim/doc.go` | ソース | パッケージドキュメント |
| strategy_test.go | `pkg/registry/core/persistentvolumeclaim/strategy_test.go` | テスト | ストラテジーのユニットテスト |
| storage_test.go | `pkg/registry/core/persistentvolumeclaim/storage/storage_test.go` | テスト | ストレージ層のテスト |
| util.go | `pkg/api/persistentvolumeclaim/util.go` | ソース | PVCユーティリティ（DataSource正規化等） |
| validation.go | `pkg/apis/core/validation/validation.go` | ソース | PVCバリデーション |
| types.go | `pkg/apis/core/types.go` | ソース | 内部API型定義 |
