Skip to main content

OpenSearch 單節點、Replica 與 Cluster Health 整理

在單節點 OpenSearch(或 Elasticsearch)上開發時,_cluster/health 回傳 yellow 是常見現象——通常不代表叢集壞掉,而是 replica 分片找不到第二個 node 可放置。這篇整理 cluster health 的判讀方式、分片原理,以及開發/正式環境該怎麼設定 number_of_replicas


叢集健康狀態:Green / Yellow / Red

OpenSearch / Elasticsearch 依分片指派情況,將叢集健康狀態分為三種:

狀態條件
Green所有 primary 與 replica 分片皆已指派
Yellow所有 primary 正常,但有 replica 分片處於 unassigned
Red有 primary 分片遺失或未指派

以下是一段典型的 yellow 輸出(單節點 Docker 環境):

{
"cluster_name": "docker-cluster",
"status": "yellow",
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 6,
"active_shards": 6,
"unassigned_shards": 2,
"active_shards_percent_as_number": 75.0
}

重點欄位:

  • number_of_nodes: 1 — 單節點叢集
  • unassigned_shards: 2 — 有 2 個分片無法指派
  • status: "yellow" — primary 分片皆正常,但 replica 分片沒被放到任何 node

原因: 叢集只有 1 個 data node,部分 index 卻設定了 number_of_replicas = 1。Replica 不允許與自己的 primary 放在同一 node(見下文),因此 replica 分片變成 unassigned,叢集 health 即為 yellow。


單節點下的 Yellow 現象

列出所有 index 的 health 與 replica 設定:

curl "http://localhost:9200/_cat/indices?v"

範例輸出:

health status index pri rep
green open .opensearch-observability 1 0
green open .plugins-ml-config 1 0
yellow open documents-production 1 1
yellow open documents 1 1
green open .kibana_1 1 0

對照說明:

Indexrep狀態原因
.opensearch-observability.plugins-ml-config.kibana_10green無 replica,單節點即可滿足
documentsdocuments-production1yellow需要第二個 node 放置 replica

結論: yellow 在此情境下是預期行為,代表「設定了 replica,但叢集只有一個 node」,並非資料損壞或服務異常。


Primary 與 Replica 分片

一個 index 的資料會切分到多個 shard(分片)

  • Primary shard(主分片)

    • 實際儲存資料的分片
    • 所有寫入先落到 primary
  • Replica shard(副本分片)

    • Primary 的完整複本
    • 用途:容錯(node 故障時仍有備份)、分散讀取負載(查詢可打到 primary 或 replica)

核心規則: Replica 不會與對應的 primary 排在同一 node。若兩者同機,該 node 故障時 primary 與 replica 會同時失效,備援便失去意義。


Replica 的用途與代價

用途

  1. 高可用(High Availability)

    • 某 node 故障時,若 replica 仍在其他 node,index 可繼續讀寫
    • 以額外儲存空間換取服務不中斷
  2. 分散讀取負載

    • 查詢可分散到 primary 與各 replica
    • 1 個 primary + N 個 replica 分散在不同 node 時,讀取吞吐理論上可接近(N+1)倍
  3. 滾動升級與維護(Rolling Restart)

    • 下線 node-1 升級時,流量改打 node-2 的 replica
    • node-1 恢復後再輪替 node-2,對外幾乎不停機
  4. 跨 AZ / 機房容錯

    • Primary 放 AZ1、replica 放 AZ2;AZ1 故障時 AZ2 仍可服務(至少可讀)
  5. 維護操作的安全緩衝

    • 錯誤設定或手動 relocate 等操作出錯時,仍有另一份資料可恢復

代價

  • 儲存與運算:每個 replica 都是完整資料複本,磁碟用量增加,並消耗額外 CPU / RAM
  • 寫入效能:Primary 寫入後需同步至 replica,寫入延遲與吞吐會受影響

開發環境建議:是否啟用 Replica

適合關閉 replica 的情境:

  • 僅 1 個 node(本機 Docker、開發機)
  • 流量與使用者數量有限
  • 可接受單點故障時短暫停機

在單 node 上啟用 replica 的問題:

  • Replica 無法指派 → unassigned_shards → health 維持 yellow
  • 無實際備援效果
  • 讀取負載尚不需要分散

建議: 開發、本機測試、或流量小且可接受停機的階段,將所有 index 的 number_of_replicas 設為 0,單節點即可維持 green,操作也最單純。

以下情況再考慮提高 replica 並擴充 node:

  • 遷移至正式環境(至少 2 個 data node)
  • 不能接受單點故障導致搜尋中斷
  • 讀取壓力明顯成長

單節點設定:關閉 Replica 取得 Green

調整既有 index

將 yellow 的 index(例如 documentsdocuments-production)副本數改為 0:

curl -X PUT "http://localhost:9200/documents/_settings" \
-H 'Content-Type: application/json' \
-d '{
"index": {
"number_of_replicas": 0
}
}'

curl -X PUT "http://localhost:9200/documents-production/_settings" \
-H 'Content-Type: application/json' \
-d '{
"index": {
"number_of_replicas": 0
}
}'

確認叢集狀態:

curl "http://localhost:9200/_cluster/health?pretty"

若所有 index 的 replica 皆為 0,status 應為 greenunassigned_shards 為 0。

設定新建 index 的預設值(選用)

避免日後新建 index 又自動變 yellow,可設定叢集層級預設:

curl -X PUT "http://localhost:9200/_settings" \
-H 'Content-Type: application/json' \
-d '{
"index": {
"number_of_replicas": 0
}
}'

之後新建的 index 若未另行指定 replica 數,預設即為 0。


多節點叢集:啟用 Replica

當需要真正的 replica 備援時,叢集至少需要 2 個 data node。

本機跑兩個 node(Docker)

在本機多跑一個 OpenSearch container,兩個 node 共用同一 cluster.name

設定項Node 1Node 2
node.nameopensearch-node1opensearch-node2
cluster.namedocker-cluster(兩者相同)同左
discovery.seed_hosts包含兩個 node 名稱同左

Node 2 的 docker run 示意:

docker run -d --name opensearch-node2 \
-p 9201:9200 -p 9601:9600 \
-e "cluster.name=docker-cluster" \
-e "node.name=opensearch-node2" \
-e "discovery.seed_hosts=opensearch-node1,opensearch-node2" \
-e "cluster.initial_cluster_manager_nodes=opensearch-node1" \
opensearchproject/opensearch:VERSION

兩個 node 啟動後確認:

curl "http://localhost:9200/_cat/nodes?v"

看到 2 個 node 後,將 index 設為 number_of_replicas: 1,replica 即可排到第二個 node,health 會變 green。

若使用 docker-compose.yml,可複製一份 service,修改 node.name 與 port 對應即可。

兩台實體機或 VM

假設:

  • 機器 A:10.0.0.1(node-1)
  • 機器 B:10.0.0.2(node-2)

機器 A(node-1):

cluster.name: docker-cluster
node.name: node-1
network.host: 10.0.0.1
discovery.seed_hosts: ["10.0.0.1", "10.0.0.2"]
cluster.initial_cluster_manager_nodes: ["node-1"]

機器 B(node-2):

cluster.name: docker-cluster
node.name: node-2
network.host: 10.0.0.2
discovery.seed_hosts: ["10.0.0.1", "10.0.0.2"]
cluster.initial_cluster_manager_nodes: ["node-1"]

兩台啟動後,在任一台執行:

curl "http://10.0.0.1:9200/_cat/nodes?v"

確認出現 2 個 node 後,將 number_of_replicas 設為 1,replica 會自動排到另一台機器。


實務建議總結

情境Replica 設定Node 數量預期 health
開發 / 本機測試01green
正式環境、需高可用>= 1(通常為 1)>= replica + 1green

現在(開發 / 單機):

  • 將所有 index 的 number_of_replicas 設為 0
  • 設定叢集預設 replica 為 0
  • 維持單純的 green 單節點叢集

未來(正式 / 多機):

  • 使用者與讀取壓力成長、需高可用時
  • 增加 data node,再將 replica 調高(通常為 1)
  • 以額外儲存與寫入成本換取容錯與讀取效能

一句話: 開發/單機用 replicas = 0;正式/多機用 replicas >= 1,依可靠度需求調整。