# 画面設計書 22-kubectl exec

## 概要

本ドキュメントは、Kubernetes CLIツール kubectl の `exec` コマンドに関する画面設計書である。kubectl exec は実行中のコンテナ内で任意のコマンドを実行する機能を提供する。

### 本画面の処理概要

kubectl exec コマンドは、Kubernetes クラスター上で既に実行中のコンテナ内で新しいプロセスを起動し、そのプロセスの標準入出力をローカルターミナルに接続する。attach コマンドとは異なり、メインプロセスではなく新規プロセスを起動する点が特徴である。

**業務上の目的・背景**：コンテナ内での診断コマンド実行、ログファイルの確認、設定ファイルの確認、デバッグ作業など、運用・保守において頻繁に利用される基本機能である。コンテナの再起動を伴わずに内部状態を確認できるため、本番環境での問題調査に不可欠である。

**画面へのアクセス方法**：ターミナルから `kubectl exec <POD名> -- <COMMAND>` を実行する。`--` の後にコンテナ内で実行するコマンドを指定する。

**主要な操作・処理内容**：
1. 対象Pod/リソースの検索と実行可能なPodの特定
2. 対象コンテナの選択（`-c` フラグまたはデフォルトコンテナ）
3. TTY のセットアップ
4. Kubelet の Exec エンドポイントへの SPDY/WebSocket 接続確立
5. コマンドの実行と stdin/stdout/stderr のストリーミング

**画面遷移**：kubectl cp コマンドが内部的に exec 機能を利用する。kubectl debug コマンドからも exec 機能が利用される。

**権限による表示制御**：対象Podの `pods/exec` サブリソースに対する権限が必要。RBACにより制御される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 88 | コンテナ実行（exec） | 主機能 | 実行中のコンテナ内でコマンドを実行する主処理 |
| 66 | Kubelet API Server | API連携 | KubeletのExecエンドポイントを通じてコンテナ内でコマンドを実行する |

## 画面種別

CLI対話型/非対話型コマンド（ストリーミング）

## URL/ルーティング

```
kubectl exec (POD | TYPE/NAME) [-c CONTAINER] [flags] -- COMMAND [args...]
```

内部的には以下の REST API エンドポイントを使用：
```
POST /api/v1/namespaces/{namespace}/pods/{name}/exec
```

## 入出力項目

| 項目名 | 種別 | 必須 | 型 | 説明 |
|--------|------|------|-----|------|
| POD / TYPE/NAME | 引数 | Yes | string | 実行対象のPodまたはリソース |
| COMMAND [args...] | 引数（-- 以降） | Yes | string[] | コンテナ内で実行するコマンドと引数 |
| --container, -c | フラグ | No | string | 実行対象のコンテナ名 |
| --stdin, -i | フラグ | No | bool | stdinをコンテナに渡す（デフォルト: false） |
| --tty, -t | フラグ | No | bool | stdinがTTYかどうか（デフォルト: false） |
| --quiet, -q | フラグ | No | bool | 情報メッセージを抑制する（デフォルト: false） |
| --pod-running-timeout | フラグ | No | duration | PodがRunningになるまでの待機時間（デフォルト: 60s） |
| -f, --filename | フラグ | No | string[] | exec対象リソースを指定するファイル |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| コマンド出力 | 実行したコマンドのstdout |
| エラー出力 | 実行したコマンドのstderr |
| TTY警告 | TTYが利用できない場合の警告メッセージ |

## イベント仕様

### 1-コマンド実行

ユーザーが `kubectl exec` コマンドを実行すると、以下の処理フローが実行される：

1. Complete: コマンドライン引数解析（`--` 前後の分離）、namespace決定、PodClient取得
2. Validate: Pod名/リソース名の存在確認、コマンドの存在確認、出力ストリームの確認
3. Run: Pod取得 -> コンテナ特定 -> TTYセットアップ -> Exec実行

### 2-コマンド終了

実行したコマンドの終了コードがそのまま kubectl の終了コードとなる。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| exec実行 | - | SELECT（読み取り） | Pod情報の取得のみ。kubectl自体はリソースを変更しない |

kubectl exec コマンド自体はKubernetesリソースの状態を変更しない。ただし実行されるコマンドがコンテナ内の状態を変更する可能性がある。

### テーブル別更新項目詳細

該当なし（kubectl 側は読み取り専用）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|------------|------|--------------|----------|
| M-01 | エラー | "pod, type/name or --filename must be specified" | Pod名もリソース名もファイルも未指定 |
| M-02 | エラー | "you must specify at least one command for the container" | コマンド未指定 |
| M-03 | エラー | "both output and error output must be provided" | 出力ストリーム未設定 |
| M-04 | エラー | "cannot exec into a container in a completed pod; current phase is %s" | PodがSucceeded/Failed |
| M-05 | エラー | "cannot exec into multiple objects at a time" | 複数オブジェクトが指定された場合 |
| M-06 | 警告 | "Unable to use a TTY - input is not a terminal or the right kind of file" | TTY要求だが入力がターミナルでない |
| M-07 | エラー | "exec [POD] [COMMAND] is not supported anymore. Use exec [POD] -- [COMMAND] instead" | 旧形式の引数使用 |

## 例外処理

| 例外 | 状態 | 対処 |
|------|------|------|
| Pod が見つからない | エラー終了 | リソースが存在しない旨のエラーを表示 |
| Pod が Succeeded/Failed | エラー終了 | 完了済みPodでは exec 不可のメッセージを表示 |
| コマンド未指定 | エラー終了 | コマンド必須のエラーを表示 |
| 複数オブジェクト指定 | エラー終了 | 単一オブジェクトのみ対応のエラーを表示 |
| Kubelet 接続失敗 | エラー終了 | ネットワークエラーまたは権限不足のエラーを表示 |
| WebSocket アップグレード失敗 | フォールバック | SPDY にフォールバック |

## 備考

- exec は新しいプロセスを起動する点で attach と異なる。attach はメインプロセスに接続する。
- `--` セパレータは必須。これがないと、コマンドのフラグが kubectl のフラグと衝突する。
- kubectl cp コマンドは内部的に exec を使用して tar によるファイル転送を実行する。
- Deployment/Service 等のリソースタイプを指定した場合、自動的にPodが選択される（`ExecutablePodFn`）。
- デフォルトタイムアウトは60秒（exec.go 行78）。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | StreamOptions（行168-184）: 共通ストリーム設定 |
| 1-2 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | ExecOptions（行187-204）: Command, Pod, Executor等のexec固有設定 |
| 1-3 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | RemoteExecutor インターフェース（行116-122）: Execute と ExecuteWithContext |

**読解のコツ**: ExecOptions は StreamOptions を埋め込んでおり、StreamOptions は attach コマンドとも共有される。FilenameOptions も埋め込まれ `-f` によるリソース指定をサポートする。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | NewCmdExec（行81-113）: コマンド定義、ArgsLenAtDash による引数分離 |

**主要処理フロー**:
1. **行97**: `cmd.ArgsLenAtDash()` で `--` の位置を取得
2. **行98-100**: Complete -> Validate -> Run の3段階実行

#### Step 3: Complete/Validate/Run を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | Complete（行207-245）: 引数の解析、`--` 前後の分離、PodClient取得 |
| 3-2 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | Validate（行248-259）: Pod名/コマンド/出力のチェック |
| 3-3 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | Run（行314-407）: Pod取得、コンテナ選択、TTYセットアップ、exec実行 |

**主要処理フロー**:
- **行319-346**: PodName指定時はPodClientで直接取得、ResourceName指定時はBuilderで検索
- **行350-351**: Succeeded/Failed Podのチェック
- **行354-361**: コンテナ名の決定（未指定時はデフォルトコンテナ）
- **行378-399**: REST API への POST リクエスト作成と実行

#### Step 4: TTYセットアップを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | SetupTTY（行261-311）: TTY設定、Raw モード、Windows対応 |

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

```
NewCmdExec (行81)
    |
    +-- Complete (行207)
    |       +-- ArgsLenAtDash で引数分離
    |       +-- f.ToRawKubeConfigLoader().Namespace()
    |       +-- f.KubernetesClientSet() -> PodClient
    |
    +-- Validate (行248)
    |
    +-- Run (行314)
            |
            +-- PodClient.Pods().Get() or Builder.Do().Object()
            +-- ExecutablePodFn (polymorphichelpers)
            +-- podcmd.FindOrDefaultContainerByName
            +-- SetupTTY (行261)
            +-- restClient.Post().Resource("pods").SubResource("exec") (行385-389)
            +-- Executor.Execute (行399)
                    |
                    +-- createExecutor (行146)
                    |       +-- NewSPDYExecutor
                    |       +-- NewWebSocketExecutor
                    |       +-- NewFallbackExecutor
                    +-- exec.StreamWithContext (行136)
```

### データフロー図

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

ユーザー引数             Complete
(POD, -- CMD) --------> (引数解析, Client初期化)
                              |
                         Validate
                         (必須チェック) -----------------> エラー or 継続
                              |
                         Run
                         (Pod/Container特定)
                              |
stdin -----------------> REST API POST
(任意)                   (/pods/{name}/exec)
                              |
                         Kubelet Exec Endpoint ---------> stdout (コマンド出力)
                         (SPDY/WebSocket)                 stderr (エラー出力)
                                                          exit code
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| exec.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec.go` | ソース | exec コマンドの主実装 |
| podcmd/ | `staging/src/k8s.io/kubectl/pkg/cmd/util/podcmd/` | ソース | コンテナ選択ユーティリティ |
| term/ | `staging/src/k8s.io/kubectl/pkg/util/term/` | ソース | TTY管理 |
| remotecommand/ | `staging/src/k8s.io/client-go/tools/remotecommand/` | ソース | SPDY/WebSocket エグゼキュータ |
| polymorphichelpers/ | `staging/src/k8s.io/kubectl/pkg/polymorphichelpers/` | ソース | AttachablePodForObject 等のヘルパー |
| exec_test.go | `staging/src/k8s.io/kubectl/pkg/cmd/exec/exec_test.go` | テスト | exec コマンドのユニットテスト |
