# 機能設計書 53-ヘルスチェック（Probe）

## 概要

本ドキュメントは、KubeletのProbe（ヘルスチェック）機能について、Liveness、Readiness、Startupプローブによるコンテナのヘルスチェック実行の設計を記載する。

### 本機能の処理概要

Kubeletのヘルスチェック機能は、Pod内の各コンテナに対してLiveness Probe（生存確認）、Readiness Probe（準備完了確認）、Startup Probe（起動完了確認）の3種類のプローブを定期的に実行し、コンテナの健全性を監視する。プローブ結果に基づいてコンテナの再起動判定やService Endpointへの登録/除外を制御する。

**業務上の目的・背景**：マイクロサービスアーキテクチャでは、コンテナが起動しても内部のアプリケーションが正常に動作しているとは限らない。ヘルスチェック機能により、アプリケーションレベルでの健全性を確認し、異常なコンテナの自動再起動やトラフィックの適切な制御を実現する。

**機能の利用シーン**：コンテナ起動時の初期化完了待ち（Startup Probe）、実行中のアプリケーションのデッドロック検知（Liveness Probe）、トラフィック受入準備の確認（Readiness Probe）。

**主要な処理内容**：
1. Pod追加時にコンテナごとのProbe worker goroutineを起動
2. 各workerが設定された間隔でHTTP、TCP、Exec、gRPCのいずれかの方式でプローブ実行
3. プローブ結果（Success/Failure/Unknown）をキャッシュし、PodStatusに反映
4. Liveness失敗時はコンテナ再起動をトリガー、Readiness失敗時はReady条件をfalseに設定
5. Startup Probe成功までLiveness/Readinessの実行を抑制

**関連システム・外部連携**：CRI（コンテナ内コマンド実行）、コンテナのHTTP/TCP/gRPCエンドポイント。

**権限による制御**：プローブはKubelet権限でコンテナに対して直接実行される。特別な認可制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Kubelet内部機能のため画面関連なし |

## 機能種別

監視処理 / 状態管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| probe.Handler | v1.ProbeHandler | Yes | プローブ方式（HTTP/TCP/Exec/gRPC） | いずれか1つ指定 |
| probe.InitialDelaySeconds | int32 | No | 初期遅延（秒） | 0以上 |
| probe.PeriodSeconds | int32 | No | 実行間隔（秒、デフォルト10） | 1以上 |
| probe.TimeoutSeconds | int32 | No | タイムアウト（秒、デフォルト1） | 1以上 |
| probe.SuccessThreshold | int32 | No | 成功判定回数（デフォルト1） | 1以上 |
| probe.FailureThreshold | int32 | No | 失敗判定回数（デフォルト3） | 1以上 |

### 入力データソース

- Pod仕様（v1.Container.LivenessProbe/ReadinessProbe/StartupProbe）
- コンテナランタイム（コンテナID、実行状態）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| results.Result | int | Success(0)/Failure(1)/Unknown(2) |
| PodStatus.Conditions | []v1.PodCondition | Ready条件の更新 |
| ContainerStatus.Ready | bool | コンテナのReady状態 |

### 出力先

- Probe結果キャッシュ（resultsManager）
- PodStatus（statusManager経由でAPI Serverへ同期）
- Prometheusメトリクス（prober_probe_total、prober_probe_duration_seconds）
- Kubernetesイベント

## 処理フロー

### 処理シーケンス

```
1. Pod追加通知（AddPod）
   └─ 各コンテナのプローブ定義を確認しworkerを起動
2. workerループ（doProbe）
   └─ コンテナの実行状態確認、プローブ実行、結果判定
3. プローブ実行（prober.probe）
   └─ HTTP/TCP/Exec/gRPCのいずれかで実行
4. 結果処理
   └─ SuccessThreshold/FailureThresholdに基づく最終判定
5. PodStatus更新（UpdatePodStatus）
   └─ キャッシュされた結果をPodStatusに反映
```

### フローチャート

```mermaid
flowchart TD
    A[AddPod] --> B[コンテナごとにworker起動]
    B --> C[doProbeループ]
    C --> D{コンテナ実行中?}
    D -->|No| E[結果をクリア/保留]
    D -->|Yes| F{Startup Probe完了?}
    F -->|No, Liveness/Readiness| G[スキップ]
    F -->|Yes or StartupProbe| H[prober.probe実行]
    H --> I{結果判定}
    I -->|Success| J{SuccessThreshold到達?}
    I -->|Failure| K{FailureThreshold到達?}
    I -->|Unknown| L[Unknown記録]
    J -->|Yes| M[Success確定 → resultsManager更新]
    K -->|Yes| N[Failure確定 → resultsManager更新]
    M --> O[次回実行まで待機]
    N --> O
    O --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | Startup優先 | Startup Probeが成功するまでLiveness/Readiness Probeは実行されない | Startup Probe定義時 |
| BR-53-02 | 連続判定 | SuccessThreshold/FailureThreshold回連続で同じ結果が出た場合に状態遷移 | 各プローブ実行時 |
| BR-53-03 | Liveness再起動 | Liveness Probe失敗確定時にコンテナ再起動をトリガー | Liveness失敗時 |
| BR-53-04 | Readiness除外 | Readiness Probe失敗時にServiceのEndpointから除外 | Readiness失敗時 |
| BR-53-05 | 最大リトライ | プローブ内部で最大3回リトライ（maxProbeRetries） | プローブ実行時 |
| BR-53-06 | 終了時停止 | Pod終了時にLivenessとStartupプローブを停止 | Pod終了通知時 |

### 計算ロジック

特になし。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 結果キャッシュ | resultsManager（インメモリ） | UPDATE | プローブ結果の更新 |

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

#### resultsManager（インメモリMap）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | containerID → Result | Success/Failure | プローブ結果確定時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Unhealthy | プローブ失敗 | Liveness/Readiness/Startupプローブ失敗 | イベント記録、閾値到達時にアクション実行 |
| Unknown | 不明 | プローブ実行エラー | Unknown結果として記録 |
| ContainerNotFound | 一時エラー | コンテナが見つからない | 次回プローブまで待機 |

### リトライ仕様

- プローブ内部リトライ: 最大3回（maxProbeRetries = 3）
- workerレベルリトライ: PeriodSecondsの間隔で継続実行

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

プローブ結果はインメモリキャッシュに保持。PodStatusへの反映はstatusManager経由で非同期にAPI Serverに同期。

## パフォーマンス要件

- 各プローブworkerは独立したgoroutineで並行実行
- プローブ間隔はPeriodSeconds（デフォルト10秒）
- タイムアウトはTimeoutSeconds（デフォルト1秒）
- 初期遅延にジッターを追加して同時プローブ実行を分散

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

- HTTPプローブはnon-localリダイレクトを追従しない（followNonLocalRedirects = false）
- Execプローブはコンテナ内でコマンドを実行するため、コンテナのセキュリティコンテキストに依存

## 備考

- プローブworkerはPodが削除されるまで継続実行される
- PodTermination時にLiveness/Startupプローブは停止されるが、Readinessプローブは継続（Ready状態をfalseにするため）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | results/ | `pkg/kubelet/prober/results/` | Result型（Success/Failure/Unknown）、Managerインターフェース |

**読解のコツ**: results.Resultは整数型で、0=Success、1=Failure、2=Unknownを表す。results.Managerはプローブ結果のキャッシュと通知を管理する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | prober_manager.go | `pkg/kubelet/prober/prober_manager.go` | Managerインターフェース、manager構造体 |

**主要処理フロー**:
1. **75-94行目**: Manager インターフェース - AddPod、RemovePod、UpdatePodStatus
2. **96-100行目**: manager構造体 - workers map、workerLock

#### Step 3: Worker処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | worker.go | `pkg/kubelet/prober/worker.go` | worker構造体、doProbeメソッド |

**主要処理フロー**:
- **39-74行目**: worker構造体 - プローブ設定、結果追跡、メトリクスラベル

#### Step 4: プローブ実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | prober.go | `pkg/kubelet/prober/prober.go` | prober構造体、probe()メソッド |

**主要処理フロー**:
- **44-52行目**: prober構造体 - exec/http/tcp/grpcの4種類のプローバー
- **56-69行目**: newProber - 各プローバーの初期化
- **83-94行目**: probe() - probeTypeに基づくプローブ仕様の選択

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

```
Kubelet.SyncPod()
    |
    +-- probeManager.AddPod()
    |       +-- worker.run() [goroutine per probe]
    |               +-- doProbe()
    |                       +-- prober.probe()
    |                       |       +-- exec.Prober / http.Prober / tcp.Prober / grpc.Prober
    |                       +-- resultsManager.Set()
    |
    +-- probeManager.UpdatePodStatus()
    |       +-- resultsManager.Get() → PodStatus更新
    |
    +-- probeManager.RemovePod()
            +-- worker.stop()
```

### データフロー図

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

Pod仕様              ──▶  AddPod()            ──▶  worker goroutine起動
(probe定義)

コンテナ状態         ──▶  doProbe()           ──▶  resultsManager
(CRI経由)                  |                         |
                           v                         v
                     prober.probe()            PodStatus更新
                     (HTTP/TCP/Exec/gRPC)      (Ready条件)
                           |
                           v                    イベント記録
                     結果判定                   メトリクス記録
                     (threshold)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| prober_manager.go | `pkg/kubelet/prober/prober_manager.go` | ソース | プローブマネージャーのメインロジック |
| prober.go | `pkg/kubelet/prober/prober.go` | ソース | 実際のプローブ実行（HTTP/TCP/Exec/gRPC） |
| worker.go | `pkg/kubelet/prober/worker.go` | ソース | プローブworkerのライフサイクル管理 |
| results/ | `pkg/kubelet/prober/results/` | ソース | プローブ結果の管理インターフェース |
| scale_test.go | `pkg/kubelet/prober/scale_test.go` | テスト | スケールテスト |
