問題概述

Elasticsearch 集羣狀態為 "red",由於某個索引的主分片數據在所有節點上丟失,導致集羣健康檢查失敗,Pod 就緒探針無法通過。

故障現象

  • 集羣狀態: red
  • 未分配分片: 1個
  • Pod 狀態: 0/1 (就緒探針失敗)
  • 錯誤信息: no_valid_shard_copy
  • 影響: 服務不可用,應用無法連接 Elasticsearch

根本原因

索引分片數據損壞或丟失,所有節點上均找不到有效的數據副本。

環境信息

  • 命名空間: system
  • Elasticsearch 集羣: 3節點 StatefulSet
  • 認證: 啓用基礎認證
  • 就緒探針: 要求集羣狀態達到 yellow

處理步驟

步驟1: 診斷集羣狀態

bash

# 檢查集羣健康狀態
kubectl exec -it -n system elasticsearch-master-0 -- curl -u <username>:<password> http://localhost:9200/_cluster/health?pretty

# 查看未分配的分片詳情
kubectl exec -it -n system elasticsearch-master-0 -- curl -u <username>:<password> http://localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason | grep UNASSIGNED

# 分析分片分配問題
kubectl exec -it -n system elasticsearch-master-0 -- curl -u <username>:<password> http://localhost:9200/_cluster/allocation/explain?pretty

步驟2: 識別問題分片

執行診斷命令後,通常會看到類似輸出:

json

{
  "index" : "problem_index",
  "shard" : 2,
  "primary" : true,
  "current_state" : "unassigned",
  "unassigned_info" : {
    "reason" : "CLUSTER_RECOVERED",
    "last_allocation_status" : "no_valid_shard_copy"
  },
  "can_allocate" : "no_valid_shard_copy"
}

步驟3: 處理損壞的分片

根據業務需求選擇以下方案:

方案A: 刪除損壞索引(數據可丟失時使用)本次修復使用的就是刪除損壞索引,刪除後會出發其他分片重新分配

  • active_primary_shards: 大量減少
  • unassigned_shards: 大量增加
  • initializing_shards: 有分片在初始化
  • 這表明刪除索引觸發了大規模的分片重新平衡,但集羣可能遇到了資源或配置問題。

bash

# 刪除有問題的索引(謹慎操作!)
kubectl exec -it -n system elasticsearch-master-0 -- curl -X DELETE -u <username>:<password> http://localhost:9200/problem_index

# 驗證刪除結果
kubectl exec -it -n system elasticsearch-master-0 -- curl -u <username>:<password> http://localhost:9200/_cluster/health?pretty

方案B: 強制分配空分片(保留索引結構)

bash

# 強制分配空的主分片(接受數據丟失)
kubectl exec -it -n system elasticsearch-master-0 -- curl -X POST -u <username>:<password> http://localhost:9200/_cluster/reroute -H 'Content-Type: application/json' -d'
{
  "commands": [
    {
      "allocate_empty_primary": {
        "index": "problem_index",
        "shard": 2,
        "node": "target-node-id",
        "accept_data_loss": true
      }
    }
  ]
}'

方案C: 從備份恢復(如果有可用備份)

bash

# 從快照恢復索引
kubectl exec -it -n system elasticsearch-master-0 -- curl -X POST -u <username>:<password> http://localhost:9200/_snapshot/repository/snapshot_name/_restore -H 'Content-Type: application/json' -d'
{
  "indices": "problem_index",
  "ignore_unavailable": false
}'

步驟4: 驗證修復結果

bash

# 檢查集羣狀態(應該變為 green 或 yellow)
kubectl exec -it -n system elasticsearch-master-0 -- curl -u <username>:<password> http://localhost:9200/_cluster/health?pretty

# 檢查 Pod 狀態(應該變為 Ready)
kubectl get pods -n system -l app=elasticsearch-master

# 測試服務連接
kubectl exec -it -n system elasticsearch-master-0 -- curl -u <username>:<password> http://elasticsearch-master.dacs.svc.cluster.local:9200/

緊急恢復方案

如果上述方法無效,考慮集羣重啓:

方案D: 集羣順序重啓

bash

# 1. 縮減副本數為1
kubectl scale statefulset -n dacs elasticsearch-master --replicas=1

# 2. 等待單節點穩定
kubectl logs -n system elasticsearch-master-0 -f

# 3. 逐步擴展回3節點
kubectl scale statefulset -n system elasticsearch-master --replicas=3

方案E: 完全重建(最後手段)

bash

# 完全清理並重建(數據會丟失!)
kubectl delete statefulset -n system elasticsearch-master
kubectl delete pvc -n system -l app=elasticsearch-master

# 重新部署
kubectl apply -f elasticsearch-statefulset.yaml

故障預防建議

1. 配置優化

yaml

# 增加副本數提高容錯
index.number_of_replicas: 1

# 配置定期快照
path.repo: ["/snapshots"]

2. 監控告警

  • 監控集羣狀態(green/yellow/red)
  • 設置未分配分片數量告警
  • 監控節點磁盤使用率

3. 運維規範

  • 定期備份重要索引
  • 測試恢復流程
  • 避免直接操作生產集羣數據

注意事項

  1. 數據丟失風險: 方案A和方案B會導致數據丟失,務必確認業務影響
  2. 備份優先: 優先考慮從備份恢復
  3. 業務影響: 處理期間服務可能不可用
  4. 權限要求: 需要集羣管理員權限執行修復操作

成功標準

  • 集羣狀態變為 green 或 yellow
  • 未分配分片數量為 0
  • 所有 Pod 狀態為 Ready
  • 服務可正常連接和訪問
  • 應用功能恢復正常