# 帳票設計書 9-Service一覧

## 概要

本ドキュメントは、Kubernetes の Service リソース一覧をテーブル形式で標準出力に出力する帳票の設計を定義する。`kubectl get svc` コマンド実行時に使用される。

### 本帳票の処理概要

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

**業務上の目的・背景**：Service は Pod へのネットワークアクセスを抽象化するリソースであり、クラスタ内外の通信におけるサービスディスカバリとロードバランシングの基盤となる。運用者が各サービスのタイプ（ClusterIP / NodePort / LoadBalancer / ExternalName）、IP アドレス、ポート設定を一覧で確認し、ネットワーク構成の把握やトラブルシューティングを行うために本帳票が必要となる。

**帳票の利用シーン**：サービスのネットワーク構成確認、LoadBalancer の外部 IP 確認、ポートマッピングの確認、サービスタイプの監査、セレクタの確認。

**主要な出力内容**：
1. Service 名（Name）
2. サービスタイプ（Type）
3. Cluster IP アドレス（Cluster-IP）
4. 外部 IP アドレス（External-IP）
5. ポート情報（Port(s)）
6. 作成からの経過時間（Age）
7. Wide 出力時: セレクタ

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

**帳票の利用者**：Kubernetes クラスタ管理者、ネットワークエンジニア、アプリケーション開発者、SRE。

## 帳票種別

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

## 利用画面

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

## 出力形式

### 基本仕様

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

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

| 項目 | 内容 |
|-----|------|
| カラム区切り | タブ文字（tabwriter） |
| ヘッダー表示 | デフォルト有効 |
| Wide 出力 | Selector が追加（Priority=1） |

## 帳票レイアウト

### レイアウト概要

```
┌──────────────────────────────────────────────────────────────────────────┐
│  NAME         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE │
├──────────────────────────────────────────────────────────────────────────┤
│  kubernetes   ClusterIP      10.96.0.1     <none>        443/TCP   30d │
│  web          LoadBalancer   10.96.1.100   203.0.113.1   80/TCP    5d  │
│  redis        NodePort       10.96.2.50    <none>        6379:31234/TCP 3d │
└──────────────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Name | Service の名前 | `obj.ObjectMeta.Name` | 文字列（name フォーマット） |
| 2 | Type | サービスタイプ | `obj.Spec.Type` | ClusterIP / NodePort / LoadBalancer / ExternalName |
| 3 | Cluster-IP | クラスタ内 IP | `obj.Spec.ClusterIPs[0]` | IP アドレス文字列 |
| 4 | External-IP | 外部 IP | `getServiceExternalIP(obj, wide)` | 複合ロジックによる文字列 |
| 5 | Port(s) | ポート情報 | `obj.Spec.Ports` | `makePortString` で整形 |
| 6 | Age | 経過時間 | `obj.ObjectMeta.CreationTimestamp` | `translateTimestampSince` |

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

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 7 | Selector | Pod セレクタ | `obj.Spec.Selector` | `labels.FormatLabels` で key=value 形式 | 可変 |

### フッター部

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

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| Namespace | 対象 Namespace | No |
| All Namespaces | 全 Namespace | No |
| Label Selector | ラベルフィルタ | No |
| Field Selector | フィールドフィルタ | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | Service 名（デフォルト） | 昇順 |

### 改ページ条件

改ページは発生しない。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| etcd: `/registry/services/specs/{namespace}/{name}` | Service オブジェクトの永続化ストア | N/A |

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

#### Service リソース（API: `v1/services`）

| 参照項目（フィールド） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| `metadata.name` | Name | N/A | Service の名前 |
| `metadata.creationTimestamp` | Age | N/A | 経過時間に変換 |
| `spec.type` | Type | N/A | ServiceType enum |
| `spec.clusterIPs` | Cluster-IP | N/A | 配列の先頭要素 |
| `spec.externalIPs` | External-IP | N/A | ClusterIP/NodePort 時に使用 |
| `spec.externalName` | External-IP | N/A | ExternalName タイプ時に使用 |
| `spec.ports` | Port(s) | N/A | makePortString で整形 |
| `spec.selector` | Selector (wide) | N/A | labels.FormatLabels |
| `status.loadBalancer` | External-IP | N/A | LoadBalancer タイプ時に使用 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Cluster-IP | `len(ClusterIPs) > 0 ? ClusterIPs[0] : "<none>"` | N/A | |
| External-IP | `getServiceExternalIP(obj, wide)` | N/A | タイプ別の複合ロジック（詳細後述） |
| Port(s) | `makePortString(obj.Spec.Ports)` | N/A | 空の場合 "<none>" |

#### External-IP 算出ロジック詳細（行 1343-1373）

| サービスタイプ | ロジック |
|-------------|---------|
| ClusterIP | ExternalIPs があれば結合、なければ "<none>" |
| NodePort | ExternalIPs があれば結合、なければ "<none>" |
| LoadBalancer | LB IP + ExternalIPs を結合。LB IP なく ExternalIPs もなければ "<pending>" |
| ExternalName | Spec.ExternalName を表示 |

#### Port(s) 表示ロジック（行 1375-1385）

- 各ポートを `{port}/{protocol}` 形式で表示
- NodePort が設定されている場合は `{port}:{nodePort}/{protocol}` 形式
- 複数ポートはカンマ区切り

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl get svc 実行] --> B[API サーバへリクエスト]
    B --> C[Service リスト取得]
    C --> D[printServiceList]
    D --> E[printService で各行生成]
    E --> F[getServiceExternalIP で External-IP 算出]
    E --> G[makePortString でポート文字列生成]
    F --> H[HumanReadablePrinter でテーブル出力]
    G --> H
    H --> I[標準出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | Service が存在しない | `No resources found in {namespace} namespace.` | 条件見直し |
| API エラー | 接続失敗 | API エラーメッセージ | kubeconfig 確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数件〜数百件 |
| 目標出力時間 | 即時 |
| 同時出力数上限 | N/A |

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

- Service 一覧取得には `services` リソースの `list` / `get` 権限が必要
- 外部 IP アドレスが表示されるため、ネットワーク構成情報の露出に注意

## 備考

- External-IP のロードバランサ IP 表示は、非 wide 時に 16 文字で切り詰めされる（loadBalancerWidth 定数）
- ClusterIP が "None" の場合はヘッドレスサービスを意味する
- Selector カラムは map[string]string 形式（LabelSelector ではない）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | printers.go | `pkg/printers/internalversion/printers.go` | serviceColumnDefinitions（行 199-207）: Name, Type, Cluster-IP, External-IP, Port(s), Age + wide: Selector |

**読解のコツ**: Service の Selector は RS/DS と異なり map[string]string 型であるため、metav1.FormatLabelSelector ではなく labels.FormatLabels が使用される。

#### Step 2: print 関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | printers.go | `pkg/printers/internalversion/printers.go` | `printService`（行 1387-1409）: ClusterIP の取得、getServiceExternalIP の呼び出し、makePortString の呼び出し |
| 2-2 | printers.go | `pkg/printers/internalversion/printers.go` | `getServiceExternalIP`（行 1343-1373）: サービスタイプ別の External-IP 算出ロジック |
| 2-3 | printers.go | `pkg/printers/internalversion/printers.go` | `makePortString`（行 1375-1385）: ポート情報のフォーマット |
| 2-4 | printers.go | `pkg/printers/internalversion/printers.go` | `loadBalancerStatusStringer`（行 1323〜）: LB ステータスの文字列化 |
| 2-5 | printers.go | `pkg/printers/internalversion/printers.go` | `printServiceList`（行 1411-1421）: Items を順に委譲 |

**主要処理フロー**:
- **行 1391**: Spec.Type を取得
- **行 1392-1395**: ClusterIPs の先頭要素を取得、空なら "<none>"
- **行 1397**: `getServiceExternalIP` で External-IP を算出
- **行 1398-1401**: `makePortString` でポート文字列を生成、空なら "<none>"
- **行 1403**: Name, Type, ClusterIP, ExternalIP, Ports, Age をセルに追加
- **行 1404-1406**: Wide 時に Selector を追加

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

```
kubectl get svc
    |
    +-- GetOptions.Run() [get.go]
           |
           +-- API Server Request
           |       |
           |       +-- printServiceList() [printers.go 行1411]
           |               |
           |               +-- printService() [printers.go 行1387]
           |                       |
           |                       +-- getServiceExternalIP() [printers.go 行1343]
           |                       |       |
           |                       |       +-- loadBalancerStatusStringer() [printers.go 行1323]
           |                       |
           |                       +-- makePortString() [printers.go 行1375]
           |                       +-- labels.FormatLabels() (wide)
           |
           +-- HumanReadablePrinter.PrintObj()
```

### データフロー図

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

API Server (etcd)          printService()                     標準出力 (stdout)
  Service Object       --> - ClusterIP 取得                --> テーブル形式テキスト
  (api.Service)            - getServiceExternalIP()            NAME TYPE CLUSTER-IP ...
                           - makePortString()                  svc1 ClusterIP 10.96.0.1 ...
                           - labels.FormatLabels (wide)
                           - TableRow 生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| printers.go | `pkg/printers/internalversion/printers.go` | ソース | Service 用カラム定義と print 関数（行 81-82, 199-210, 1323-1421） |
| tablegenerator.go | `pkg/printers/tablegenerator.go` | ソース | テーブル生成基盤 |
| tableprinter.go | `staging/src/k8s.io/cli-runtime/pkg/printers/tableprinter.go` | ソース | テーブルレンダリング |
| get.go | `staging/src/k8s.io/kubectl/pkg/cmd/get/get.go` | ソース | kubectl get コマンドエントリーポイント |
