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
對照說明:
| Index | rep | 狀態 | 原因 |
|---|---|---|---|
.opensearch-observability、.plugins-ml-config、.kibana_1 | 0 | green | 無 replica,單節點即可滿足 |
documents、documents-production | 1 | yellow | 需要第二個 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 的用途與代價
用途
-
高可用(High Availability)
- 某 node 故障時,若 replica 仍在其他 node,index 可繼續讀寫
- 以額外儲存空間換取服務不中斷
-
分散讀取負載
- 查詢可分散到 primary 與各 replica
- 1 個 primary + N 個 replica 分散在不同 node 時,讀取吞吐理論上可接近(N+1)倍
-
滾動升級與維護(Rolling Restart)
- 下線 node-1 升級時,流量改打 node-2 的 replica
- node-1 恢復後再輪替 node-2,對外幾乎不停機
-
跨 AZ / 機房容錯
- Primary 放 AZ1、replica 放 AZ2;AZ1 故障時 AZ2 仍可服務(至少可讀)
-
維護操作的安全緩衝
- 錯誤設定或手動 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(例如 documents、documents-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 應為 green,unassigned_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 1 | Node 2 |
|---|---|---|
node.name | opensearch-node1 | opensearch-node2 |
cluster.name | docker-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 |
|---|---|---|---|
| 開發 / 本機測試 | 0 | 1 | green |
| 正式環境、需高可用 | >= 1(通常為 1) | >= replica + 1 | green |
現在(開發 / 單機):
- 將所有 index 的
number_of_replicas設為 0 - 設定叢集預設 replica 為 0
- 維持單純的 green 單節點叢集
未來(正式 / 多機):
- 使用者與讀取壓力成長、需高可用時
- 增加 data node,再將 replica 調高(通常為 1)
- 以額外儲存與寫入成本換取容錯與讀取效能
一句話: 開發/單機用
replicas = 0;正式/多機用replicas >= 1,依可靠度需求調整。