# 帳票設計書 14-Node一覧

## 概要

本ドキュメントは、Kubernetes Nodeリソースの一覧をテーブル形式で出力する帳票の設計書である。`kubectl get nodes` コマンド実行時にNodeリソースの情報を人間が読みやすいテーブル形式で標準出力に表示する。

### 本帳票の処理概要

Nodeリソースの一覧情報を取得し、テーブル形式で出力する処理を行う。

**業務上の目的・背景**：NodeはKubernetesクラスタを構成するワーカーマシンを表すリソースである。クラスタの健全性を監視するためには、各Nodeの状態（Ready/NotReady）、ロール（control-plane/workerなど）、Kubeletバージョンを一覧で把握することが不可欠である。クラスタのスケールアウト状況やアップグレード進行状況の確認にも利用される。障害対応時には最初に確認されるリソースの一つである。

**帳票の利用シーン**：クラスタ内のNode状態を一覧確認する場合、NotReadyなNodeの特定、SchedulingDisabledなNodeの確認、Kubeletバージョンの確認、クラスタアップグレード状況の把握に利用される。

**主要な出力内容**：
1. Node名
2. ステータス（Ready/NotReady/SchedulingDisabled等の組み合わせ）
3. ロール（control-plane, worker等）
4. 作成からの経過時間（Age）
5. Kubeletバージョン
6. Internal-IP、External-IP、OS-Image、Kernel-Version、Container-Runtime（Wide出力時）

**帳票の出力タイミング**：ユーザが `kubectl get nodes` または `kubectl get no` コマンドを実行した際に出力される。

**帳票の利用者**：Kubernetesクラスタ管理者、SREエンジニア、インフラストラクチャエンジニア

## 帳票種別

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

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLIターミナル | - | `kubectl get nodes` コマンド実行 |

## 出力形式

### 基本仕様

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

## 帳票レイアウト

### レイアウト概要

タブ区切りのテーブル形式で、通常モードとWideモードの2パターンが存在する。

```
[通常モード]
NAME           STATUS                     ROLES           AGE   VERSION
master-01      Ready                      control-plane   30d   v1.29.0
worker-01      Ready                      <none>          28d   v1.29.0
worker-02      Ready,SchedulingDisabled   worker          28d   v1.29.0

[Wideモード (-o wide)]
NAME        STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION          CONTAINER-RUNTIME
master-01   Ready    control-plane   30d   v1.29.0   192.168.1.10   <none>        Ubuntu 22.04.3 LTS   5.15.0-91 (amd64)       containerd://1.7.11
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | NAME | Node名 | `obj.Name` | 文字列 |
| 2 | STATUS | Nodeの状態 | `obj.Status.Conditions` + `obj.Spec.Unschedulable` | Ready/NotReady,SchedulingDisabled等 |
| 3 | ROLES | Nodeのロール | `obj.Labels`（node-role.kubernetes.io/*プレフィックス等） | カンマ区切り文字列、未設定時`<none>` |
| 4 | AGE | 作成からの経過時間 | `obj.CreationTimestamp` | 相対時間（例: 30d, 5h） |
| 5 | VERSION | Kubeletバージョン | `obj.Status.NodeInfo.KubeletVersion` | 文字列 |
| 6 | INTERNAL-IP | 内部IPアドレス（Wide時のみ） | `obj.Status.Addresses`（NodeInternalIP型） | IPアドレス、未設定時`<none>` |
| 7 | EXTERNAL-IP | 外部IPアドレス（Wide時のみ） | `obj.Status.Addresses`（NodeExternalIP型） | IPアドレス、未設定時`<none>` |
| 8 | OS-IMAGE | OS イメージ名（Wide時のみ） | `obj.Status.NodeInfo.OSImage` | 文字列、空文字時`<unknown>` |
| 9 | KERNEL-VERSION | カーネルバージョン（Wide時のみ） | `obj.Status.NodeInfo.KernelVersion` + `obj.Status.NodeInfo.Architecture` | "バージョン (アーキテクチャ)"形式 |
| 10 | CONTAINER-RUNTIME | コンテナランタイムバージョン（Wide時のみ） | `obj.Status.NodeInfo.ContainerRuntimeVersion` | 文字列、空文字時`<unknown>` |

### 明細部

ヘッダーと同一カラムで各Nodeリソースの情報を1行ずつ出力する。

### フッター部

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

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| リソースタイプ | Nodeリソースを対象とする | Yes |
| ラベルセレクタ | `-l` オプションで指定されたラベルによるフィルタリング | No |
| フィールドセレクタ | `--field-selector` オプションで指定されたフィールドによるフィルタリング | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | APIサーバからの返却順（デフォルト） | 昇順 |

### 改ページ条件

改ページは発生しない（ターミナル出力のため）。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| etcd: /registry/minions/{name} | Nodeリソースの保存先 | リソース名で直接参照 |

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

#### Node リソース

| 参照項目（フィールド名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| `metadata.name` | NAME | 全件取得 | そのまま文字列出力 |
| `metadata.creationTimestamp` | AGE | 全件取得 | 相対時間に変換 |
| `metadata.labels` | ROLES | 全件取得 | findNodeRoles関数で解析 |
| `spec.unschedulable` | STATUS | 全件取得 | trueの場合「SchedulingDisabled」を付加 |
| `status.conditions[*]` | STATUS | 全件取得 | NodeReady Conditionの状態を判定 |
| `status.nodeInfo.kubeletVersion` | VERSION | 全件取得 | そのまま文字列出力 |
| `status.addresses[*]` | INTERNAL-IP, EXTERNAL-IP | Wide時 | アドレスタイプで分類 |
| `status.nodeInfo.osImage` | OS-IMAGE | Wide時 | 空文字時`<unknown>` |
| `status.nodeInfo.kernelVersion` | KERNEL-VERSION | Wide時 | Architecture付加 |
| `status.nodeInfo.architecture` | KERNEL-VERSION | Wide時 | カーネルバージョンに括弧付きで付加 |
| `status.nodeInfo.containerRuntimeVersion` | CONTAINER-RUNTIME | Wide時 | 空文字時`<unknown>` |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| STATUS | NodeReady Conditionがtrue -> "Ready"、false -> "NotReady"、Unschedulable -> 末尾に",SchedulingDisabled"追加 | N/A | 複数条件のカンマ区切り結合 |
| ROLES | node-role.kubernetes.io/<role>ラベルまたはkubernetes.io/role=<role>ラベルから抽出 | N/A | findNodeRoles関数で取得、ソートして返却 |
| AGE | 現在時刻 - CreationTimestamp | N/A | `translateTimestampSince`関数で変換 |
| KERNEL-VERSION | kernelVersion + " (" + architecture + ")" | N/A | architectureが空でない場合のみ括弧付加 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl get nodes 実行] --> B[コマンドパラメータ解析]
    B --> C[API Server へ LIST リクエスト]
    C --> D[Node リソース一覧取得]
    D --> E[printNode 関数で各行生成]
    E --> F[Condition解析でSTATUS生成]
    F --> G[findNodeRolesでROLES生成]
    G --> H{Wideモード?}
    H -->|Yes| I[IP/OS/Kernel/Runtime情報追加]
    H -->|No| J[基本カラムのみ]
    I --> K[HumanReadablePrinter でテーブル整形]
    J --> K
    K --> L[標準出力へ出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| リソース未存在 | 指定した名前のNodeが存在しない | `Error from server (NotFound): nodes "<名前>" not found` | 正しいリソース名を指定 |
| 権限不足 | Nodeリソースへのアクセス権限がない | `Error from server (Forbidden): ...` | RBACで適切な権限を付与 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数件〜数千件 |
| 目標出力時間 | 1秒以内（100件以下） |
| 同時出力数上限 | N/A（CLIコマンド） |

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

NodeリソースにはIPアドレス、OS情報、カーネルバージョンなどインフラストラクチャの詳細情報が含まれる。Wide出力時にはこれらが表示されるため、アクセス権限の管理が重要。Nodeリソースの閲覧にはRBACによる `get` / `list` 権限が必要。Nodeはクラスタスコープリソースである。

## 備考

- Nodeはクラスタスコープリソースであり、Namespace指定は不要
- ロール判定は `node-role.kubernetes.io/<role>` ラベルまたは `kubernetes.io/role` ラベルに基づく
- Conditionsが空の場合はステータスは「Unknown」と表示される
- Wide出力時のKERNEL-VERSIONにはアーキテクチャ情報が括弧付きで付加される

---

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

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

### 推奨読解順序

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

NodeリソースのAPI型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `staging/src/k8s.io/api/core/v1/types.go` | Node, NodeSpec, NodeStatus, NodeCondition, NodeAddress, NodeSystemInfo構造体の定義 |

**読解のコツ**: NodeStatusには`Conditions`（Ready状態等）、`Addresses`（IP一覧）、`NodeInfo`（システム情報）が含まれる。

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

テーブル出力のためのカラム定義と印刷関数の登録を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | printers.go | `pkg/printers/internalversion/printers.go` | AddHandlers関数内のnodeColumnDefinitions（行250-264） |

**主要処理フロー**:
1. **行250-260**: nodeColumnDefinitionsでカラム定義（Name, Status, Roles, Age, Version + Wide: Internal-IP, External-IP, OS-Image, Kernel-Version, Container-Runtime）
2. **行263-264**: TableHandlerにprintNodeとprintNodeListを登録

#### Step 3: 印刷関数を理解する

実際のテーブル行生成ロジックを読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | printers.go | `pkg/printers/internalversion/printers.go` | printNode関数（行1952-2004） |

**主要処理フロー**:
- **行1957-1972**: Conditionマップを作成し、NodeReady条件からステータス文字列を生成
- **行1973-1974**: Conditionsが空の場合は「Unknown」
- **行1976-1978**: `Spec.Unschedulable`がtrueなら「SchedulingDisabled」を追加
- **行1980-1983**: `findNodeRoles`でロールを取得、未設定なら`<none>`
- **行1985**: 基本カラム（Name, Status, Roles, Age, Version）をCellsに追加
- **行1986-2001**: Wideモード時にIP、OS、カーネル、ランタイム情報を追加

#### Step 4: ヘルパー関数を理解する

ロール判定やIPアドレス取得のヘルパー関数を読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | printers.go | `pkg/printers/internalversion/printers.go` | findNodeRoles関数（行2033-2047）、getNodeInternalIP関数（行2018-2027）、getNodeExternalIP関数（行2007-2016） |

**主要処理フロー**:
- **行2033-2047**: `node-role.kubernetes.io/<role>`ラベルまたは`kubernetes.io/role`ラベルからロールを抽出
- **行2018-2027**: NodeInternalIP型のアドレスを返却、なければ`<none>`
- **行2007-2016**: NodeExternalIP型のアドレスを返却、なければ`<none>`

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

```
kubectl get nodes
    |
    +-- NewCmdGet (pkg/cmd/get/get.go)
    |      +-- RunGet
    |             +-- API Server LIST /api/v1/nodes
    |
    +-- AddHandlers (pkg/printers/internalversion/printers.go:93)
    |      +-- TableHandler(nodeColumnDefinitions, printNode) (行263)
    |
    +-- printNode (pkg/printers/internalversion/printers.go:1952)
    |      +-- findNodeRoles (行2033)
    |      +-- getNodeInternalIP (行2018) [Wide時]
    |      +-- getNodeExternalIP (行2007) [Wide時]
    |      +-- translateTimestampSince
    |
    +-- HumanReadablePrinter.PrintObj (cli-runtime/pkg/printers/tableprinter.go)
           +-- tabwriter による整形出力
```

### データフロー図

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

API Server               printNode()                      標準出力(stdout)
(Node                    行1952-2004                      テーブル形式
 リソース一覧)   -------> - Condition解析           -------> NAME | STATUS | ROLES | AGE | VERSION
                         - ロール判定                      (Wide時: + INTERNAL-IP | EXTERNAL-IP |
                         - IP取得(Wide時)                           OS-IMAGE | KERNEL-VERSION |
                         - NodeInfo取得(Wide時)                     CONTAINER-RUNTIME)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| printers.go | `pkg/printers/internalversion/printers.go` | ソース | カラム定義、printNode関数、findNodeRoles、getNodeInternalIP、getNodeExternalIP |
| tableprinter.go | `staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go` | ソース | HumanReadablePrinterによるテーブル出力エンジン |
| types.go | `staging/src/k8s.io/api/core/v1/types.go` | ソース | Node API型定義 |
| printers_test.go | `pkg/printers/internalversion/printers_test.go` | テスト | printNodeのテストケース |
