# 帳票設計書 72-Podリソース使用状況

## 概要

本ドキュメントは、Kubernetesクラスタ内のPodリソース使用状況（CPU/メモリ/スワップ）をテーブル形式で標準出力に出力する帳票の設計書である。`kubectl top pod` コマンドとして提供される。

### 本帳票の処理概要

本帳票は、Kubernetesクラスタ内の各Podのリソース消費状況をリアルタイムに一覧表示する機能を提供する。Pod単位だけでなくコンテナ単位の表示や、全Namespace横断表示にも対応する。

**業務上の目的・背景**：アプリケーションのリソース消費を把握することは、適切なリソースRequest/Limitの設定、HPA/VPAによるオートスケーリングの検証、パフォーマンス問題の特定において不可欠である。本帳票は、Metrics Serverから取得したPodメトリクスを元に、Pod/コンテナごとのCPU・メモリ使用量を表示し、運用者がアプリケーションのリソース状況を迅速に確認できるようにすることを目的としている。

**帳票の利用シーン**：アプリケーション開発者や運用者がPodのリソース使用状況をスポットチェックする場合に利用される。例えば、メモリリークの疑いがあるPodの調査、CPU使用量に基づくHPAの動作検証、複数コンテナ構成のPodでどのコンテナがリソースを消費しているかの特定などに使用される。

**主要な出力内容**：
1. Namespace（NAMESPACE）: --all-namespaces時のみ
2. Pod名（NAME）
3. CPU使用量（CPU(cores)）: ミリコア単位
4. メモリ使用量（MEMORY(bytes)）: MiB単位
5. スワップ使用量（SWAP(bytes)）: --show-swapオプション時のみ、MiB単位
6. コンテナ名: --containersオプション時のみ
7. 合計行: --sumオプション時のみ

**帳票の出力タイミング**：ユーザが `kubectl top pod` コマンドを実行した時点で即座に出力される。

**帳票の利用者**：アプリケーション開発者、クラスタ管理者、SRE

## 帳票種別

一覧表（メトリクスサマリ）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLIターミナル | - | `kubectl top pod [NAME \| -l label]` コマンド実行 |

## 出力形式

### 基本仕様

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

### テーブル出力仕様

| 項目 | 内容 |
|-----|------|
| 区切り文字 | タブ文字（tabwriter使用） |
| ヘッダー | デフォルト表示、--no-headersで非表示 |
| ソート | --sort-byでcpu/memoryによるソート可能 |

## 帳票レイアウト

### レイアウト概要

Pod単位でリソース使用量を1行1Podで表示する。--containersオプション時はコンテナ単位で展開表示する。

```
┌────────────────────────────────────────────────────────────┐
│  ヘッダー行（--no-headersで省略可）                            │
├────────────────────────────────────────────────────────────┤
│  [NAMESPACE]  NAME      CPU(cores)  MEMORY(bytes)          │
│  default      pod-a     100m        256Mi                   │
│  default      pod-b     200m        512Mi                   │
│                         ________    ________                │
│                         300m        768Mi       (--sum時)    │
└────────────────────────────────────────────────────────────┘
```

--containersオプション時:
```
┌──────────────────────────────────────────────────────────────┐
│  [NAMESPACE]  POD    NAME         CPU(cores)  MEMORY(bytes)  │
│  default      pod-a  container1   80m         200Mi          │
│  default      pod-a  container2   20m         56Mi           │
│  default      pod-b  container1   200m        512Mi          │
└──────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | NAMESPACE | Namespace名（-A時のみ） | PodMetrics.Namespace | 文字列 |
| 2 | POD | Pod名（--containers時のみ追加列） | PodMetrics.Name | 文字列 |
| 3 | NAME | Pod名またはコンテナ名 | PodMetrics.Name / Container.Name | 文字列 |
| 4 | CPU(cores) | CPU使用量 | Container.Usage[cpu]の合計 | {値}m（ミリコア） |
| 5 | MEMORY(bytes) | メモリ使用量 | Container.Usage[memory]の合計 | {値}Mi |
| 6 | SWAP(bytes) | スワップ使用量（--show-swap時） | Container.Usage[swap]の合計 | {値}Mi |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | NAMESPACE | Namespace名 | PodMetrics.Namespace | 文字列 | 可変 |
| 2 | POD | Pod名（コンテナ表示時） | PodMetrics.Name | 文字列 | 可変 |
| 3 | NAME | Pod名/コンテナ名 | Name | 文字列 | 可変 |
| 4 | CPU(cores) | CPU使用量 | Usage[cpu].MilliValue() | {値}m | 可変 |
| 5 | MEMORY(bytes) | メモリ使用量 | Usage[memory].Value()/(1024*1024) | {値}Mi | 可変 |

### フッター部

--sumオプション指定時のみ合計行が出力される。

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 区切り線 | ________ | - | 各数値列に下線 |
| 2 | 合計CPU | CPU使用量合計 | 全Podの合計 | {値}m |
| 3 | 合計MEMORY | メモリ使用量合計 | 全Podの合計 | {値}Mi |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ResourceName | 特定のPod名を指定して絞り込み | No |
| LabelSelector (-l) | ラベルセレクタによるPod絞り込み | No |
| FieldSelector (--field-selector) | フィールドセレクタによるPod絞り込み | No |
| Namespace | 名前空間の指定（デフォルトは現在のコンテキスト） | No |
| AllNamespaces (-A) | 全Namespace横断で表示 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | --sort-by=cpu: CPU使用量 | 降順 |
| 1 | --sort-by=memory: メモリ使用量 | 降順 |
| - | デフォルト: Metrics APIからの返却順 | - |

### 改ページ条件

改ページは発生しない（標準出力へのストリーム出力）。

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

### 参照テーブル一覧

本帳票はデータベースではなくKubernetes APIを参照する。

| API | 用途 | 結合条件 |
|-----|------|---------|
| Metrics API (v1beta1) PodMetricses | Podのリソース使用量取得 | Namespace/Pod名 |
| Core API v1 Pods | Pod作成時刻の確認（メトリクス未取得時の診断用） | Namespace/Pod名 |

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

#### Metrics API - PodMetrics

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| Name | NAME | ResourceName指定時は単一Get、それ以外はList | ラベル/フィールドセレクタ適用可 |
| Namespace | NAMESPACE | -A指定時はNamespaceAll | - |
| Containers[].Name | NAME（コンテナ表示時） | --containers指定時 | - |
| Containers[].Usage[cpu] | CPU(cores) | - | Pod単位では全コンテナの合計 |
| Containers[].Usage[memory] | MEMORY(bytes) | - | Pod単位では全コンテナの合計 |

#### Core API - Pod（メトリクス未取得時の診断用）

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| CreationTimestamp | - | メトリクス0件時 | 作成から2分以内ならメトリクス未準備 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Pod CPU使用量 | sum(Container[i].Usage[cpu]) for all containers | - | MilliValue()で取得 |
| Pod メモリ使用量 | sum(Container[i].Usage[memory]) for all containers | - | Value()/(1024*1024)でMiB変換 |
| 合計CPU（--sum） | sum(Pod[j].CPU使用量) for all pods | - | ResourceAdderで計算 |
| 合計メモリ（--sum） | sum(Pod[j].メモリ使用量) for all pods | - | ResourceAdderで計算 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl top pod コマンド実行] --> B[Complete: クライアント初期化]
    B --> C[Validate: パラメータ検証]
    C --> D[RunTopPod: Metrics API可用性確認]
    D --> E{Metrics API利用可能?}
    E -->|No| F[エラー: Metrics API not available]
    E -->|Yes| G[getMetricsFromMetricsAPI: メトリクス取得]
    G --> H{メトリクス件数 > 0?}
    H -->|No| I[verifyEmptyMetrics: 原因診断]
    I --> J{Pod作成から2分以上?}
    J -->|Yes| K[エラー: Metrics not available for pod]
    J -->|No| L[メッセージ: No resources found]
    H -->|Yes| M[PrintPodMetrics: テーブル出力]
    M --> N[終了]
    L --> N
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| Metrics API未対応 | クラスタにMetrics Serverが未導入 | "Metrics API not available" | Metrics Serverをインストール |
| メトリクス未準備 | Pod作成から2分以上経過してもメトリクスなし | "Metrics not available for pod {ns}/{name}, age: {age}" | Metrics Server/kubeletの稼働確認 |
| メトリクス未準備 | Pod作成から2分未満でメトリクスなし | "metrics not available yet" | 時間を置いて再実行 |
| リソースなし | 該当するPodが存在しない | "No resources found [in {ns} namespace.]" | Namespace/セレクタの確認 |
| パラメータエラー | --sort-byにcpu/memory以外を指定 | "--sort-by accepts only cpu or memory" | cpu/memoryのいずれかを指定 |
| パラメータエラー | NAMEとセレクタを同時指定 | "only one of NAME or selector can be provided" | いずれか一方のみ指定 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数十〜数万Pod |
| 目標出力時間 | Metrics API応答速度に依存（通常数秒以内） |
| 同時出力数上限 | CLIコマンドのため制限なし |

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

- Metrics APIへのアクセスにはRBACによる適切な権限が必要（pods/metrics リソースへのget/list権限）
- `--use-protocol-buffers`オプション（デフォルト有効）によりprotobuf形式で通信し、転送効率を向上
- 出力データにはPod名/Namespace/コンテナ名とリソース使用量のみが含まれ、機密情報は含まれない

## 備考

- Metrics Serverは別途クラスタにインストールが必要
- メトリクスパイプラインの遅延により、Pod作成後数分間はメトリクスが利用できない場合がある（metricsCreationDelay = 2分）
- Pod単位のメトリクスは全コンテナのUsageを合算したもの
- Node帳票（No.71）と異なり、Podメトリクスには使用率（%）列がない（Allocatableに対する割合の概念がないため）

---

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

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

### 推奨読解順序

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

まず、帳票出力に使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | top_pod.go | `staging/src/k8s.io/kubectl/pkg/cmd/top/top_pod.go` | TopPodOptions構造体（行45-64）でコマンドオプションの全体像を把握。AllNamespaces, PrintContainers, Sumなどの表示制御フラグに注目 |
| 1-2 | metrics_printer.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_printer.go` | TopCmdPrinter構造体（行44-51）でpodColumnsフィールド（行61: NAME, CPU(cores), MEMORY(bytes)）を確認 |

**読解のコツ**: TopPodOptionsはTopNodeOptionsと構造が似ているが、Namespace/AllNamespaces/PrintContainers/Sum等の追加フィールドがある点に注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | top_pod.go | `staging/src/k8s.io/kubectl/pkg/cmd/top/top_pod.go` | NewCmdTopPod関数（行91-123）でコマンドフラグ定義を確認。--containers, -A, --sum等のフラグに注目 |

**主要処理フロー**:
1. **行106-109**: Run関数内でComplete -> Validate -> RunTopPod の順に実行
2. **行125-159**: Complete関数でMetricsClient、PodClient、Printerを初期化
3. **行173-223**: RunTopPod関数でメトリクス取得からテーブル出力まで実行

#### Step 3: メトリクス取得と空結果診断を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | top_pod.go | `staging/src/k8s.io/kubectl/pkg/cmd/top/top_pod.go` | getMetricsFromMetricsAPI関数（行225-250）でPodMetrics取得を理解 |
| 3-2 | top_pod.go | `staging/src/k8s.io/kubectl/pkg/cmd/top/top_pod.go` | verifyEmptyMetrics関数（行252-279）とcheckPodAge関数（行281-290）で空結果時の診断ロジックを理解 |

**主要処理フロー**:
- **行206-220**: メトリクス0件時にverifyEmptyMetricsを呼び出し、Pod年齢をチェックして適切なエラーメッセージを返す
- **行281-290**: Pod作成から2分（metricsCreationDelay）経過しているかで挙動が変わる

#### Step 4: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | metrics_printer.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_printer.go` | PrintPodMetrics関数（行105-146）でPodメトリクスのテーブル出力処理を理解 |
| 4-2 | metrics_printer.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_printer.go` | getPodMetrics関数（行188-202）でコンテナUsageの合算ロジックを理解 |
| 4-3 | metrics_printer.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_printer.go` | printPodResourcesSum関数（行260-276）で--sum時の合計行出力を理解 |

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

```
NewCmdTop (top.go:69)
    |
    +-- NewCmdTopPod (top_pod.go:91)
            |
            +-- Complete (top_pod.go:125)
            |       +-- KubernetesClientSet
            |       +-- metricsclientset.NewForConfig
            |       +-- NewTopCmdPrinter (metrics_printer.go:53)
            |
            +-- Validate (top_pod.go:161)
            |
            +-- RunTopPod (top_pod.go:173)
                    +-- SupportedMetricsAPIVersionAvailable (top.go:84)
                    +-- getMetricsFromMetricsAPI (top_pod.go:225)
                    |       +-- MetricsV1beta1().PodMetricses(ns).Get/List
                    |       +-- Convert_v1beta1_PodMetricsList_To_metrics_PodMetricsList
                    +-- verifyEmptyMetrics (top_pod.go:252) [メトリクス0件時]
                    |       +-- PodClient.Pods(ns).Get/List
                    |       +-- checkPodAge (top_pod.go:281)
                    +-- PrintPodMetrics (metrics_printer.go:105)
                            +-- NewPodMetricsSorter / sort.Sort
                            +-- printSinglePodMetrics (metrics_printer.go:162)
                            |       +-- getPodMetrics (metrics_printer.go:188)
                            +-- printSinglePodContainerMetrics (metrics_printer.go:174)
                            +-- printPodResourcesSum (metrics_printer.go:260) [--sum時]
```

### データフロー図

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

Metrics API               RunTopPod()
(PodMetrics) ----------> getMetricsFromMetricsAPI() --------+
                                                             |
                          getPodMetrics()                     |
                          (コンテナUsage合算) ----------------+--> PrintPodMetrics() --> stdout
                                                             |    (タブ区切りテーブル)
Core API                  verifyEmptyMetrics()               |
(Pods) ----------------> checkPodAge() [0件時の診断] --------+
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| top.go | `staging/src/k8s.io/kubectl/pkg/cmd/top/top.go` | ソース | topコマンド親定義、API可用性チェック |
| top_pod.go | `staging/src/k8s.io/kubectl/pkg/cmd/top/top_pod.go` | ソース | top podサブコマンド本体 |
| metrics_printer.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_printer.go` | ソース | メトリクステーブル出力ロジック |
| metrics_sorter.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_sorter.go` | ソース | メトリクスソート処理 |
| metrics_resource_adder.go | `staging/src/k8s.io/kubectl/pkg/metricsutil/metrics_resource_adder.go` | ソース | --sum用リソース合算処理 |
