# バッチ設計書 4-Pod GC Controller

## 概要

本ドキュメントは、終了したPodを定期的にガベージコレクションするPod GC Controllerの設計を記述する。

### 本バッチの処理概要

Pod GC Controllerは、Kubernetesクラスタ内の不要なPodを定期的に検出・削除するコントローラーである。孤立Pod、終了済みPod、out-of-serviceノード上のterminatingPodを対象とする。

**業務上の目的・背景**：クラスタ運用において、ノード障害やPodの正常終了後にPodリソースがetcdに蓄積される。Pod GC Controllerは、terminatedPodの上限数管理、孤立Pod（所属ノードが存在しない）の検出・削除、out-of-serviceノード上のterminatingPodの強制削除を行い、クラスタリソースの健全性を維持する。

**バッチの実行タイミング**：20秒周期（gcCheckPeriod）で定期実行される。ノードイベントに基づくDelayingQueueも使用する。

**主要な処理内容**：
1. 全Pod/Node一覧の取得（labels.Everything()でリスト）
2. gcTerminated: 終了済みPodの上限数管理（terminatedPodThresholdを超過した分を削除）
3. gcTerminating: out-of-serviceノード（node.kubernetes.io/out-of-service taint）上のterminatingPodの削除
4. gcOrphaned: 孤立Pod（所属ノードが存在しない）の検出・削除（quarantineTime=40秒の猶予付き）
5. gcUnscheduledTerminating: 未スケジュールのterminatingPodの削除

**前後の処理との関連**：Job ControllerやReplicaSet Controller等が管理するPodが対象となる。ノードの状態はNode Lifecycle Controllerが管理する。

**影響範囲**：Podリソースの削除。全Namespaceが対象。

## バッチ種別

ガベージコレクション型（定期的リソースクリーンアップ）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 20秒周期（gcCheckPeriod） |
| 実行時刻 | 常時稼働 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 定期タイマー（wait.UntilWithContext） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| kube-controller-manager起動 | Pod GC Controllerはkube-controller-manager内で起動 |
| Informerキャッシュ同期完了 | PodとNodeのInformerキャッシュが同期済みであること |
| API Server接続 | kube-apiserverと通信可能であること |

### 実行可否判定

Informerキャッシュの同期完了後に定期実行を開始する。terminatedPodThreshold > 0の場合のみgcTerminatedが実行される。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| terminatedPodThreshold | int | Yes | なし | 終了済みPodの保持上限数 |
| gcCheckPeriod | time.Duration | No | 20秒 | GCチェック周期 |
| quarantineTime | time.Duration | No | 40秒 | 孤立Pod判定の猶予時間 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Pod Informer | Kubernetes API (core/v1 Pod) | 全Podの一覧取得 |
| Node Informer | Kubernetes API (core/v1 Node) | 全Nodeの一覧取得 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Pod (削除) | Kubernetes API (core/v1 Pod) | 不要Podの削除リクエスト |

### 出力ファイル仕様

ファイル出力はなし。

## 処理フロー

### 処理シーケンス

```
1. コントローラー初期化（NewPodGC / NewPodGCInternal）
   └─ Informer設定、nodeQueue作成、メトリクス登録
2. Run起動
   └─ キャッシュ同期待ち、gcループgoroutine起動
3. gc処理（20秒周期）
   ├─ 全Pod/Node一覧取得
   ├─ gcTerminated: terminatedPodThreshold超過分を削除
   ├─ gcTerminating: out-of-serviceノード上のterminatingPod削除
   ├─ gcOrphaned: 孤立Pod検出・削除
   └─ gcUnscheduledTerminating: 未スケジュールterminatingPod削除
```

### フローチャート

```mermaid
flowchart TD
    A[gc周期トリガー 20秒] --> B[全Pod/Node一覧取得]
    B --> C{terminatedPodThreshold > 0?}
    C -->|Yes| D[gcTerminated: 超過分削除]
    C -->|No| E[スキップ]
    D --> F[gcTerminating: out-of-service Pod削除]
    E --> F
    F --> G[gcOrphaned: 孤立Pod削除]
    G --> H[gcUnscheduledTerminating: 未スケジュールPod削除]
    H --> A
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Pod一覧取得 | etcd (pods) | SELECT | Informerキャッシュから全Pod取得 |
| Node一覧取得 | etcd (nodes) | SELECT | Informerキャッシュから全Node取得 |
| Pod削除 | etcd (pods) | DELETE | 不要Podの削除 |
| Pod Status更新 | etcd (pods) | PATCH | 削除前にPhase=Failedに設定（markFailedAndDeletePod） |

### テーブル別操作詳細

#### Pod (core/v1)

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | status.phase | Succeeded/Failed判定 | isPodTerminated |
| SELECT | metadata.deletionTimestamp | 非nil判定 | isPodTerminating |
| PATCH | status.phase | Failed | 削除前にFailedマーク |
| DELETE | - | GC対象Pod | 各gcサブ関数で実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Pod一覧取得エラー | API Serverエラー | エラーログ、次周期で再試行 |
| - | Node一覧取得エラー | API Serverエラー | エラーログ、次周期で再試行 |
| - | Pod削除失敗 | 権限不足等 | エラーログ、メトリクスカウント |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 定期実行による暗黙的リトライ（20秒周期） |
| リトライ間隔 | 20秒（gcCheckPeriod） |
| リトライ対象エラー | 全エラー（次周期で再評価） |

### 障害時対応

定期実行のため、1回のGCサイクルで失敗しても次のサイクルで自動リトライされる。孤立Pod判定はquarantineTime（40秒）の猶予を設けており、一時的なノード情報の遅延による誤削除を防止する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | Pod単位（各Pod個別に削除） |
| コミットタイミング | 各Pod削除APIコール時 |
| ロールバック条件 | なし（個別Pod削除は独立） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | クラスタ内全Pod数に依存 |
| 目標処理時間 | 20秒（gcCheckPeriod）以内 |
| メモリ使用量上限 | Informerキャッシュサイズに依存 |

## 排他制御

- 各GCサブ関数内でsync.WaitGroupによる並行Pod削除
- Pod削除はgoroutineで並行実行
- API Serverの楽観的並行性制御

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | コントローラー起動時 | "Starting GC controller" |
| 進捗ログ | gc実行時（V4） | "GC'ing terminating pods that are on out-of-service nodes" |
| 終了ログ | コントローラー停止時 | "Shutting down GC controller" |
| エラーログ | エラー発生時 | "Error while listing all pods", "Failed to delete terminating pod" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| deletingPodsTotal | メトリクス（Prometheusで監視、ラベル: namespace, reason） | クラスタ管理者 |
| deletingPodsErrorTotal | メトリクス（Prometheusで監視） | クラスタ管理者 |

## 備考

- ソースコード: `pkg/controller/podgc/gc_controller.go`
- メトリクス: `pkg/controller/podgc/metrics/`
- GC理由ラベル: PodGCReasonTerminatingOutOfService等
- byEvictionAndCreationTimestampによるソート: 削除対象Podを作成時刻とeviction状態でソート
- NodeのTaint `node.kubernetes.io/out-of-service` をチェック
