# 機能設計書 52-ノードディスカバリ

## 概要

本ドキュメントは、OpenSearchにおけるノードディスカバリ機能の設計を記述する。ノードディスカバリは、クラスタ内のノードを自動的に検出し、クラスタの形成・維持を担う基盤機能である。

### 本機能の処理概要

ノードディスカバリ機能は、OpenSearchクラスタにおけるノード間の相互検出、クラスタマネージャ選挙、ノード参加処理を実現する。シードホストの解決、ピア探索、ハンドシェイク、クラスタ参加処理などの一連のディスカバリプロセスを提供する。

**業務上の目的・背景**：分散システムであるOpenSearchでは、クラスタを構成する複数のノード間で相互に認識し合い、協調して動作する必要がある。ノードディスカバリは、ノードの追加・削除時にクラスタの一貫性を保ちながら、自動的にクラスタ構成を更新する基盤機能である。

**機能の利用シーン**：
- クラスタの初期起動時に各ノードがお互いを発見する場合
- 新しいノードを既存クラスタに追加する場合
- クラスタマネージャノードの障害後に新しいリーダーを選出する場合
- ノードのネットワーク断からの復旧時にクラスタに再参加する場合

**主要な処理内容**：
1. シードホストプロバイダーからアドレス取得
2. ホスト名解決（SeedHostsResolver）
3. ピアノードプローブとハンドシェイク（PeerFinder）
4. クラスタマネージャの発見または選出
5. クラスタ参加リクエスト（JoinRequest）

**関連システム・外部連携**：TransportServiceと連携してノード間通信を行う。ClusterServiceと連携してクラスタ状態を管理する。GatewayMetaStateと連携して永続化された状態を復元する。

**権限による制御**：ノードディスカバリは内部プロセスであり、直接的なアクション権限は不要。ただし、ノードの参加には適切なクラスタ設定（discovery.seed_hosts等）が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | クラスタヘルス | 参照画面 | ノードの参加状態を確認 |
| - | ノード情報 | 参照画面 | 検出されたノードの一覧表示 |

## 機能種別

クラスタ管理 / 内部プロセス

## 入力仕様

### 主要設定パラメータ

| パラメータ名 | 型 | 必須 | 説明 | デフォルト値 |
|-------------|-----|-----|------|-------------|
| discovery.type | String | No | ディスカバリタイプ | zen |
| discovery.seed_hosts | List | No | シードホストのリスト | [] |
| discovery.seed_providers | List | No | シードホストプロバイダー | [] |
| discovery.find_peers_interval | TimeValue | No | ピア探索間隔 | 1s |
| cluster.initial_cluster_manager_nodes | List | No | 初期クラスタマネージャノード | [] |
| cluster.election.strategy | String | No | 選挙戦略 | default |

### シードホストプロバイダー

| プロバイダー名 | 説明 |
|--------------|------|
| settings | opensearch.ymlのdiscovery.seed_hostsから取得 |
| file | unicast_hosts.txtファイルから取得 |

### 入力データソース

- 設定ファイル（opensearch.yml）
- unicast_hosts.txtファイル
- プラグインによるカスタムプロバイダー

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DiscoveryStats | Object | ディスカバリ統計情報 |
| DiscoveryStats.cluster_state_queue | Object | クラスタ状態キュー情報 |
| DiscoveryStats.published_cluster_states | Object | パブリッシュされたクラスタ状態情報 |

### 出力先

- クラスタ状態（ノード情報の更新）
- ログファイル

## 処理フロー

### 処理シーケンス

```
1. ノード起動
   └─ DiscoveryModuleの初期化
2. シードホストプロバイダーの設定
   └─ settings/file/カスタムプロバイダーの登録
3. Coordinatorの初期化
   └─ Zen2ディスカバリの開始
4. シードホスト解決
   └─ SeedHostsResolver.resolveHosts()
5. ピア探索開始
   └─ PeerFinder.findPeers()
6. ハンドシェイク実行
   └─ HandshakingTransportAddressConnector.connectToRemoteMasterNode()
7. クラスタ参加
   └─ JoinHelper.sendJoinRequest()
```

### フローチャート

```mermaid
flowchart TD
    A[ノード起動] --> B[DiscoveryModule初期化]
    B --> C{discovery.type}
    C -->|zen| D[Coordinator生成]
    C -->|single-node| E[単一ノードモード]

    D --> F[シードホストプロバイダー設定]
    F --> G[SeedHostsResolver]
    G --> H[ホスト名解決]

    H --> I[PeerFinder開始]
    I --> J[ピアプローブ]
    J --> K[ハンドシェイク]

    K --> L{クラスタマネージャ発見?}
    L -->|Yes| M[JoinRequest送信]
    L -->|No| N[選挙開始]

    M --> O[クラスタ参加完了]
    N --> P[PreVote収集]
    P --> Q[選挙実行]
    Q --> R[リーダー確定]
    R --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | シードホスト必須 | クラスタ形成にはシードホストの設定が必要 | マルチノード時 |
| BR-02 | 初期ノード設定 | 新規クラスタでは初期クラスタマネージャノードの設定が必要 | 新規クラスタ時 |
| BR-03 | ハンドシェイク検証 | ノード参加時にクラスタ名・バージョンを検証 | 常時 |
| BR-04 | 選挙戦略 | デフォルト選挙戦略またはカスタム戦略を使用 | クラスタマネージャ選出時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| ノード参加 | ClusterState.nodes | UPDATE | ノード一覧の更新 |
| クラスタマネージャ選出 | ClusterState.metadata | UPDATE | クラスタマネージャ情報の更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ClusterManagerNotDiscoveredException | クラスタマネージャが発見できない | シードホスト設定を確認 |
| - | IllegalArgumentException | 不正なディスカバリタイプ | discovery.type設定を確認 |
| - | ConnectTransportException | ノード接続失敗 | ネットワーク設定を確認 |

### リトライ仕様

ピア探索は`discovery.find_peers_interval`（デフォルト1秒）間隔で自動的に再試行される。

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

ノードディスカバリはクラスタ状態の更新を伴う。クラスタ状態の変更はCoordinatorによってアトミックに処理され、全ノードにパブリッシュされる。

## パフォーマンス要件

- シードホスト解決は並列実行される
- ピア探索は設定された間隔で非同期実行
- 大規模クラスタではシードホストの数を適切に設定することを推奨

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

- ノード参加時にクラスタ名の一致を検証
- TLS/SSL設定によりノード間通信を暗号化可能
- 適切なネットワークセグメンテーションを推奨

## 備考

- ディスカバリタイプは`zen`（デフォルト）または`single-node`
- Zen2はRaftベースのコンセンサスアルゴリズムを使用
- プラグインによりカスタムシードホストプロバイダーを追加可能（EC2、GCE、Azure等）

---

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

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

### 推奨読解順序

#### Step 1: モジュール初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DiscoveryModule.java | `server/src/main/java/org/opensearch/discovery/DiscoveryModule.java` | ディスカバリモジュールの初期化。DISCOVERY_TYPE_SETTING、シードホストプロバイダーの設定を確認 |
| 1-2 | Discovery.java | `server/src/main/java/org/opensearch/discovery/Discovery.java` | Discoveryインターフェースの定義 |

**読解のコツ**: DiscoveryModuleはZEN2_DISCOVERY_TYPE（"zen"）とSINGLE_NODE_DISCOVERY_TYPE（"single-node"）の2つのタイプをサポート。両方ともCoordinatorを使用する。

#### Step 2: シードホスト解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SeedHostsProvider.java | `server/src/main/java/org/opensearch/discovery/SeedHostsProvider.java` | シードホストプロバイダーのインターフェース |
| 2-2 | SettingsBasedSeedHostsProvider.java | `server/src/main/java/org/opensearch/discovery/SettingsBasedSeedHostsProvider.java` | 設定ベースのプロバイダー実装 |
| 2-3 | FileBasedSeedHostsProvider.java | `server/src/main/java/org/opensearch/discovery/FileBasedSeedHostsProvider.java` | ファイルベースのプロバイダー実装 |
| 2-4 | SeedHostsResolver.java | `server/src/main/java/org/opensearch/discovery/SeedHostsResolver.java` | ホスト名解決処理 |

#### Step 3: ピア探索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PeerFinder.java | `server/src/main/java/org/opensearch/discovery/PeerFinder.java` | ピア探索の中核ロジック |
| 3-2 | HandshakingTransportAddressConnector.java | `server/src/main/java/org/opensearch/discovery/HandshakingTransportAddressConnector.java` | ノード接続・ハンドシェイク処理 |

#### Step 4: コーディネーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Coordinator.java | `server/src/main/java/org/opensearch/cluster/coordination/Coordinator.java` | ディスカバリの中心実装。Mode（CANDIDATE/LEADER/FOLLOWER）の状態遷移 |
| 4-2 | JoinHelper.java | `server/src/main/java/org/opensearch/cluster/coordination/JoinHelper.java` | クラスタ参加処理 |

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

```
Node起動
    |
    +-- DiscoveryModule
          |
          +-- SeedHostsProvider設定
          |     +-- SettingsBasedSeedHostsProvider
          |     +-- FileBasedSeedHostsProvider
          |
          +-- Coordinator生成
                |
                +-- PeerFinder
                |     +-- SeedHostsResolver.resolveHosts()
                |     +-- HandshakingTransportAddressConnector.connectToRemoteMasterNode()
                |
                +-- JoinHelper
                |     +-- sendJoinRequest()
                |
                +-- ClusterBootstrapService（初期クラスタ時）
```

### データフロー図

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

opensearch.yml ------> DiscoveryModule -------------------------> ClusterState更新
 (discovery.seed_hosts,  |                                         (nodes追加)
  discovery.type)        +-> SeedHostsResolver
                         |     +-> ホスト名解決
unicast_hosts.txt -----> |
                         +-> PeerFinder
                         |     +-> ピアプローブ
                         |     +-> ハンドシェイク
                         |
                         +-> Coordinator
                               +-> JoinRequest
                               +-> クラスタ状態更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DiscoveryModule.java | `server/src/main/java/org/opensearch/discovery/DiscoveryModule.java` | ソース | モジュール初期化 |
| Discovery.java | `server/src/main/java/org/opensearch/discovery/Discovery.java` | ソース | Discoveryインターフェース |
| SeedHostsProvider.java | `server/src/main/java/org/opensearch/discovery/SeedHostsProvider.java` | ソース | シードホストプロバイダーインターフェース |
| SettingsBasedSeedHostsProvider.java | `server/src/main/java/org/opensearch/discovery/SettingsBasedSeedHostsProvider.java` | ソース | 設定ベースプロバイダー |
| FileBasedSeedHostsProvider.java | `server/src/main/java/org/opensearch/discovery/FileBasedSeedHostsProvider.java` | ソース | ファイルベースプロバイダー |
| SeedHostsResolver.java | `server/src/main/java/org/opensearch/discovery/SeedHostsResolver.java` | ソース | ホスト名解決 |
| PeerFinder.java | `server/src/main/java/org/opensearch/discovery/PeerFinder.java` | ソース | ピア探索 |
| HandshakingTransportAddressConnector.java | `server/src/main/java/org/opensearch/discovery/HandshakingTransportAddressConnector.java` | ソース | ハンドシェイク処理 |
| Coordinator.java | `server/src/main/java/org/opensearch/cluster/coordination/Coordinator.java` | ソース | コーディネーション中心実装 |
| JoinHelper.java | `server/src/main/java/org/opensearch/cluster/coordination/JoinHelper.java` | ソース | クラスタ参加処理 |
| ClusterBootstrapService.java | `server/src/main/java/org/opensearch/cluster/coordination/ClusterBootstrapService.java` | ソース | 初期クラスタブートストラップ |
| DiscoveryStats.java | `server/src/main/java/org/opensearch/discovery/DiscoveryStats.java` | ソース | ディスカバリ統計 |
