# 帳票設計書 1-Pod一覧

## 概要

本ドキュメントは、Kubernetes の Pod リソース一覧をテーブル形式で標準出力に出力する帳票の設計を定義する。`kubectl get pods` コマンド実行時に、API サーバから取得した Pod オブジェクトの情報を人間が読みやすいテーブル形式に変換して表示する仕組みを対象とする。

### 本帳票の処理概要

本帳票は、Kubernetes クラスタ上で稼働する Pod リソースの一覧情報を、テーブル形式で標準出力に表示する処理を行う。

**業務上の目的・背景**：Kubernetes クラスタの運用において、Pod はアプリケーションの最小デプロイ単位であり、運用者はその状態を常に把握する必要がある。Pod の名前、Ready 状態、ステータス、再起動回数、経過時間などの情報を一覧表示することで、クラスタ全体の健全性を迅速に確認できる。障害発生時のトリアージや、デプロイ後のヘルスチェックなど、日常的な運用タスクにおいて不可欠な帳票である。

**帳票の利用シーン**：クラスタ運用者がデプロイ状況を確認する場合、Pod の異常（CrashLoopBackOff、OOMKilled 等）を検出する場合、特定の Namespace 内のワークロード一覧を取得する場合、ノード障害時に影響を受ける Pod を特定する場合など、多岐にわたるシーンで利用される。

**主要な出力内容**：
1. Pod 名（Name）
2. Ready コンテナ数 / 全コンテナ数（Ready）
3. Pod のステータス（Status）: Running, Pending, Succeeded, Failed, Terminating, Init 状態など
4. 再起動回数と最終再起動からの経過時間（Restarts）
5. 作成からの経過時間（Age）
6. Wide 出力時: Pod IP, ノード名, Nominated Node, Readiness Gates

**帳票の出力タイミング**：ユーザが `kubectl get pods` コマンドを実行した際にリアルタイムで出力される。`-w` オプション指定時は Watch モードで継続的に更新情報が出力される。

**帳票の利用者**：Kubernetes クラスタ管理者、アプリケーション開発者、SRE（Site Reliability Engineer）、DevOps エンジニア。

## 帳票種別

一覧表（リソース一覧出力）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | ターミナル（CLI） | N/A | `kubectl get pods [flags]` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | 標準出力（テキスト / テーブル形式） |
| 用紙サイズ | N/A（ターミナル出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力） |
| 出力方法 | 標準出力（stdout）へのテーブル表示 |
| 文字コード | UTF-8 |

### テーブル出力固有設定

| 項目 | 内容 |
|-----|------|
| カラム区切り | タブ文字（tabwriter による整列） |
| ヘッダー表示 | デフォルト有効（`--no-headers` で無効化可能） |
| Wide 出力 | `-o wide` で追加カラム表示（Priority > 0 のカラム） |

## 帳票レイアウト

### レイアウト概要

テーブルはヘッダー行と明細行で構成される。サーバサイド（API サーバ）でテーブル変換が行われる場合と、クライアントサイド（kubectl）でテーブル変換が行われる場合がある。

```
┌──────────────────────────────────────────────────────────────────────┐
│  NAME    READY   STATUS    RESTARTS   AGE                          │
│  ヘッダー行（カラム定義に基づく）                                       │
├──────────────────────────────────────────────────────────────────────┤
│  pod-1   1/1     Running   0          5d                           │
│  pod-2   0/1     Pending   3 (2h ago) 1d                           │
│  ...（Pod 数分の明細行）                                              │
└──────────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Name | Pod の名前 | `pod.ObjectMeta.Name` | 文字列（name フォーマット） |
| 2 | Ready | Ready 状態のコンテナ数/全コンテナ数 | `pod.Status.ContainerStatuses` + `pod.Spec.Containers` | `{ready}/{total}` 形式 |
| 3 | Status | Pod の現在のステータス | `pod.Status.Phase`, `pod.Status.Reason`, コンテナ状態から算出 | 文字列 |
| 4 | Restarts | コンテナの再起動回数 | `pod.Status.ContainerStatuses[].RestartCount` の合計 | `{count}` または `{count} ({duration} ago)` |
| 5 | Age | 作成からの経過時間 | `pod.ObjectMeta.CreationTimestamp` | `translateTimestampSince` による人間可読形式 |

### 明細部（Wide 出力時の追加カラム）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 6 | IP | Pod の IP アドレス | `pod.Status.PodIPs[0].IP` | IP アドレス文字列、未割当時は `<none>` | 可変 |
| 7 | Node | Pod が配置されたノード名 | `pod.Spec.NodeName` | 文字列、未配置時は `<none>` | 可変 |
| 8 | Nominated Node | 優先ノード名 | `pod.Status.NominatedNodeName` | 文字列、未設定時は `<none>` | 可変 |
| 9 | Readiness Gates | Readiness Gate の状態 | `pod.Spec.ReadinessGates` + `pod.Status.Conditions` | `{true}/{total}` 形式、未設定時は `<none>` | 可変 |

### フッター部

フッター部は存在しない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| Namespace | 対象 Namespace（`-n` / `--namespace`） | No（デフォルト: 現在のコンテキストの Namespace） |
| All Namespaces | 全 Namespace 対象（`-A` / `--all-namespaces`） | No |
| Label Selector | ラベルによるフィルタリング（`-l`） | No |
| Field Selector | フィールドによるフィルタリング（`--field-selector`） | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | Pod 名（デフォルト） | 昇順（API サーバのレスポンス順） |
| - | `--sort-by` 指定時 | 指定フィールドで昇順 |

### 改ページ条件

改ページは発生しない（全データを一括出力）。ただし、`--chunk-size` オプションにより API サーバからのデータ取得をページネーションすることは可能。

## データベース参照仕様

### 参照テーブル一覧

本帳票は Kubernetes API サーバ経由で etcd からデータを取得する。直接的なデータベーステーブルへのアクセスは行わない。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| etcd: `/registry/pods/{namespace}/{name}` | Pod オブジェクトの永続化ストア | N/A（API サーバ経由でアクセス） |

### テーブル別参照項目詳細

#### Pod リソース（API: `v1/pods`）

| 参照項目（フィールド） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| `metadata.name` | Name | N/A | Pod の一意な名前 |
| `metadata.creationTimestamp` | Age | N/A | `translateTimestampSince` で経過時間に変換 |
| `spec.containers` | Ready (分母), Containers (wide) | N/A | コンテナ定義一覧 |
| `spec.initContainers` | Ready (分母に加算: restartable init containers) | N/A | 初期化コンテナ定義 |
| `spec.nodeName` | Node (wide) | N/A | スケジュール先ノード |
| `spec.readinessGates` | Readiness Gates (wide) | N/A | カスタム Readiness Gate |
| `status.phase` | Status | N/A | Pod のフェーズ |
| `status.reason` | Status | N/A | フェーズの補足理由 |
| `status.conditions` | Status, Readiness Gates (wide) | N/A | Pod の状態条件 |
| `status.podIPs` | IP (wide) | N/A | 割当 IP アドレス一覧 |
| `status.nominatedNodeName` | Nominated Node (wide) | N/A | プリエンプションによる優先ノード |
| `status.containerStatuses` | Ready (分子), Restarts, Status | N/A | 各コンテナの状態 |
| `status.initContainerStatuses` | Restarts, Status | N/A | 初期化コンテナの状態 |
| `metadata.deletionTimestamp` | Status | N/A | 削除中の場合 "Terminating" と表示 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Ready | `readyContainers / totalContainers` | N/A | totalContainers = len(Spec.Containers) + restartable init containers。readyContainers は Running かつ Ready のコンテナ数 |
| Restarts | `sum(ContainerStatuses[].RestartCount) + sum(restartable InitContainerStatuses[].RestartCount)` | N/A | 初期化完了後は restartable init container のリスタート数のみ再計算 |
| Status | 複合ロジック（詳細後述） | N/A | Phase, Reason, コンテナ状態, DeletionTimestamp を総合的に判定 |
| Age | `time.Since(CreationTimestamp)` | `duration.HumanDuration` による丸め | 秒/分/時/日/年の単位で表示 |

#### Status 算出ロジック詳細

1. 基本値は `pod.Status.Phase` の文字列表現
2. `pod.Status.Reason` が設定されていればそれで上書き
3. `PodScheduled` 条件が `SchedulingGated` なら "SchedulingGated"
4. InitContainer の状態を順にチェック:
   - Terminated(ExitCode!=0): `Init:Signal:{signal}` / `Init:ExitCode:{code}` / `Init:{Reason}`
   - Waiting: `Init:{Reason}`
   - 進行中: `Init:{index}/{total}`
5. 初期化完了後、ContainerStatuses を逆順にチェック:
   - Waiting: そのまま `{Reason}` を表示
   - Terminated: `{Reason}` / `Signal:{signal}` / `ExitCode:{code}`
6. "Completed" かつ Running コンテナありなら "Running" または "NotReady"
7. `DeletionTimestamp` 設定済みかつ `NodeUnreachablePodReason` なら "Unknown"
8. `DeletionTimestamp` 設定済みかつ Phase が Terminal でなければ "Terminating"

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl get pods 実行] --> B[GetOptions.Run]
    B --> C[API サーバへリクエスト]
    C --> D{サーバサイドテーブル変換?}
    D -->|Yes| E[API サーバ内で TableConvertor.ConvertToTable]
    D -->|No| F[クライアントサイドで HumanReadableGenerator.GenerateTable]
    E --> G[TablePrinter.PrintObj]
    F --> G
    G --> H[HumanReadablePrinter.PrintObj]
    H --> I[tabwriter でテーブル整列]
    I --> J[標準出力へ出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | 指定条件に合致する Pod が存在しない | `No resources found in {namespace} namespace.` | 条件を見直す |
| API エラー | API サーバへの接続失敗、認証エラー | API サーバのエラーメッセージを表示 | kubeconfig の設定を確認 |
| テーブル変換失敗 | サーバレスポンスを Table 型に変換できない | クライアントサイドフォールバックで表示 | ログレベル V(2) で詳細出力 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数件〜数万件（大規模クラスタ） |
| 目標出力時間 | ChunkSize（デフォルト 500）単位で逐次取得 |
| 同時出力数上限 | N/A（CLI ツールのため単一プロセスで動作） |

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

- Pod 一覧の取得には RBAC による `pods` リソースの `list` / `get` 権限が必要
- Namespace スコープのアクセス制御が適用される
- `--all-namespaces` 使用時はクラスタレベルの `list` 権限が必要
- 出力内容に機密情報（環境変数、シークレット等）は含まれない

## 備考

- サーバサイドテーブル変換は Kubernetes 1.10 以降でデフォルト有効
- `printPod` 関数内で Pod のステータス表示は複雑なロジックを持ち、InitContainer（restartable を含む）の状態も考慮される
- `kubectl get pods -o wide` で追加カラムが表示される（Priority > 0 のカラム定義）

---

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

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

### 推奨読解順序

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

まず、Pod リソースのデータ構造と、テーブル出力の基盤となる TableRow / TableColumnDefinition を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tablegenerator.go | `pkg/printers/tablegenerator.go` | PrintHandler インターフェース、GenerateOptions 構造体、HumanReadableGenerator によるテーブル生成の仕組み（行 30〜121） |
| 1-2 | types.go (metav1) | `staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/types.go` | TableColumnDefinition、TableRow、Table 型の定義 |

**読解のコツ**: `PrintHandler.TableHandler` はリフレクションを使って print 関数を登録する仕組みであり、型チェックは `ValidateRowPrintHandlerFunc`（行 155〜171）で行われる。

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

kubectl get コマンドの実行フローを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | get.go | `staging/src/k8s.io/kubectl/pkg/cmd/get/get.go` | GetOptions 構造体の定義（行 55〜）、Run メソッドでの API 呼び出しと結果表示の流れ |
| 2-2 | table_printer.go | `staging/src/k8s.io/kubectl/pkg/cmd/get/table_printer.go` | TablePrinter.PrintObj（行 38〜47）でサーバレスポンスをテーブルにデコードし、HumanReadablePrinter に委譲 |

**主要処理フロー**:
1. **行 38-47**: `TablePrinter.PrintObj` がサーバレスポンスのテーブルデコードを試行
2. **行 58-94**: `decodeIntoTable` で Unstructured を metav1.Table に変換

#### Step 3: カラム定義と print 関数の登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | printers.go | `pkg/printers/internalversion/printers.go` | `AddHandlers` 関数（行 93〜108）で Pod 用のカラム定義（Name, Ready, Status, Restarts, Age + wide 用 IP, Node, Nominated Node, Readiness Gates）を登録 |

**主要処理フロー**:
- **行 94-104**: podColumnDefinitions の定義。Priority=0 は通常表示、Priority=1 は wide 表示
- **行 107-108**: `printPodList` と `printPod` を TableHandler に登録

#### Step 4: Pod テーブル行生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | printers.go | `pkg/printers/internalversion/printers.go` | `printPod` 関数（行 898〜1085）: Pod の Status 算出ロジック、Ready コンテナ数の計算、再起動回数の集計 |

**主要処理フロー**:
- **行 898-910**: 基本変数初期化、Phase / Reason の設定
- **行 913-917**: SchedulingGated 条件のチェック
- **行 930-986**: InitContainer の状態解析（restartable init container 対応含む）
- **行 988-1033**: 通常コンテナの状態解析、Status 文字列の最終決定
- **行 1035-1039**: DeletionTimestamp による Terminating / Unknown 判定
- **行 1041-1044**: Restarts 表示文字列の生成（最終再起動時刻の経過時間付き）
- **行 1046**: Name, Ready, Status, Restarts, Age をセルに追加
- **行 1047-1082**: Wide 出力時の追加カラム（IP, Node, Nominated Node, Readiness Gates）

#### Step 5: テーブルレンダリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | tableprinter.go | `staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go` | `HumanReadablePrinter.PrintObj`（行 80〜）で metav1.Table をタブ区切りテキストとして出力 |

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

```
kubectl get pods
    |
    +-- GetOptions.Run() [get.go]
           |
           +-- API Server Request (REST)
           |       |
           |       +-- TableConvertor.ConvertToTable() [サーバサイド]
           |               |
           |               +-- HumanReadableGenerator.GenerateTable() [tablegenerator.go 行78]
           |                       |
           |                       +-- printPodList() [printers.go 行886]
           |                               |
           |                               +-- printPod() [printers.go 行898]
           |
           +-- TablePrinter.PrintObj() [table_printer.go 行38]
                   |
                   +-- decodeIntoTable() [table_printer.go 行58]
                   |
                   +-- HumanReadablePrinter.PrintObj() [tableprinter.go]
                           |
                           +-- tabwriter による整列出力
```

### データフロー図

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

API Server (etcd)          printPod()                         標準出力 (stdout)
  Pod Object         -->   - Status 算出                  -->  テーブル形式テキスト
  (api.Pod)                - Ready 数計算                      NAME  READY  STATUS ...
                           - Restart 数集計                    pod1  1/1    Running ...
                           - TableRow 生成
                                 |
                           HumanReadablePrinter
                           - tabwriter 整列
                           - ヘッダー付与
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| printers.go | `pkg/printers/internalversion/printers.go` | ソース | Pod 用カラム定義と printPod / printPodList 関数（行 93-108, 886-1085） |
| tablegenerator.go | `pkg/printers/tablegenerator.go` | ソース | PrintHandler / HumanReadableGenerator のテーブル生成基盤 |
| tableprinter.go | `staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go` | ソース | HumanReadablePrinter によるテーブルレンダリング |
| table_printer.go | `staging/src/k8s.io/kubectl/pkg/cmd/get/table_printer.go` | ソース | TablePrinter: サーバレスポンスのテーブルデコード |
| get.go | `staging/src/k8s.io/kubectl/pkg/cmd/get/get.go` | ソース | kubectl get コマンドのエントリーポイント |
| printers_test.go | `pkg/printers/internalversion/printers_test.go` | テスト | printPod の各種ステータスパターンのテストケース |
