# 機能設計書 87-ログ表示（logs）

## 概要

本ドキュメントは、kubectlの`logs`コマンドによるPodログ表示機能の設計を記述する。Pod内のコンテナのログを取得・表示し、ストリーミング表示や複数コンテナ/Pod対応も行う。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesクラスター上で稼働するアプリケーションのログを取得するための主要なデバッグツールを提供する。開発者や運用者がアプリケーションの動作状況を確認し、トラブルシューティングを行うために不可欠な機能である。

**機能の利用シーン**：アプリケーションログの確認、エラー原因の調査、リアルタイムログストリーミング、複数Podのログ一括取得、過去の特定期間のログ取得、前回のコンテナインスタンスのログ取得など。

**主要な処理内容**：
1. コマンドライン引数とフラグの解析（Complete）
2. PodLogOptionsの構築（ToLogOptions）
3. ログ取得リクエストの生成（LogsForObject/AllPodLogsForObject）
4. ログの消費（シーケンシャルまたはパラレル）
5. 出力（プレフィックス付きオプション含む）

**関連システム・外部連携**：API Server経由でkubeletからコンテナランタイムのログを取得する。

**権限による制御**：対象Podに対するget/logs権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | kubectl logs | 主機能 | Podのコンテナログを表示する主処理 |

## 機能種別

CRUD操作（Read）/ ログ取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| POD / TYPE/NAME | string | Yes（-lと排他） | Pod名またはリソースタイプ/名前 | -lとの排他 |
| -l / --selector | string | No | ラベルセレクター | POD名と排他 |
| -c / --container | string | No | コンテナ名 | --all-containersと排他 |
| --all-containers | bool | No | 全コンテナのログ表示 | -cと排他 |
| --all-pods | bool | No | 全Podのログ表示 | prefixをtrueに設定 |
| -f / --follow | bool | No | ストリーミングモード | - |
| -p / --previous | bool | No | 前回インスタンスのログ | - |
| --timestamps | bool | No | タイムスタンプ付き表示 | - |
| --tail | int64 | No | 末尾行数 | デフォルト-1（全行） |
| --since | duration | No | 指定期間内のログ | --since-timeと排他 |
| --since-time | string | No | 指定日時以降のログ（RFC3339） | --sinceと排他 |
| --limit-bytes | int64 | No | 最大バイト数 | 0以上 |
| --prefix | bool | No | Pod名/コンテナ名プレフィックス表示 | - |
| --ignore-errors | bool | No | ストリーミング時のエラーを非致命的に | - |
| --max-log-requests | int | No | 最大同時ストリーミング数 | デフォルト5 |
| --insecure-skip-tls-verify-backend | bool | No | kubeletのTLS検証をスキップ | - |
| --pod-running-timeout | duration | No | Pod起動待機タイムアウト | デフォルト20秒 |

### 入力データソース

- API Server経由のkubelet（コンテナログ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ログテキスト | string | コンテナのログ出力 |
| プレフィックス | string | [pod/NAME/CONTAINER] 形式のプレフィックス |

### 出力先

- 標準出力（stdout）：ログテキスト
- 標準エラー出力（stderr）：エラーメッセージ、リソース未検出メッセージ

## 処理フロー

### 処理シーケンス

```
1. NewCmdLogs: コマンド定義
2. Complete: オプション補完
   ├─ 引数解析（POD名、コンテナ名、セレクター）
   ├─ PodLogOptions構築（ToLogOptions）
   ├─ ResourceBuilder構築
   └─ Objectの取得
3. Validate: バリデーション
   ├─ sinceTime/sinceSecondsの排他チェック
   ├─ allContainers/container排他チェック
   └─ パラメータ値の範囲チェック
4. RunLogs: ログ取得の実行
   └─ RunLogsContext
       ├─ LogsForObject / AllPodLogsForObject: リクエスト生成
       ├─ [follow && 複数] parallelConsumeRequest
       │   └─ goroutine + io.Pipe による並列消費
       └─ [それ以外] sequentialConsumeRequest
```

### フローチャート

```mermaid
flowchart TD
    A[開始: RunLogs] --> B[context作成]
    B --> C[RunLogsContext]
    C --> D{AllPods?}
    D -->|Yes| E[AllPodLogsForObject]
    D -->|No| F[LogsForObject]
    E --> G{リクエスト数チェック}
    F --> G
    G --> H{follow && 複数?}
    H -->|Yes| I{max-log-requests超過?}
    I -->|Yes| J[エラー: 上限超過]
    I -->|No| K[parallelConsumeRequest]
    H -->|No| L[sequentialConsumeRequest]
    K --> M[goroutine × リクエスト数]
    M --> N[io.Pipe → stdout]
    L --> O[順次ストリーム読み取り → stdout]
    N --> P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | since/since-time排他 | --sinceと--since-timeは同時指定不可 | 常時 |
| BR-02 | allContainers/container排他 | --all-containers=trueとコンテナ名指定は排他 | 常時 |
| BR-03 | セレクターtailデフォルト | -l使用時でtail未指定の場合、デフォルト10行 | -l使用時 |
| BR-04 | allPods→prefix | --all-pods指定時に--prefixを自動でtrue | --all-pods時 |
| BR-05 | 並列上限 | follow + 複数Podの並列数はmax-log-requestsで制限 | follow && 複数Pod |
| BR-06 | インライン/フラグcontainer排他 | -cフラグとインライン引数のコンテナ名指定は排他 | 常時 |

### 計算ロジック

- selectorTail = 10（112行目）：セレクター使用時のデフォルトtail行数
- SinceSecondsの丸め: time.Duration.Round(time.Second).Seconds()で秒単位に丸め

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ログ取得 | kubelet（API Server経由） | SELECT | コンテナログの読み取り |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | NotFound | Podが存在しない | Pod名を確認 |
| - | バリデーションエラー | --sinceと--since-timeの同時指定 | いずれか一方を使用 |
| - | 並列上限エラー | フォロー対象Pod数が上限を超過 | --max-log-requestsを増加 |
| - | タイムアウト | Pod起動待機タイムアウト | --pod-running-timeoutを増加 |

### リトライ仕様

--ignore-errors=true時、ストリーミング中のエラーを非致命的として処理を継続する。

## トランザクション仕様

読み取り専用操作のため、トランザクション管理は不要。

## パフォーマンス要件

- 並列ストリーミングはio.PipeとgoroutineでI/Oを並列化
- prefixingWriterが原子的な書き込み（プレフィックス + データ）を保証し、並列出力の混在を防止
- DefaultConsumeRequestがbufio.Readerで行単位にバッファリング

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

- pods/logs サブリソースへのget権限が必要
- --insecure-skip-tls-verify-backendはkubeletのTLS検証をスキップするため、セキュリティリスクがある

## 備考

- polymorphichelpers.LogsForObjectFnにより、Deployment/ReplicaSet/Job等のリソースからPodを自動的に解決してログを取得可能
- containerNameFromRefSpecRegexpにより、ObjectReferenceのFieldPathからコンテナ名を抽出してプレフィックスに使用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go` | LogsOptions構造体（120-159行目）でオプション全体を把握 |

**読解のコツ**: LogsOptionsはPodLogOptions（core/v1 API）のフィールドと、kubectl固有のフィールド（AllPods、Prefix、MaxFollowConcurrency等）を含む。

#### Step 2: PodLogOptions構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go` | ToLogOptions関数（212-247行目）でCLIオプションからPodLogOptionsへの変換を理解 |

**主要処理フロー**:
- **213-218行目**: PodLogOptionsの基本フィールド設定
- **221-227行目**: SinceTimeのRFC3339パース
- **240-243行目**: セレクター使用時のデフォルトtail設定（10行）

#### Step 3: ログ取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go` | RunLogsContext関数（373-398行目）でログ取得のメインフローを理解 |
| 3-2 | logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go` | parallelConsumeRequest関数（400-429行目）で並列ストリーミングを理解 |
| 3-3 | logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go` | sequentialConsumeRequest関数（431-444行目）で逐次取得を理解 |

**主要処理フロー**:
- **376-380行目**: AllPods時とそれ以外のリクエスト生成分岐
- **385-392行目**: follow+複数Podの並列上限チェック
- **394-397行目**: 並列/逐次の分岐

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

```
NewCmdLogs (logs.go:172)
    │
    ├─ Complete (logs.go:249)
    │      ├─ ToLogOptions (logs.go:212)
    │      └─ f.NewBuilder().Do().Infos()
    │
    ├─ Validate (logs.go:327)
    │
    └─ RunLogs (logs.go:361)
           └─ RunLogsContext (logs.go:373)
                  ├─ AllPodLogsForObject / LogsForObject
                  ├─ [follow+複数] parallelConsumeRequest (logs.go:400)
                  │      ├─ goroutine × N
                  │      ├─ addPrefixIfNeeded (logs.go:446)
                  │      └─ DefaultConsumeRequest (logs.go:475)
                  └─ [それ以外] sequentialConsumeRequest (logs.go:431)
                         └─ DefaultConsumeRequest (logs.go:475)
```

### データフロー図

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

POD名/-l selector ──▶ Builder.Do() ──▶ LogsForObject
                                           │
                                     API Server ──▶ kubelet
                                           │
                                     ResponseWrapper
                                           │
                              ┌──── follow+複数? ────┐
                              │                       │
                    parallelConsumeRequest    sequentialConsumeRequest
                              │                       │
                         io.Pipe              addPrefixIfNeeded
                              │                       │
                              └──────── stdout ───────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| logs.go | `staging/src/k8s.io/kubectl/pkg/cmd/logs/logs.go` | ソース | コマンド定義・ログ取得処理 |
| logsforobject.go | `staging/src/k8s.io/kubectl/pkg/polymorphichelpers/logsforobject.go` | ソース | リソースタイプに応じたログ取得ヘルパー |
