# 機能設計書 68-ユーザー名前空間管理

## 概要

本ドキュメントは、KubeletにおけるLinux User Namespace（ユーザー名前空間）の割り当て・管理機能の設計を記述する。

### 本機能の処理概要

UsernsManagerは、Podに対するLinux User Namespaceのuid/gidマッピングを管理するコンポーネントである。PodのhostUsersフィールドがfalseに設定された場合に、コンテナ内のroot(uid=0)をホスト上の高いuid/gidにマッピングし、セキュリティを強化する。

**業務上の目的・背景**：Linux User Namespaceは、コンテナ内のプロセスをホストの非特権ユーザーにマッピングすることで、コンテナエスケープ時のリスクを大幅に軽減するセキュリティ機能である。KubeletはこのUser Namespaceのuid/gid範囲をPod単位で割り当て、永続化し、コンテナランタイムに配信する。

**機能の利用シーン**：(1) セキュリティ強化のためhostUsers=falseを設定したPodの起動、(2) Podの再起動時における以前のマッピングの復元、(3) 孤児Pod（削除済み）のマッピングクリーンアップ。

**主要な処理内容**：
1. ビットマップアロケータを使用してuid/gid範囲をPodに割り当てる
2. マッピング情報をPodディレクトリ内のJSONファイルに永続化する
3. Kubelet再起動時にディスクから既存のマッピングを復元する
4. コンテナランタイムに渡すUserNamespace設定を生成する
5. 孤児Podのマッピングを定期的にクリーンアップする

**関連システム・外部連携**：CRI（UserNamespace設定の配信先）、ファイルシステム（マッピングの永続化）、Linux kernel（User Namespace機能）。

**権限による制御**：UserNamespacesSupportフィーチャーゲートで制御される。ランタイムハンドラがUser Namespaceをサポートしている必要がある。

## 関連画面

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

## 機能種別

セキュリティ管理（User Namespaceリソース割り当て）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pod | *v1.Pod | Yes | 対象Pod | pod.Spec.HostUsersがfalseであること |
| runtimeHandler | string | No | ランタイムハンドラ名 | ランタイムがUser Namespaceをサポートすること |
| idsPerPod | *int64 | No | Pod当たりのID数 | userNsUnitLength(65536)の倍数 |

### 入力データソース

- Pod Spec: hostUsersフィールド
- Kubelet設定: idsPerPodパラメータ
- ディスク: 既存Podのマッピングファイル（userns）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| *runtimeapi.UserNamespace | CRI UserNamespace | コンテナランタイムに渡すUser Namespace設定 |
| userNamespace | JSON file | Podディレクトリ内のマッピング永続化ファイル |

### 出力先

- CRI: RunPodSandbox呼び出し時のUserNamespaceConfig
- ファイルシステム: {podDir}/userns

## 処理フロー

### 処理シーケンス

```
1. MakeUserNsManager初期化
   └─ AllocationBitmap作成 → ディスクから既存マッピング復元
2. GetOrCreateUserNamespaceMappings（Pod起動時）
   └─ hostUsers判定 → 既存マッピング読み込みまたは新規割り当て → CRI設定生成
3. Release（Pod削除時）
   └─ ビットマップ解放 → マッピングファイル削除
4. CleanupOrphanedPodUsernsAllocations（定期クリーンアップ）
   └─ 実行中Pod一覧と割り当て一覧を比較 → 孤児割り当ての解放
```

### フローチャート

```mermaid
flowchart TD
    A[Pod起動: GetOrCreateUserNamespaceMappings] --> B{hostUsers == false?}
    B -->|No or nil| C[NamespaceMode_NODE返却]
    B -->|Yes| D{フィーチャーゲート有効?}
    D -->|No| E[エラー返却]
    D -->|Yes| F{ランタイムサポート?}
    F -->|No| G[エラー返却]
    F -->|Yes| H{既存マッピングあり?}
    H -->|Yes| I[ファイルから読み込み・記録]
    H -->|No| J[新規割り当て・ファイル書き込み]
    I --> K[CRI UserNamespace生成]
    J --> K
    K --> L[NamespaceMode_POD + uid/gidマッピング返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | userNsUnitLength | ID範囲の基本単位は65536 | 常時 |
| BR-68-02 | ID=0禁止 | kubeletMappingIDはuserNsLength以上（ホストのuid 0をマッピングしない） | 初期化時 |
| BR-68-03 | UID/GID同一 | UIDマッピングとGIDマッピングは同一内容 | 常時 |
| BR-68-04 | ContainerID=0必須 | コンテナ内のUID/GID 0（root）がマッピングされていること | 常時 |
| BR-68-05 | メモリリーク防止 | mapReInitializeThreshold(1000)回の解放ごとにマップを再初期化する | Pod解放時 |
| BR-68-06 | 最大Pod数保証 | kubeletMappingLen/userNsLength >= maxPods | 初期化時 |

### 計算ロジック

- ビットマップインデックス: `index = (hostId / userNsLength) - offset`
- firstID: `(firstZero + offset) * userNsLength`
- マップ再初期化閾値: `mapReInitializeThreshold = 1000`

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

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

本機能はデータベースを直接操作しない。マッピング情報はPodディレクトリ内のJSONファイルに永続化される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | フィーチャーゲート無効 | UserNamespacesSupportが無効な状態でhostUsers=false指定 | エラー返却（Pod起動失敗） |
| - | ランタイム非対応 | ランタイムハンドラがUser Namespaceをサポートしない | エラー返却（Pod起動失敗） |
| - | 割り当て枯渇 | 利用可能なID範囲がない | エラー返却（Pod起動失敗） |
| - | マッピングファイルエラー | JSONの解析失敗 | エラー返却 |
| - | 不正なマッピング | UIDとGIDが不一致、ContainerID != 0 | エラー返却 |

### リトライ仕様

マッピング割り当ての失敗はPod起動の再試行（syncPodループ）で自動リトライされる。

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

マッピングファイルはFileStoreによるアトミック書き込みとfsyncで永続化される。割り当て失敗時はreleaseWithLockでロールバックされる。

## パフォーマンス要件

- AllocationBitmapによるO(1)のビットマップ操作
- マップ再初期化による長期運用時のメモリリーク防止
- lockによる排他制御でスレッドセーフ

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

- ホストのUID 0をコンテナにマッピングしない（kubeletMappingID >= userNsLength）
- マッピング情報はPodディレクトリ内に保存され、適切なファイルパーミッションで保護
- User Namespaceによりコンテナエスケープ時のリスクを大幅に軽減

## 備考

- 本機能はLinux固有（`//go:build !windows`）
- UserNamespacesSupportフィーチャーゲートにより制御される
- Kubelet再起動時にディスクから全既存Podのマッピングを復元する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | UsernsManager構造体（52-65行目）: AllocationBitmap、usedByマップ、offset/len |
| 1-2 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | userNamespace/idMapping構造体（68-83行目）: JSONシリアライズ形式 |
| 1-3 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | 定数定義（43-49行目）: mapReInitializeThreshold、userNsUnitLength |

**読解のコツ**: `AllocationBitmap`は各ビットがuserNsLength(65536)個のIDブロックを表す。`offset`はビットマップ先頭のホストID位置を示す。`usedBy`マップはPod UIDからホスト上のfirstIDへのマッピングを保持する。

#### Step 2: 初期化と復元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | MakeUserNsManager（132-193行目）: 初期化とバリデーション |
| 2-2 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | recordPodMappings（197-210行目）: 既存Podのマッピング復元 |

**主要処理フロー**:
- **133-135行目**: フィーチャーゲートチェック
- **137-163行目**: idsPerPodのバリデーション（userNsUnitLengthの倍数チェック等）
- **168-175行目**: AllocationBitmapとusedByマップの初期化
- **177-190行目**: ディスクからの既存Podマッピング復元

#### Step 3: マッピング割り当てを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | GetOrCreateUserNamespaceMappings（396-479行目）: メインエントリーポイント |
| 3-2 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | createUserNs（363-393行目）: 新規マッピング割り当て |
| 3-3 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | allocateOne（224-238行目）: ビットマップからの空き検索 |

#### Step 4: 解放とクリーンアップを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | Release（275-284行目）: マッピング解放 |
| 4-2 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | releaseWithLock（299-321行目）: 内部解放ロジック（マップ再初期化含む） |
| 4-3 | userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | CleanupOrphanedPodUsernsAllocations（484-532行目）: 孤児クリーンアップ |

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

```
Kubelet
    │
    ├─ MakeUserNsManager()
    │      ├─ GetKubeletMappings()
    │      ├─ AllocationBitmap作成
    │      └─ ListPodsFromDisk() → recordPodMappings()
    │             └─ readMappingsFromFile() → parseUserNsFileAndRecord()
    │
    ├─ GetOrCreateUserNamespaceMappings()
    │      ├─ hostUsers判定
    │      ├─ HandlerSupportsUserNamespaces()
    │      ├─ readMappingsFromFile()
    │      │      └─ parseUserNsFileAndRecord() → record()
    │      └─ createUserNs()
    │             ├─ allocateOne()
    │             └─ writeMappingsToFile()
    │
    ├─ Release()
    │      └─ releaseWithLock()
    │             ├─ used.Release()
    │             ├─ delete(usedBy)
    │             └─ os.Remove(mappingsFile)
    │
    └─ CleanupOrphanedPodUsernsAllocations()
           ├─ ListPodsFromDisk()
           └─ releaseWithLock() [孤児Pod分]
```

### データフロー図

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

Pod Spec (hostUsers) ──▶ GetOrCreateUserNamespaceMappings ──▶ runtimeapi.UserNamespace
ディスク (userns file) ──▶ readMappingsFromFile ──────────▶ userNamespace構造体
AllocationBitmap ─────▶ allocateOne ───────────────────────▶ firstID + length
                              │
                              └─ writeMappingsToFile ──────▶ {podDir}/userns (JSON)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| userns_manager.go | `pkg/kubelet/userns/userns_manager.go` | ソース | User Namespace管理の中核実装 |
| userns_manager_test.go | `pkg/kubelet/userns/userns_manager_test.go` | テスト | User Namespace管理のテスト |
| userns_manager_unsupported.go | `pkg/kubelet/userns/userns_manager_unsupported.go` | ソース | Windows/非対応OS用のスタブ |
| allocator.go | `pkg/registry/core/service/allocator/bitmap.go` | ソース | AllocationBitmapの実装 |
