# 機能設計書 23-HPAコントローラー

## 概要

本ドキュメントは、KubernetesのHorizontal Pod Autoscaler（HPA）コントローラーの機能設計を記述する。HPAコントローラーは、メトリクスに基づいてDeployment、ReplicaSet等のPodレプリカ数を自動調整する。

### 本機能の処理概要

**業務上の目的・背景**：アプリケーションの負荷変動に応じて自動的にPod数を増減させ、リソースの効率的な利用と安定したサービス提供を両立させる。手動でのスケーリング作業を排除し、運用負荷を軽減する。

**機能の利用シーン**：Webアプリケーションのトラフィック増加時に自動的にPod数を増やし、閑散時に削減する。CPU使用率、メモリ使用率、カスタムメトリクス、外部メトリクスなど多様な指標に基づくスケーリング。

**主要な処理内容**：
1. HorizontalPodAutoscalerリソースの変更を監視する
2. 各メトリクスソース（Resource、Pod、Object、External）からメトリクスを収集する
3. ReplicaCalculatorを用いて目標レプリカ数を算出する
4. スケールアップ/ダウンの安定化ウィンドウを適用する
5. ScalingRulesに基づくスケーリングポリシーを適用する
6. Scale APIを通じて対象ワークロードのレプリカ数を更新する

**関連システム・外部連携**：Metrics Server（Resource Metrics API）、Custom Metrics API（カスタムメトリクス）、External Metrics API（外部メトリクス）、Scale API（レプリカ数更新）

**権限による制御**：HPAコントローラーはsystem:controller:horizontal-pod-autoscalerサービスアカウントで動作し、HPA/Scale/Metricsの読み書き権限を持つ。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | kubectl autoscale | API連携 | HPAリソース作成後にHPAコントローラーがレプリカ数を自動調整する |

## 機能種別

計算処理 / 自動制御（バックグラウンド定期処理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| workers | int | Yes | 同時実行ワーカー数 | 正の整数 |
| resyncPeriod | time.Duration | Yes | HPAの再同期間隔 | 正の値 |
| downscaleStabilisationWindow | time.Duration | Yes | スケールダウン安定化ウィンドウ | 正の値 |
| tolerance | float64 | Yes | メトリクス変動の許容誤差 | 0以上の浮動小数点 |
| cpuInitializationPeriod | time.Duration | Yes | CPU初期化期間 | 正の値 |
| delayOfInitialReadinessStatus | time.Duration | Yes | 初期Readiness遅延 | 正の値 |

### 入力データソース

- HPA Informer: HorizontalPodAutoscalerオブジェクトのadd/update/deleteイベント
- Pod Informer: Pod一覧の取得（メトリクス計算用）
- Metrics Client: Resource/Custom/External Metrics APIからのメトリクス取得
- Scale API: 対象ワークロードの現在のレプリカ数取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Scale.Spec.Replicas | int32 | 更新後のレプリカ数 |
| HPA.Status | autoscalingv2.HorizontalPodAutoscalerStatus | 現在のメトリクス値、レプリカ数、条件 |
| Event | v1.Event | スケーリングイベント記録 |

### 出力先

- Scale API: 対象ワークロードのレプリカ数更新
- API Server: HPAステータス更新
- Kubernetes Events: スケーリングイベントログ

## 処理フロー

### 処理シーケンス

```
1. Run()でワーカーを起動する
   └─ キャッシュ同期待機後、workers個のワーカーを起動
2. キューからHPAキーを取得し、reconcileAutoscalerを実行する
   └─ HPA/Scaleオブジェクトの取得
3. 各メトリクスソースからメトリクスを収集しレプリカ数を計算する
   └─ ReplicaCalculatorで目標レプリカ数を算出
4. 安定化ウィンドウとScalingRulesを適用する
   └─ スケールダウン安定化、スケールアップ/ダウンポリシー適用
5. 計算結果に基づきScale APIでレプリカ数を更新する
   └─ 変更がある場合のみ更新
6. HPAステータスを更新する
   └─ CurrentReplicas、DesiredReplicas、CurrentMetrics、Conditionsを更新
```

### フローチャート

```mermaid
flowchart TD
    A[HPA同期開始] --> B[Scale APIでレプリカ数取得]
    B --> C{メトリクス種別}
    C -->|Resource| D[Resource Metricsからレプリカ計算]
    C -->|Pods| E[Pods Metricsからレプリカ計算]
    C -->|Object| F[Object Metricsからレプリカ計算]
    C -->|External| G[External Metricsからレプリカ計算]
    D --> H[各メトリクスの最大レプリカ数を選択]
    E --> H
    F --> H
    G --> H
    H --> I[MinReplicas/MaxReplicasでクランプ]
    I --> J[安定化ウィンドウ適用]
    J --> K[ScalingRules適用]
    K --> L{レプリカ数変更あり?}
    L -->|Yes| M[Scale API更新]
    L -->|No| N[スキップ]
    M --> O[HPAステータス更新]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | 許容誤差 | メトリクスの変動がtolerance以内の場合はスケーリングしない | 全メトリクス計算時 |
| BR-23-02 | スケールアップ上限 | scaleUpLimitFactor(2.0) * 現在レプリカ数またはscaleUpLimitMinimum(4.0)の大きい方 | スケールアップ時 |
| BR-23-03 | スケールダウン安定化 | downscaleStabilisationWindow内の推奨値の最大値を採用 | スケールダウン時 |
| BR-23-04 | MinReplicas/MaxReplicas | 計算されたレプリカ数はMinReplicasとMaxReplicasの範囲にクランプされる | 全スケーリング時 |
| BR-23-05 | 複数メトリクス | 複数メトリクスが定義されている場合、最大のレプリカ数を採用する | 複数メトリクス定義時 |
| BR-23-06 | ScalingRules | Behavior.ScaleUp/ScaleDownのポリシーに基づきスケーリング速度を制限する | Behavior定義時 |

### 計算ロジック

- **レプリカ計算**: `desiredReplicas = ceil(currentReplicas * (currentMetricValue / targetMetricValue))`
- **安定化**: `stabilizedRecommendation = max(recommendations within stabilization window)`
- **ポリシー適用**: MaxChange/MinPolicy に基づく変更量制限

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| HPA取得 | HPA（etcd） | SELECT | HPAオブジェクトの取得 |
| Scale取得 | Scale（etcd） | SELECT | 対象ワークロードの現在レプリカ数 |
| Scale更新 | Scale（etcd） | UPDATE | レプリカ数の更新 |
| HPAステータス更新 | HPA（etcd） | UPDATE | Status.CurrentReplicas等の更新 |

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

#### HorizontalPodAutoscaler（etcd経由）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | status.currentReplicas | 現在のレプリカ数 | UpdateStatusサブリソース |
| UPDATE | status.desiredReplicas | 算出されたレプリカ数 | UpdateStatusサブリソース |
| UPDATE | status.currentMetrics | 現在のメトリクス値 | UpdateStatusサブリソース |
| UPDATE | status.conditions | スケーリング条件 | UpdateStatusサブリソース |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NotFound | API応答 | HPA/Scaleリソースが存在しない | ログ出力し正常終了 |
| errSpec | 内部 | HPAのSpec定義が不正 | ステータスにInvalidMetricSourceType条件を記録 |
| メトリクス取得失敗 | API応答 | Metrics APIが応答しない | ステータスにScalingActive=False条件を記録 |
| Scale更新失敗 | API応答 | Scale APIの更新失敗 | リトライ（RetryOnConflict使用） |

### リトライ仕様

- syncHandler失敗時: RateLimitingキューによるリトライ
- Scale API更新: client-go RetryOnConflictによるConflictリトライ
- HPAの再同期: resyncPeriod間隔での定期再処理

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

Scale APIの更新はResourceVersionによる楽観的並行性制御が適用される。HPA Statusの更新も同様。Scale更新とStatus更新は別々のAPI呼び出しで行われ、アトミックではない。

## パフォーマンス要件

- resyncPeriod（デフォルト15秒）間隔で全HPAを再評価
- metricsClientを通じたメトリクス取得はAPI呼び出しを伴うため、HPA数増加に応じてレイテンシが増加する可能性がある
- recommendationsマップとscaleEvents マップにより過去の推奨値・スケールイベントを保持し、安定化ウィンドウの計算を高速化

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

- HPAコントローラーはScale APIを通じて対象ワークロードのレプリカ数を変更できる
- Metrics APIへのアクセス権限が必要
- HPAのtargetRef指定により、意図しないワークロードのスケーリングを防止

## 備考

- HPA v2 APIをサポートし、v1との互換性を維持する
- monitor パッケージによりHPA動作のPrometheusメトリクスを記録
- selectors.BiMultimapによりHPAとPodの関連を効率的に管理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | horizontal.go | `pkg/controller/podautoscaler/horizontal.go` | timestampedRecommendation（73-76行目）、timestampedScaleEvent（78-82行目）: 安定化ウィンドウ計算用の履歴データ |
| 1-2 | horizontal.go | `pkg/controller/podautoscaler/horizontal.go` | HorizontalController構造体（87-126行目）: scaleNamespacer、tolerance、replicaCalc、recommendations、scaleUpEvents/scaleDownEventsを保持 |

**読解のコツ**: scaleUpLimitFactor(2.0)とscaleUpLimitMinimum(4.0)はパッケージレベル変数（62-64行目）で定義されている。これらはスケールアップの上限計算に使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | horizontal.go | `pkg/controller/podautoscaler/horizontal.go` | NewHorizontalController（129-197行目）。ReplicaCalculator初期化、HPA/Pod Informerのイベントハンドラ登録 |
| 2-2 | horizontal.go | `pkg/controller/podautoscaler/horizontal.go` | Run（200-219行目）。キャッシュ同期待機後、workers個のワーカーを起動 |

**主要処理フロー**:
1. **172-179行目**: HPA InformerにAdd/Update/Deleteハンドラを登録（resyncPeriod間隔でResync）
2. **186-192行目**: ReplicaCalculatorを初期化（metricsClient、podListerを渡す）
3. **213-215行目**: キャッシュ同期待機
4. **217-219行目**: ワーカー起動

#### Step 3: 同期処理の流れを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | horizontal.go | `pkg/controller/podautoscaler/horizontal.go` | reconcileAutoscalerがメインの同期処理。Scaleオブジェクト取得、メトリクス計算、安定化ウィンドウ適用、Scale更新の一連の流れ |

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

```
HorizontalController.Run()
    │
    ├─ worker()
    │      └─ processNextWorkItem()
    │             └─ reconcileAutoscaler()
    │                    ├─ Scale API Get ── 現在レプリカ数取得
    │                    ├─ computeReplicasForMetrics()
    │                    │      └─ ReplicaCalculator.GetResourceReplicas()
    │                    │      └─ ReplicaCalculator.GetMetricReplicas()
    │                    │      └─ ReplicaCalculator.GetObjectMetricReplicas()
    │                    │      └─ ReplicaCalculator.GetExternalMetricReplicas()
    │                    ├─ stabilizeRecommendation() ── 安定化ウィンドウ
    │                    ├─ normalizeDesiredReplicas() ── ポリシー適用
    │                    ├─ Scale API Update ── レプリカ数更新
    │                    └─ HPA UpdateStatus ── ステータス更新
    │
    └─ enqueueHPA() / updateHPA() / deleteHPA()
```

### データフロー図

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

HPAイベント ──────────▶ reconcileAutoscaler()
(Informer)                │
                          ├─ Scale API Get ──▶ currentReplicas
                          │
Metrics API ──────────▶ computeReplicasForMetrics()
(Resource/Custom/Ext)     │
                          ├─ stabilizeRecommendation() ──▶ 安定化後レプリカ数
                          │
                          ├─ normalizeDesiredReplicas() ──▶ ポリシー適用後レプリカ数
                          │
                          ├─▶ Scale API Update ──▶ レプリカ数更新
                          │
                          └─▶ HPA UpdateStatus ──▶ HPAステータス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| horizontal.go | `pkg/controller/podautoscaler/horizontal.go` | ソース | HPAコントローラーのメインロジック |
| replica_calculator.go | `pkg/controller/podautoscaler/replica_calculator.go` | ソース | メトリクスに基づくレプリカ数の計算 |
| metrics/client.go | `pkg/controller/podautoscaler/metrics/client.go` | ソース | Metrics APIクライアント |
| monitor/monitor.go | `pkg/controller/podautoscaler/monitor/monitor.go` | ソース | HPA動作のPrometheusメトリクス |
