# 機能設計書 77-ヘルスチェック

## 概要

本ドキュメントは、kube-proxyのヘルスチェック機能の設計を記述する。ProxyHealthServerによるkube-proxy自体の健全性チェックと、ServiceHealthServerによるNodePort/LoadBalancerタイプServiceのヘルスチェックエンドポイントの提供を定義する。

### 本機能の処理概要

**業務上の目的・背景**：クラウドロードバランサーやモニタリングシステムがkube-proxyおよびServiceバックエンドの健全性を確認するためのHTTPエンドポイントが必要である。ProxyHealthServerはkube-proxy自体の正常動作を報告し、ServiceHealthServerは各Serviceのローカルエンドポイント数を報告してロードバランサーのバックエンド選択を支援する。

**機能の利用シーン**：(1) Kubernetesのlivenessプローブやモニタリングシステムがkube-proxyの/healthzおよび/livezエンドポイントにアクセスする場合。(2) クラウドロードバランサーがexternalTrafficPolicy=Localの場合にServiceのヘルスチェックポートにアクセスしてバックエンド選択を行う場合。

**主要な処理内容**：
1. ProxyHealthServer: /healthzと/livezエンドポイントの提供
2. ProxyHealthServer: Proxierの最終更新時刻と保留中の更新の監視
3. ProxyHealthServer: ノード適格性判定（ToBeDeletedTaintチェック）
4. ServiceHealthServer: Service毎のヘルスチェックHTTPサーバー管理
5. ServiceHealthServer: ローカルエンドポイント数の報告
6. ServiceHealthServer: ヘルスチェックポートの動的開閉

**関連システム・外部連携**：クラウドロードバランサー、モニタリングシステム、Cluster Autoscaler。

**権限による制御**：ヘルスチェックポートへのアクセスはネットワークレベルで制御。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | HTTPエンドポイント提供のため直接の画面関連はなし |

## 機能種別

ヘルスチェック / HTTP API

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| addr | string | Yes | ヘルスチェックサーバーのリッスンアドレス | 有効なアドレス:ポート |
| healthTimeout | time.Duration | Yes | ヘルス判定のタイムアウト | 正の値 |
| newServices | map[NamespacedName]uint16 | Yes | Service名とヘルスチェックポートのマップ | - |
| newEndpoints | map[NamespacedName]int | Yes | Service名とローカルエンドポイント数のマップ | - |

### 入力データソース

- kube-proxyのProxierからのUpdated/QueuedUpdate呼び出し
- Service/EndpointSliceリソースから計算されたヘルスチェック情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ProxyHealth | JSON | lastUpdated, currentTime, nodeEligible, healthy, statusの構造体 |
| ServiceHealth | JSON | namespace, name, localEndpoints, serviceProxyHealthyの構造体 |
| HTTPステータス | int | 200（正常）または503（異常） |

### 出力先

HTTP応答（/healthz, /livez, Service毎のヘルスチェックポート）

## 処理フロー

### 処理シーケンス

```
1. ProxyHealthServer初期化
   ├─ HTTPサーバー起動（/healthz, /livez）
   └─ lastUpdatedMap/oldestPendingQueuedMap初期化
2. Proxierからの更新通知
   ├─ QueuedUpdate: 更新待ちの記録
   └─ Updated: 更新完了の記録
3. /healthzリクエスト処理
   ├─ Health()で全Proxierの健全性チェック
   ├─ NodeEligible()でノード適格性チェック
   └─ JSON応答返却
4. /livezリクエスト処理
   ├─ Health()で全Proxierの健全性チェック
   └─ JSON応答返却（NodeEligibleなし）
5. ServiceHealthServer
   ├─ SyncServices: ヘルスチェックポートの動的開閉
   └─ SyncEndpoints: ローカルエンドポイント数の更新
6. Serviceヘルスチェックリクエスト処理
   ├─ ローカルエンドポイント数の確認
   ├─ kube-proxy自体の健全性確認
   └─ 200/503応答返却
```

### フローチャート

```mermaid
flowchart TD
    A[/healthz リクエスト] --> B[Health関数]
    B --> C{全Proxier健全?}
    C -->|Yes| D[NodeEligible確認]
    C -->|No| E[503応答]
    D --> F{ノード適格?}
    F -->|Yes| G[200応答]
    F -->|No| E

    H[Service ヘルスチェック] --> I{ローカルEndpoint > 0?}
    I -->|Yes| J{kube-proxy健全?}
    I -->|No| K[503応答]
    J -->|Yes| L[200応答 + endpoint count]
    J -->|No| K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-77-01 | Proxier健全性 | QueuedUpdateからUpdatedまでの時間がhealthTimeoutを超えると不健全 | QueuedUpdate呼び出し後 |
| BR-77-02 | ノード適格性 | ToBeDeletedByClusterAutoscaler Taintがあるノードは不適格 | /healthzエンドポイントのみ |
| BR-77-03 | ノード削除状態 | DeletionTimestampが設定されたノードは不適格 | /healthzエンドポイントのみ |
| BR-77-04 | Service健全性 | ローカルエンドポイントが0かつkube-proxyが不健全なら503 | externalTrafficPolicy=Local |
| BR-77-05 | IPファミリー独立 | IPv4/IPv6のProxierは独立して健全性が管理される | DualStackクラスター |
| BR-77-06 | 起動中の扱い | QueuedUpdate未呼び出し時は健全として扱う | Proxier起動直後 |

### 計算ロジック

健全性判定: `currentTime - oldestPendingQueuedTime < healthTimeout`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベースへの直接操作はなし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ポートバインド失敗 | ヘルスチェックポートが使用中 | ポート設定の見直し |
| - | リスナー作成失敗 | ネットワーク設定エラー | ネットワーク設定確認 |

### リトライ仕様

ServiceHealthServerのSyncServicesで失敗した場合、次回のSync呼び出しで再試行される。

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

トランザクションの概念はなし。各HTTP応答は独立して処理される。

## パフォーマンス要件

- ヘルスチェック応答はミリ秒オーダーであること
- Service毎に独立したHTTPサーバーが起動される

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

- Content-Typeヘッダーのapplication/json設定
- X-Content-Type-Options: nosniffヘッダーによるMIMEスニッフィング防止
- ノードポートアドレス設定によるリッスンIP制御

## 備考

- ProxyHealthServerのメトリクス: ProxyHealthzTotal, ProxyLivezTotal
- X-Load-Balancing-Endpoint-Weightヘッダーでエンドポイント数を報告
- /healthzと/livezの違い: /healthzにはNodeEligible情報が含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | proxy_health.go | `pkg/proxy/healthcheck/proxy_health.go` | ProxierHealth, ProxyHealth, ProxyHealthServer構造体 |
| 1-2 | common.go | `pkg/proxy/healthcheck/common.go` | listener, httpServerFactoryインターフェース |

**読解のコツ**: ProxyHealthServerはIPファミリーごとのlastUpdatedMapとoldestPendingQueuedMapを管理する。健全性はこの2つのマップの時間差で判定される。

#### Step 2: ProxyHealthServerを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | proxy_health.go | `pkg/proxy/healthcheck/proxy_health.go` | NewProxyHealthServer（89-91行目） |
| 2-2 | proxy_health.go | `pkg/proxy/healthcheck/proxy_health.go` | Updated/QueuedUpdate/Health（109-176行目） |
| 2-3 | proxy_health.go | `pkg/proxy/healthcheck/proxy_health.go` | NodeEligible（180-197行目） |
| 2-4 | proxy_health.go | `pkg/proxy/healthcheck/proxy_health.go` | Run, healthzHandler, livezHandler（200-275行目） |

**主要処理フロー**:
- **109-114行目**: Updated - oldestPendingを削除し、lastUpdatedを更新
- **121-128行目**: QueuedUpdate - 初回のみoldestPendingを記録
- **131-176行目**: Health - 全IPファミリーのProxierを走査し、タイムアウトチェック
- **180-197行目**: NodeEligible - ToBeDeletedTaintとDeletionTimestampチェック
- **223-249行目**: healthzHandler - Health() + NodeEligible()で判定

#### Step 3: ServiceHealthServerを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | service_health.go | `pkg/proxy/healthcheck/service_health.go` | ServiceHealthServerインターフェース（43-53行目） |
| 3-2 | service_health.go | `pkg/proxy/healthcheck/service_health.go` | server.SyncServices（104-151行目） |
| 3-3 | service_health.go | `pkg/proxy/healthcheck/service_health.go` | hcHandler.ServeHTTP（223-254行目） |
| 3-4 | service_health.go | `pkg/proxy/healthcheck/service_health.go` | server.SyncEndpoints（256-273行目） |

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

```
kube-proxy main
    |
    +-- healthcheck.NewProxyHealthServer(addr, timeout, nodeManager)
    |       +-- Run(ctx) -> /healthz, /livez HTTPサーバー
    |
    +-- healthcheck.NewServiceHealthServer(nodeName, recorder, nodePortAddresses, healthzServer)
    |       +-- SyncServices(newServices)
    |       |       +-- hcInstance.listenAndServeAll
    |       +-- SyncEndpoints(newEndpoints)
    |
    +-- Proxier
            +-- QueuedUpdate(ipFamily) -> ProxyHealthServer
            +-- Updated(ipFamily) -> ProxyHealthServer
```

### データフロー図

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

Proxier ----QueuedUpdate----> ProxyHealthServer
        ----Updated---------> (時刻管理)                --> /healthz (200/503)
                                                        --> /livez (200/503)
Node info -------> NodeEligible判定

Service/Endpoint -> SyncServices/SyncEndpoints -------> ServiceHealthServer
                    (ポート開閉・カウント更新)          --> :healthCheckPort (200/503)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| proxy_health.go | `pkg/proxy/healthcheck/proxy_health.go` | ソース | ProxyHealthServerの実装 |
| service_health.go | `pkg/proxy/healthcheck/service_health.go` | ソース | ServiceHealthServerの実装 |
| common.go | `pkg/proxy/healthcheck/common.go` | ソース | 共通インターフェースとファクトリー |
| doc.go | `pkg/proxy/healthcheck/doc.go` | ソース | パッケージドキュメント |
| healthcheck_test.go | `pkg/proxy/healthcheck/healthcheck_test.go` | テスト | ユニットテスト |
