# 機能設計書 98-Pod実行（run）

## 概要

本ドキュメントは、kubectl runコマンドによるPod作成・実行機能の設計を記述する。

### 本機能の処理概要

kubectl runコマンドは、指定されたコンテナイメージを使用してPodを作成し、オプションでインタラクティブなアタッチやService作成を行うCLI機能である。

**業務上の目的・背景**：デバッグ用のワンショットPodの起動、テスト実行、クイックなアプリケーション起動など、YAMLマニフェストを書くことなくPodを素早く作成するために利用される。

**機能の利用シーン**：デバッグ用Pod起動（busybox, curlイメージ等）、テスト実行、クイックデモ、インタラクティブシェルアクセス、ワンショットジョブの実行。

**主要な処理内容**：
1. コマンドライン引数からPod名、イメージ、環境変数等を解析
2. GeneratorFn（RunPodV1Generator）を使用してPodオブジェクトを生成
3. Override適用後にAPI Serverに作成
4. オプションでアタッチ、Service作成、Pod終了待機、自動削除

**関連システム・外部連携**：コンテナランタイムがPodを起動。--attach時はattachコマンドを内部的に使用。--expose時はServiceを自動作成。

**権限による制御**：Podのcreate権限、--expose時はServiceのcreate権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | kubectl run | 主機能 | Podの作成・実行 |

## 機能種別

CRUD操作（Create） / Pod実行・アタッチ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| NAME | string | Yes | Pod名 | DNS-1123形式 |
| --image | string | Yes | コンテナイメージ | 有効なイメージ参照形式 |
| --port | string | No | コンテナ公開ポート | 有効なポート番号 |
| --env | string[] | No | 環境変数（key=value） | 有効なkey=value形式 |
| --labels / -l | string | No | Podラベル | 有効なラベル形式 |
| --annotations | string[] | No | Podアノテーション | 有効なアノテーション形式 |
| --restart | string | No | 再起動ポリシー（Always/OnFailure/Never） | 有効なポリシー |
| --command | bool | No | -- 以降をCommandとして使用（デフォルトはArgs） | - |
| -i / --stdin | bool | No | stdinをオープンに保持 | - |
| -t / --tty | bool | No | TTY割り当て | -i必須 |
| --attach | bool | No | Pod起動後にアタッチ | -i指定時はデフォルトtrue |
| --rm | bool | No | 終了後にPod自動削除 | attach時のみ有効 |
| --expose | bool | No | 同時にServiceを作成 | --port必須 |
| --privileged | bool | No | 特権モードで実行 | - |
| --image-pull-policy | string | No | イメージプルポリシー | Always/IfNotPresent/Never |
| --dry-run | string | No | dry-run戦略 | none/client/server |
| -q / --quiet | bool | No | メッセージ抑制 | - |
| --leave-stdin-open | bool | No | アタッチ後もstdinを閉じない | - |
| --pod-running-timeout | duration | No | Pod起動待機タイムアウト | デフォルト60秒 |

### 入力データソース

CLI引数、kubeconfig

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 作成結果 | string | "pod/xxx created" メッセージ |
| アタッチ出力 | stream | コンテナの標準出力/エラー出力 |
| 終了コード | int | --attach かつ --restart=Never時のコンテナ終了コード |

### 出力先

標準出力（stdout）、標準エラー出力（stderr）

## 処理フロー

### 処理シーケンス

```
1. Complete: 引数と環境の初期化
   ├─ RecordFlags設定
   ├─ DryRunStrategy取得
   ├─ PrintFlags設定
   └─ DeleteOptions設定
2. Run: Pod作成・実行
   ├─ 入力パラメータの検証
   ├─ Generator（RunPodV1Generator）でPodオブジェクト生成
   ├─ Override適用
   ├─ API Serverに作成（dry-run!=client時）
   ├─ [--expose時] ServiceGeneratorでService作成
   ├─ [--attach時]
   │   ├─ attachablePodの取得（waitForPod: Running & Ready）
   │   ├─ handleAttachPod: アタッチ実行
   │   │   ├─ 事前ログ取得（5秒タイムアウト）
   │   │   └─ attach.Run() / logOptsへのフォールバック
   │   └─ [--restart=Never/OnFailure時] waitForPod: 完了待機
   │       └─ 終了コードの取得と返却
   └─ [--rm時] removeCreatedObjects: 作成オブジェクトの削除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Complete: 初期化]
    B --> C[Run: 入力検証]
    C --> D{イメージ名有効?}
    D -->|No| E[エラー終了]
    D -->|Yes| F[Generator.Generate: Pod生成]
    F --> G[Override適用]
    G --> H{dry-run client?}
    H -->|Yes| I[オブジェクト出力]
    H -->|No| J[API Server CREATE Pod]
    J --> K{--expose?}
    K -->|Yes| L[Service作成]
    K -->|No| M{--attach?}
    L --> M
    M -->|Yes| N[waitForPod: Running & Ready]
    N --> O[handleAttachPod: アタッチ実行]
    O --> P{restart=Never/OnFailure?}
    P -->|Yes| Q[waitForPod: 完了待機]
    Q --> R{PodSucceeded?}
    R -->|Yes| S[正常終了]
    R -->|No| T[終了コード付きエラー]
    P -->|No| S
    M -->|No| U[PrintObj: 結果出力]
    I --> V[終了]
    S --> V
    T --> V
    U --> V
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-98-01 | イメージ必須 | --imageの指定は必須 | 常時 |
| BR-98-02 | イメージ名検証 | ReferenceRegexpによるイメージ名の形式検証 | 常時 |
| BR-98-03 | TTYはstdin必須 | -tは-iと同時に指定する必要がある | -t指定時 |
| BR-98-04 | expose時はport必須 | --expose指定時は--portの指定が必須 | expose時 |
| BR-98-05 | rm時はattach必須 | --rmは--attach時のみ有効 | rm時 |
| BR-98-06 | dry-run時はattach不可 | --dry-runと--attach/--stdin/--ttyは併用不可 | dry-run時 |
| BR-98-07 | attachデフォルト | -i指定時は--attachのデフォルトがtrue | -i指定時 |
| BR-98-08 | restartデフォルト | デフォルトはAlways。interactiveモード時はOnFailure | - |
| BR-98-09 | 終了コード伝搬 | restart=Never/OnFailure時、コンテナの終了コードをプロセス終了コードとして返す | attach時 |
| BR-98-10 | Pod起動タイムアウト | デフォルト60秒でPod起動を待機 | attach時 |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Create Pod | Pod | CREATE | Podリソースを新規作成 |
| Create Service | Service | CREATE | --expose時にServiceリソースを作成 |
| Delete Pod | Pod | DELETE | --rm時にPodを削除 |
| Delete Service | Service | DELETE | --rm時にServiceを削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数エラー | NAME未指定 | Pod名を指定 |
| - | イメージエラー | --image未指定または無効 | 有効なイメージ名を指定 |
| - | TTYエラー | -tのみで-i未指定 | -iも同時に指定 |
| - | exposeエラー | --expose時に--port未指定 | --portを指定 |
| - | rmエラー | --rm時に--attach未使用 | --attachも指定 |
| - | dry-runエラー | dry-runとattach系オプションの併用 | どちらかを選択 |
| - | Pod完了エラー | Podが異常終了（restart=Never時） | コンテナログを確認 |

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

Pod作成とService作成は別々のAPI呼び出し。Service作成失敗時もPodは作成済み。--rm時はdeferで作成オブジェクトを削除。

## パフォーマンス要件

Pod作成は単一API呼び出し。attachモードではPod起動待機のためポーリング（watchtools.UntilWithSync）が発生。タイムアウトはpod-running-timeoutで制御。

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

- Podのcreate権限が必要
- --privilegedは特権コンテナを作成するため注意
- --exposeはNetworkPolicyの影響を受ける

## 備考

- Generator（RunPodV1Generator）によるPod生成はレガシーな仕組みだが現在も使用されている
- --rm付きattachモードはdeferで確実にクリーンアップされる
- attachフォールバックでログストリーミングに切り替え

---

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **99-102行目**: RunObject構造体（作成されたオブジェクトのラッパー） |
| 1-2 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **104-134行目**: RunOptions構造体で全オプションを確認 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **148-172行目**: NewCmdRun関数でcobraコマンド定義 |
| 2-2 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **174-195行目**: addRunFlags関数で多数のフラグ登録 |

#### Step 3: Pod作成フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **245-413行目**: Run関数がPod作成の本体 |
| 3-2 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **261-263行目**: イメージ名のReferenceRegexp検証 |
| 3-3 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **294-298行目**: GeneratorFnでRunPodV1Generator取得 |
| 3-4 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **311行目**: createGeneratedObjectでPod生成→API作成 |
| 3-5 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **616-680行目**: createGeneratedObject内でGenerator→Override→Create |

#### Step 4: アタッチフローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **327-405行目**: attachモードの全体フロー |
| 4-2 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **356-357行目**: attachablePodの取得 |
| 4-3 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **471-510行目**: handleAttachPod関数でwaitForPod→attach/logsフォールバック |
| 4-4 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **442-469行目**: waitForPod関数（watchtools.UntilWithSync） |
| 4-5 | run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | **688-744行目**: podCompleted/podSucceeded/podRunningAndReady条件関数 |

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

```
NewCmdRun
    │
    ├─ Complete
    │      ├─ RecordFlags / DryRunStrategy
    │      ├─ PrintFlags.ToPrinter
    │      └─ DeleteFlags.ToOptions
    │
    └─ Run
           ├─ 入力検証（image, tty, expose, rm, dry-run）
           ├─ getRestartPolicy()
           ├─ GeneratorFn("run") → RunPodV1Generator
           ├─ createGeneratedObject()
           │      ├─ generator.Generate(params)
           │      ├─ overrider.Apply()
           │      └─ resource.NewHelper().Create()  ───▶ API Server
           │
           ├─ [--expose] generateService()
           │      ├─ GeneratorFn("expose") → ServiceV2Generator
           │      └─ createGeneratedObject()  ───▶ API Server
           │
           ├─ [--attach]
           │      ├─ attachablePodForObject()
           │      ├─ handleAttachPod()
           │      │      ├─ waitForPod(podRunningAndReady)
           │      │      ├─ logOpts() (事前ログ)
           │      │      └─ attach.Run() / logOpts(fallback)
           │      └─ waitForPod(podCompleted/podSucceeded)
           │             └─ 終了コード取得
           │
           └─ [--rm] removeCreatedObjects()
                  └─ DeleteOptions.DeleteResult()
```

### データフロー図

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

CLI引数              ───▶ Complete（初期化）
 (NAME --image)            │
                           ▼
kubeconfig           ───▶ Run
                      ├─ Generator.Generate()
                      ├─ NewHelper().Create() ───▶ API Server (CREATE Pod)
                      ├─ [expose] Create()   ───▶ API Server (CREATE Service)
                      ├─ [attach]
                      │   ├─ waitForPod()    ───▶ API Server (WATCH Pod)
                      │   ├─ attach.Run()    ◀──▶ Container Runtime (stdin/stdout)
                      │   └─ logOpts()       ◀─── API Server (GET logs)
                      └─ PrintObj()          ───▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| run.go | `staging/src/k8s.io/kubectl/pkg/cmd/run/run.go` | ソース | runコマンドのメイン実装（745行） |
| generators.go | `staging/src/k8s.io/kubectl/pkg/generate/versioned/` | ソース | RunPodV1Generator, ServiceV2Generator |
| attach.go | `staging/src/k8s.io/kubectl/pkg/cmd/attach/` | ソース | アタッチ機能 |
| logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/` | ソース | ログストリーミング |
| exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/` | ソース | StreamOptions定義 |
| interrupt.go | `staging/src/k8s.io/kubectl/pkg/util/interrupt/` | ソース | シグナルハンドリング |
