# 機能設計書 79-トポロジー対応ルーティング

## 概要

本ドキュメントは、kube-proxyにおけるトポロジー対応ルーティング機能の設計を記述する。トポロジーキー（ゾーン、ノード）に基づくエンドポイントの分類とトラフィックの優先ルーティング制御を定義する。

### 本機能の処理概要

**業務上の目的・背景**：大規模な分散クラスターでは、トラフィックが異なるアベイラビリティゾーンやノードに転送されるとレイテンシが増加し、クラウド環境ではゾーン間通信コストが発生する。トポロジー対応ルーティングにより、同一ゾーンや同一ノード内のエンドポイントを優先的に使用することで、レイテンシ削減とコスト最適化を実現する。

**機能の利用シーン**：EndpointSliceコントローラーがエンドポイントにトポロジーヒント（ゾーン、ノード）を付与し、kube-proxyがこれらのヒントに基づいてトラフィック転送先を絞り込む。

**主要な処理内容**：
1. CategorizeEndpoints: エンドポイントをCluster/Local/全到達可能に分類
2. topologyModeFromHints: ヒントからトポロジーモードを決定
3. availableForTopology: トポロジーモードに基づくエンドポイントフィルタリング
4. Terminating EndpointへのFallback
5. externalTrafficPolicy/internalTrafficPolicyに応じた分類

**関連システム・外部連携**：EndpointSliceコントローラー（ヒント付与）、kube-proxy各モード（iptables/ipvs/nftables）。

**権限による制御**：特になし。エンドポイントのトポロジーヒントはEndpointSliceコントローラーが管理。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 内部ライブラリのため直接の画面関連はなし |

## 機能種別

ネットワーク制御 / フィルタリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| endpoints | []Endpoint | Yes | 全エンドポイントリスト | - |
| svcInfo | ServicePort | Yes | サービスポート情報 | - |
| nodeName | string | Yes | 現在のノード名 | - |
| topologyLabels | map[string]string | Yes | ノードのトポロジーラベル | - |

### 入力データソース

- EndpointSliceから取得したエンドポイント情報
- Nodeのトポロジーラベル（topology.kubernetes.io/zone等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| clusterEndpoints | []Endpoint | Clusterトラフィックポリシー用エンドポイント |
| localEndpoints | []Endpoint | Localトラフィックポリシー用エンドポイント |
| allReachableEndpoints | []Endpoint | このノードから到達可能な全エンドポイント |
| hasAnyEndpoints | bool | クラスター全体にエンドポイントが存在するか |

### 出力先

kube-proxy各モード（iptables/ipvs/nftables）のルール生成に使用。

## 処理フロー

### 処理シーケンス

```
1. CategorizeEndpoints呼び出し
2. Clusterエンドポイント分類
   ├─ トポロジーモード決定（topologyModeFromHints）
   │   ├─ PreferSameNode: 全Readyエンドポイントにノードヒントあり
   │   ├─ PreferSameZone: 全Readyエンドポイントにゾーンヒントあり
   │   └─ "": ヒントなし（全エンドポイント対象）
   ├─ Readyエンドポイントのフィルタリング
   └─ Ready=0の場合、Serving+Terminatingにフォールバック
3. Localエンドポイント分類
   ├─ ローカルReadyエンドポイントの抽出
   └─ Ready=0の場合、Serving+Terminatingにフォールバック
4. 全到達可能エンドポイントの構築
   └─ ClusterとLocalの和集合
```

### フローチャート

```mermaid
flowchart TD
    A[CategorizeEndpoints] --> B{UsesClusterEndpoints?}
    B -->|Yes| C[topologyModeFromHints]
    C --> D[Readyエンドポイントフィルタ]
    D --> E{Readyエンドポイント数 > 0?}
    E -->|Yes| F[clusterEndpoints設定]
    E -->|No| G[Serving+Terminatingフォールバック]
    G --> F

    B -->|No| H{UsesLocalEndpoints?}
    F --> H
    H -->|Yes| I[ローカルReadyエンドポイント抽出]
    I --> J{ローカルReady > 0?}
    J -->|Yes| K[localEndpoints設定]
    J -->|No| L[ローカルServing+Terminatingフォールバック]
    L --> K
    K --> M[allReachableEndpoints構築]
    H -->|No| M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-01 | PreferSameNode | 全Readyエンドポイントにノードヒントがあり、対象ノードにヒントがある場合 | PreferSameTrafficDistributionフィーチャーゲート有効 |
| BR-79-02 | PreferSameZone | 全Readyエンドポイントにゾーンヒントがあり、対象ゾーンにヒントがある場合 | 常時 |
| BR-79-03 | フォールバック | トポロジーモード判定ではReady=0時のフォールバックなし、Readyエンドポイントフィルタリング後にTerminatingへフォールバック | Ready=0時 |
| BR-79-04 | Local優先 | externalTrafficPolicy=Localの場合、ローカルエンドポイントのみ使用 | Localポリシー設定時 |
| BR-79-05 | ヒント不完全時の無視 | 一部のエンドポイントにヒントがない場合、トポロジーモードを無効化 | ヒント部分欠落時 |
| BR-79-06 | 和集合構築 | allReachableEndpointsはclusterとlocalの和集合 | 両方のポリシーが使用される場合 |

### 計算ロジック

トポロジーモード判定：
1. PreferSameTrafficDistribution有効 AND 全ReadyにNodeHints AND 対象ノードにヒントあり → "PreferSameNode"
2. 全ReadyにZoneHints AND 対象ゾーンにヒントあり → "PreferSameZone"
3. それ以外 → ""（ヒントなし）

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | エラーを返す関数ではない | フォールバックロジックで対処 |

### リトライ仕様

リトライ不要。純粋な分類処理のため。

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

トランザクションの概念はなし。

## パフォーマンス要件

- O(N)の計算量（Nはエンドポイント数）
- 各syncProxyRulesで呼び出されるため、効率的な実装が求められる

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

- トポロジーヒントの改ざんは、トラフィックの不正なルーティングを引き起こす可能性がある
- EndpointSliceコントローラーの信頼性に依存

## 備考

- NodeTopologyConfigがpkg/proxy/configでトポロジーラベルのフィルタリングを行うことに注意
- topologyModeFromHintsはヒントが不完全な場合にログを出力する
- allReachableEndpointsの構築では、clusterとlocalが同一の場合はアロケーションを回避

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | topology.go | `pkg/proxy/topology.go` | CategorizeEndpoints関数のシグネチャと戻り値（48行目） |

**読解のコツ**: CategorizeEndpointsは4つの戻り値を持つ。clusterEndpoints/localEndpointsはnilになる可能性があり、これはそのトラフィックポリシーが使用されないことを意味する。

#### Step 2: メイン分類ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | topology.go | `pkg/proxy/topology.go` | CategorizeEndpoints（48-154行目） |

**主要処理フロー**:
- **57-89行目**: Clusterエンドポイントの分類（トポロジーモード適用、Terminatingフォールバック）
- **96-123行目**: Localエンドポイントの分類（ローカル判定、Terminatingフォールバック）
- **130-153行目**: allReachableEndpointsの構築（和集合のマージ）

#### Step 3: トポロジーモード決定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | topology.go | `pkg/proxy/topology.go` | topologyModeFromHints（164-217行目） |

**主要処理フロー**:
- **171-191行目**: 全Readyエンドポイントのヒント走査
- **193-202行目**: PreferSameTrafficDistribution有効時のノードヒント判定
- **203-214行目**: ゾーンヒント判定

#### Step 4: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | topology.go | `pkg/proxy/topology.go` | availableForTopology（222-233行目） |
| 4-2 | topology.go | `pkg/proxy/topology.go` | filterEndpoints（236-246行目） |

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

```
Proxier.syncProxyRules (各モード共通)
    |
    +-- proxy.CategorizeEndpoints(endpoints, svcInfo, nodeName, topologyLabels)
            |
            +-- topologyModeFromHints(svcInfo, endpoints, nodeName, zone)
            |       +-- endpoint.NodeHints().Has(nodeName)
            |       +-- endpoint.ZoneHints().Has(zone)
            |
            +-- filterEndpoints(endpoints, predicate)
            |       +-- ep.IsReady()
            |       +-- availableForTopology(ep, mode, nodeName, zone)
            |
            +-- filterEndpoints(endpoints, predicate) [Terminating fallback]
            |       +-- ep.IsServing() && ep.IsTerminating()
            |
            +-- filterEndpoints(endpoints, predicate) [Local]
                    +-- ep.IsLocal() && ep.IsReady()
```

### データフロー図

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

EndpointSlice               CategorizeEndpoints         clusterEndpoints
  endpoints ---------> topologyModeFromHints -----+     localEndpoints
                              |                   |     allReachableEndpoints
Node                    filterEndpoints ----------+     hasAnyEndpoints
  nodeName ---------> availableForTopology
  topologyLabels

ServicePort
  svcInfo -----------> UsesCluster/LocalEndpoints
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| topology.go | `pkg/proxy/topology.go` | ソース | トポロジー対応ルーティングのメインロジック |
| topology_test.go | `pkg/proxy/topology_test.go` | テスト | ユニットテスト |
| endpoint.go | `pkg/proxy/endpoint.go` | ソース | Endpointインターフェース定義 |
| serviceport.go | `pkg/proxy/serviceport.go` | ソース | ServicePortインターフェース定義 |
| types.go | `pkg/proxy/types.go` | ソース | 共通型定義 |
| node.go | `pkg/proxy/node.go` | ソース | ノードトポロジーラベル管理 |
