之前在IDC機房線上環境部署了一套ELK日誌集中分析系統, 這裡簡單總結下ELK中Elasticsearch健康狀態相關問題, Elasticsearch的索引狀態和叢集狀態傳達著不同的意思。
一. Elasticsearch 叢集健康狀態
一個 Elasticsearch 叢集至少包括一個節點和一個索引。或者它 可能有一百個資料節點、三個單獨的主節點,以及一小打客戶端節點——這些共同操作一千個索引(以及上萬個分片)。但是不管叢集擴充套件到多大規模,你都會想要一個快速獲取叢集狀態的途徑。Cluster Health API 充當的就是這個角色。你可以把它想象成是在一萬英尺的高度鳥瞰叢集。它可以告訴你安心吧一切都好,或者警告你叢集某個地方有問題。Elasticsearch 裡其他 API 一樣,cluster-health 會返回一個 JSON 響應。這對自動化和告警系統來說,非常便於解析。響應中包含了和你叢集有關的一些關鍵資訊:
檢視Elasticsearch健康狀態 (*表示ES叢集的master主節點) [root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cat/nodes?v' host ip heap.percent ram.percent load node.role master name 10.0.8.47 10.0.8.47 53 85 0.16 d * elk-node03.kevin.cn 10.0.8.44 10.0.8.44 26 54 0.09 d m elk-node01.kevin.cn 10.0.8.45 10.0.8.45 71 81 0.02 d m elk-node02.kevin.cn 下面兩條shell命令都可以監控到Elasticsearch健康狀態 [root@elk-node03 ~]# curl 10.0.8.47:9200/_cat/health 1554792912 14:55:12 kevin-elk green 3 3 4478 2239 0 0 0 0 - 100.0% [root@elk-node03 ~]# curl -X GET 'http://10.0.8.47:9200/_cluster/health?pretty' { "cluster_name" : "kevin-elk", #叢集名稱 "status" : "green", #為 green 則代表健康沒問題,如果是 yellow 或者 red 則是叢集有問題 "timed_out" : false, #是否有超時 "number_of_nodes" : 3, #叢集中的節點數量 "number_of_data_nodes" : 3, "active_primary_shards" : 2234, "active_shards" : 4468, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 #叢集分片的可用性百分比,如果為0則表示不可用 }
正常情況下,Elasticsearch 叢集健康狀態分為三種:
green 最健康得狀態,說明所有的分片包括備份都可用; 這種情況Elasticsearch叢集所有的主分片和副本分片都已分配, Elasticsearch叢集是 100% 可用的。
yellow 基本的分片可用,但是備份不可用(或者是沒有備份); 這種情況Elasticsearch叢集所有的主分片已經分片了,但至少還有一個副本是缺失的。不會有資料丟失,所以搜尋結果依然是完整的。不過,你的高可用性在某種程度上被弱化。如果 更多的 分片消失,你就會丟資料了。把 yellow 想象成一個需要及時調查的警告。
red 部分的分片可用,表明分片有一部分損壞。此時執行查詢部分資料仍然可以查到,遇到這種情況,還是趕快解決比較好; 這種情況Elasticsearch叢集至少一個主分片(以及它的全部副本)都在缺失中。這意味著你在缺少資料:搜尋只能返回部分資料,而分配到這個分片上的寫入請求會返回一個異常。
Elasticsearch 叢集不健康時的排查思路
-> 首先確保 es 主節點最先啟動,隨後啟動資料節點;
-> 允許 selinux(非必要),關閉 iptables;
-> 確保資料節點的elasticsearch配置檔案正確;
-> 系統最大開啟檔案描述符數是否夠用;
-> elasticsearch設定的記憶體是否夠用 ("ES_HEAP_SIZE"記憶體設定 和 "indices.fielddata.cache.size"上限設定);
-> elasticsearch的索引數量暴增 , 刪除一部分索引(尤其是不需要的索引);
二. Elasticsearch索引狀態
檢視Elasticsearch 索引狀態 (*表示ES叢集的master主節點) [root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cat/indices?v' health status index pri rep docs.count docs.deleted store.size pri.store.size green open 10.0.61.24-vfc-intf-ent-deposit.log-2019.03.15 5 1 159 0 324.9kb 162.4kb green open 10.0.61.24-vfc-intf-ent-login.log-2019.03.04 5 1 3247 0 3.4mb 1.6mb green open 10.0.61.24-vfc-intf-ent-login.log-2019.03.05 5 1 1663 0 2.6mb 1.3mb green open 10.0.61.24-vfc-intf-ent-deposit.log-2019.03.19 5 1 14 0 81.1kb 40.5kb ................. .................
Elasticsearch 索引的健康狀態也有三種,即yellow、green、red與叢集的健康狀態解釋是一樣的!
三. Elasticsearch 相關概念
- Elasticsearch叢集與節點
節點(node)是你執行的Elasticsearch例項。一個叢集(cluster)是一組具有相同cluster.name的節點集合,它們協同工作,共享資料並提供故障轉移和擴充套件功能,當有新的節點加入或者刪除節點,叢集就會感知到並平衡資料。叢集中一個節點會被選舉為主節點(master),它用來管理叢集中的一些變更,例如新建或刪除索引、增加或移除節點等;當然一個節點也可以組成一個叢集。
- Elasticsearch節點通訊
可以與叢集中的任何節點通訊,包括主節點。任何一個節點互相知道文件存在於哪個節點上,它們可以轉發請求到我們需要資料所在的節點上。我們通訊的節點負責收集各節點返回的資料,最後一起返回給客戶端。這一切都由Elasticsearch透明的管理。
- Elasticsearch叢集生態
-> 同叢集中節點之間可以擴容縮容;
-> 主分片的數量會在其索引建立完成後修正,但是副本分片的數量會隨時變化;
-> 相同的分片不會放在同一個節點上;
- Elasticsearch分片與副本分片
分片用於Elasticsearch在叢集中分配資料, 可以想象把分片當作資料的容器, 文件儲存在分片中,然後分片分配給你叢集中的節點上。 當叢集擴容或縮小,Elasticsearch將會自動在節點間遷移分片,以使叢集保持平衡。 一個分片(shard)是一個最小級別的“工作單元(worker unit)”,它只是儲存索引中所有資料的一小片.我們的文件儲存和被索引在分片中,但是我們的程式不知道如何直接與它們通訊。取而代之的是,它們直接與索引通訊.Elasticsearch中的分片分為主分片和副本分片,複製分片只是主分片的一個副本,它用於提供資料的冗餘副本,在硬體故障之後提供資料保護,同時服務於像搜尋和檢索等只讀請求,主分片的數量和複製分片的數量都可以通過配置檔案配置。但是主切片的數量只能在建立索引時定義且不能修改.相同的分片不會放在同一個節點上。
- Elasticsearch分片演算法
shard = hash(routing) % number_of_primary_shards
routing值是一個任意字串,它預設是_id但也可以自定義,這個routing字串通過雜湊函式生成一個數字,然後除以主切片的數量得到一個餘數(remainder),餘數的範圍永遠是0到number_of_primary_shards - 1,這個數字就是特定文件所在的分片。 這也解釋了為什麼主切片的數量只能在建立索引時定義且不能修改:如果主切片的數量在未來改變了,所有先前的路由值就失效了,文件也就永遠找不到了。所有的文件API(get、index、delete、bulk、update、mget)都接收一個routing引數,它用來自定義文件到分片的對映。自定義路由值可以確保所有相關文件.比如使用者的文章,按照使用者賬號路由,就可以實現屬於同一使用者的文件被儲存在同一分片上。
- Elasticsearch分片與副本互動
新建、索引和刪除請求都是寫(write)操作,它們必須在主分片上成功完成才能複製到相關的複製分片上,下面我們羅列在主分片和複製分片上成功新建、索引或刪除一個文件必要的順序步驟:
-> 客戶端給Node 1傳送新建、索引或刪除請求。
-> 節點使用文件的_id確定文件屬於分片0。它轉發請求到Node 3,分片0位於這個節點上。
-> Node 3在主分片上執行請求,如果成功,它轉發請求到相應的位於Node 1和Node 2的複製節點上。當所有的複製節點報告成功,Node 3報告成功到請求的節點,請求的節點再報告給客戶端。 客戶端接收到成功響應的時候,文件的修改已經被應用於主分片和所有的複製分片。你的修改生效了
- 檢視分片狀態
[root@elk-node03 ~]# curl -X GET 'http://10.0.8.47:9200/_cluster/health?pretty' { "cluster_name" : "kevin-elk", "status" : "green", "timed_out" : false, "number_of_nodes" : 3, "number_of_data_nodes" : 3, "active_primary_shards" : 2214, "active_shards" : 4428, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 }
這裡需要注意: 如下是單點單節點部署Elasticsearch, 叢集狀態可能為yellow, 因為單點部署Elasticsearch, 預設的分片副本數目配置為1,而相同的分片不能在一個節點上,所以就存在副本分片指定不明確的問題,所以顯示為yellow,可以通過在Elasticsearch叢集上新增一個節點來解決問題,如果不想這麼做,可以刪除那些指定不明確的副本分片(當然這不是一個好辦法)但是作為測試和解決辦法還是可以嘗試的,下面試一下刪除副本分片的辦法:
[root@elk-server ~]# curl -X GET 'http://localhost:9200/_cluster/health?pretty' { "cluster_name" : "elasticsearch", "status" : "yellow", "timed_out" : false, "number_of_nodes" : 1, "number_of_data_nodes" : 1, "active_primary_shards" : 931, "active_shards" : 931, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 930, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 50.02686727565825 } [root@elk-server ~]# curl -XPUT "http://localhost:9200/_settings" -d' { "number_of_replicas" : 0 } ' {"acknowledged":true} 這個時候再次檢視叢集的狀態狀態變成了green [root@elk-server ~]# curl -X GET 'http://localhost:9200/_cluster/health?pretty' { "cluster_name" : "elasticsearch", "status" : "green", "timed_out" : false, "number_of_nodes" : 1, "number_of_data_nodes" : 1, "active_primary_shards" : 931, "active_shards" : 931, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 }
- Elasticsearch索引的unssigned問題
如下, 訪問http://10.0.8.47:9200/_plugin/head/, 發現有unssigned現象:
這裡的unssigned就是未分配副本分片的問題,接下來執行settings中刪除副本分片的命令後, 這個問題就解決了:
[root@elk-node03 ~]# curl -XPUT "http://10.0.8.47:9200/_settings" -d' { "number_of_replicas" : 0 } ' {"acknowledged":true}
四. Elasticsearch叢集健康狀態為"red"現象的排查分析
通過Elasticsearch的Head外掛訪問, 發現Elasticsearch叢集的健康值為red, 則說明至少一個主分片分配失敗, 這將導致一些資料以及索引的某些部分不再可用。head外掛會以不同的顏色顯示, 綠色表示最健康的狀態,代表所有的主分片和副本分片都可用; 黃色表示所有的主分片可用,但是部分副本分片不可用; 紅色表示部分主分片不可用. (此時執行查詢部分資料仍然可以查到,遇到這種情況,還是趕快解決比較好)
接著檢視Elasticsearch啟動日誌會發現叢集服務超時連線的情況:
timeout notification from cluster service. timeout setting [1m], time since start [1m]
什麼是unassigned 分片?
一句話解釋:未分配的分片。 啟動ES的時候,通過Head外掛不停重新整理,就會發現叢集分片會呈現紫色、灰色、最終綠色的狀態。
為什麼會出現 unassigned 分片?
如果不能分配分片,例如已經為叢集中的節點數過分分配了副本分片的數量,則分片將保持UNASSIGNED狀態。 其錯誤碼為:ALLOCATION_FAILED。可以通過如下指令,檢視叢集中不同節點、不同索引的狀態.
[root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason'
出現unassigned 分片後的症狀?
head外掛檢視會:Elasticsearch啟動N長時候後,某一個或幾個分片仍持續為灰色。
unassigned 分片問題可能的原因?
INDEX_CREATED: 由於建立索引的API導致未分配。 CLUSTER_RECOVERED: 由於完全叢集恢復導致未分配。 INDEX_REOPENED: 由於開啟open或關閉close一個索引導致未分配。 DANGLING_INDEX_IMPORTED: 由於匯入dangling索引的結果導致未分配。 NEW_INDEX_RESTORED: 由於恢復到新索引導致未分配。 EXISTING_INDEX_RESTORED: 由於恢復到已關閉的索引導致未分配。 REPLICA_ADDED: 由於顯式新增副本分片導致未分配。 ALLOCATION_FAILED: 由於分片分配失敗導致未分配。 NODE_LEFT: 由於承載該分片的節點離開叢集導致未分配。 REINITIALIZED: 由於當分片從開始移動到初始化時導致未分配(例如,使用影子shadow副本分片)。 REROUTE_CANCELLED: 作為顯式取消重新路由命令的結果取消分配。 REALLOCATED_REPLICA: 確定更好的副本位置被標定使用,導致現有的副本分配被取消,出現未分配。
Elasticsearch叢集狀態紅色如何排查?
症狀:叢集健康值紅色;
日誌:叢集服務連線超時;
可能原因:叢集中部分節點的主分片未分配。
接下來的解決方案主要圍繞:使主分片unsigned 分片完成再分配展開。
如何解決 unassigned 分片問題?
方案一:極端情況——這個分片資料已經不可用,直接刪除該分片 (即刪除索引)
Elasticsearch中沒有直接刪除分片的介面,除非整個節點資料已不再使用,刪除節點。
刪除索引命令"curl -XDELETE http://10.0.8.44:9200/索引名"
方案二:叢集中節點數量 >= 叢集中所有索引的最大副本數量 +1
N > = R + 1
其中:
N——叢集中節點的數目;
R——叢集中所有索引的最大副本數目。
注意事項:當節點加入和離開叢集時,主節點會自動重新分配分片,以確保分片的多個副本不會分配給同一個節點。換句話說,主節點不會將主分片分配給與其副本相同的節點,也不會將同一分片的兩個副本分配給同一個節點。 如果沒有足夠的節點相應地分配分片,則分片可能會處於未分配狀態。
如果Elasticsearch叢集就一個節點,即N=1;所以R=0,才能滿足公式。這樣問題就轉嫁為:
1) 新增節點處理,即N增大;
2) 刪除副本分片,即R置為0。
R置為0的方式,可以通過如下命令列實現:
[root@elk-node03 ~]# curl -XPUT "http://10.0.8.47:9200/_settings" -d' { "number_of_replicas" : 0 } ' {"acknowledged":true}
方案三:allocate重新分配分片
如果方案二仍然未解決,可以考慮重新分配分片。可能的原因:
1) 節點在重新啟動時可能遇到問題。正常情況下,當一個節點恢復與群集的連線時,它會將有關其分片的資訊轉發給主節點,然後主節點將這分片從“未分配”轉換為 "已分配/已啟動"。
2) 當由於某種原因 (例如節點的儲存已被損壞) 導致該程式失敗時,分片可能保持未分配狀態。
在這種情況下,必須決定如何繼續: 嘗試讓原始節點恢復並重新加入叢集(並且不要強制分配主分片); 或者強制使用Reroute API分配分片並重新索引缺少的資料原始資料來源或備份。 如果你決定分配未分配的主分片,請確保將"allow_primary":"true"標誌新增到請求中。
Elasticsearch5.X使用指令碼如下:
#!/bin/bash NODE="YOUR NODE NAME" IFS=$'\n' for line in $(curl -s '10.0.8.47:9200/_cat/shards' | fgrep UNASSIGNED); do INDEX=$(echo $line | (awk '{print $1}')) SHARD=$(echo $line | (awk '{print $2}')) curl -XPOST '10.0.8.47:9200/_cluster/reroute' -d '{ "commands": [ { " allocate_replica ": { "index": "'$INDEX'", "shard": '$SHARD', "node": "'$NODE'", "allow_primary": true } } ] }' done
Elasticsearch2.X及早期版本,只需將上面指令碼中的allocate_replica改為 allocate,其他不變。
上面指令碼解讀:
步驟1:定位 UNASSIGNED 的節點和分片
curl -s '10.0.8.47:9200/_cat/shards' | fgrep UNASSIGNED
步驟2:通過 allocate_replica 將 UNASSIGNED的分片重新分配。
allocate分配原理
分配unassigned的分片到一個節點。將未分配的分片分配給節點。接受索引和分片的索引名稱和分片號,以及將分片分配給它的節點。它還接受allow_primary標誌來明確指定允許顯式分配主分片(可能導致資料丟失)。
五. 分享一個案例: ELK中ElasticSearch叢集狀態異常問題
線上環境部署的ELK日誌集中分析系統, 過了一段時間後, 發現Kibana展示裡沒有日誌, 檢視head外掛索引情況, 發現一直打不開! 這是因為如果不對es索引定期做處理, 則隨著日誌收集資料量的不斷增大, es記憶體消耗不斷增量, 索引數量也會隨之暴增, 那麼elk就會出現問題, 比如elk頁面展示超時, 訪問http://10.0.8.47:9200/_plugin/head/ 一直卡頓等; es叢集狀態異常(出現red的status)等!
在任意一個node節點上執行下面命令檢視es叢集狀態 (url裡的ip地址可以是三個node中的任意一個), 如下可知, es叢集當前master節點是10.0.8.47
[root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cat/nodes?v' host ip heap.percent ram.percent load node.role master name 10.0.8.47 10.0.8.47 31 78 0.92 d * elk-node03.kevin.cn 10.0.8.44 10.0.8.44 16 55 0.27 d m elk-node01.kevin.cn 10.0.8.45 10.0.8.45 61 78 0.11 d m elk-node02.kevin.cn
查詢叢集的健康狀態(一共三種狀態:green、yellow,red;其中green表示健康)
[root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cat/health?v' epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1554689492 10:11:32 kevin-elk red 3 3 3587 3447 0 6 5555 567 11.1m 39.2%
解決辦法:
1) 調優叢集的穩定性
-> 增大系統最大開啟檔案描述符數,即65535;
-> 關閉swap,鎖定程式地址空間,防止記憶體swap;
-> JVM調優, 增大es記憶體設定, 預設是2g (Heap Size不超過實體記憶體的一半,且小於32G);
2) 定期刪除es索引或刪除不可用的索引, 比如只保留最近一個月的索引資料 (可寫指令碼定期執行, 具體可參考: https://www.cnblogs.com/kevingrace/p/9994178.html);
3) 如果es主節點重啟, 則主節點在轉移到其他節點過程中, 分片分片也會轉移過去; 如果分片比較多, 資料量比較大, 則需要耗費一定的時間, 在此過程中, elk叢集的狀態是yellow; 檢視elk叢集狀態, shards分片會不斷增加, unassign會不斷減少,直至unassign減到0時, 表明分片已經完全轉移到新的主節點上, 則此時檢視elk的健康狀態就是green了;
4) 如果所有es節點都重啟, 則需要先啟動一個節點作為master主節點, 然後再啟動其他節點;
注意, 這裡記錄下修改ElasticSearch的記憶體配置操作 ("ES_HEAP_SIZE"記憶體設定 和 "indices.fielddata.cache.size"上限設定)
先修改/etc/sysconfig/elasticsearch 檔案裡的ES_HEAP_SIZE引數值, 預設為2g [root@elk-node03 ~]# vim /etc/sysconfig/elasticsearch ............. ES_HEAP_SIZE=8g 接著修改elasticsearch配置檔案 [root@elk-node03 ~]# vim /etc/elasticsearch/elasticsearch.yml ............. bootstrap.mlockall: true #預設為false. 表示鎖住記憶體.當JVM進行記憶體轉換時,es效能會降低, 設定此引數值為true即可鎖住記憶體. 注意: 這個時候最好在elasticsearch.yml配置檔案裡設定下indices.fielddata.cache.size , 此參數列示"控制有多少堆記憶體是分配給fielddata" 因為elasticsearch在查詢時,fielddata快取的資料越來越多造成的(預設是不自動清理的) [root@elk-node03 ~]# vim /etc/elasticsearch/elasticsearch.yml .............. indices.fielddata.cache.size: 40% 上面設定了限制fielddata 上限, 表示讓欄位資料快取的記憶體大小達到heap 40% (也就是上面設定的8g的40%)的時候就起用自動清理舊的快取資料 然後重啟elasticsearch [root@elk-node03 ~]# systemctl restart elasticsearch 檢視啟動的elasticsearch, 發現記憶體已經調整到8g了 [root@elk-node03 ~]# ps -ef|grep elasticsearch root 7066 3032 0 16:46 pts/0 00:00:00 grep --color=auto elasticsearch elastic+ 15586 1 22 10:33 ? 01:22:00 /bin/java -Xms8g -Xmx8g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -Djna.nosys=true -Des.path.home=/usr/share/elasticsearch -cp /usr/share/elasticsearch/lib/elasticsearch-2.4.6.jar:/usr/share/elasticsearch/lib/* org.elasticsearch.bootstrap.Elasticsearch start -Des.pidfile=/var/run/elasticsearch/elasticsearch.pid -Des.default.path.home=/usr/share/elasticsearch -Des.default.path.logs=/var/log/elasticsearch -Des.default.path.data=/var/lib/elasticsearch -Des.default.path.conf=/etc/elasticsearch
如上, 在進行一系列修復操作 (增大系統最大開啟檔案描述符數65535, 關閉swap,鎖定程式地址空間,防止記憶體swap, 增大ES記憶體, 刪除不用或異常索引, 重啟各節點的ES服務) 後, 再次檢視ES叢集狀態, 發現此時仍然是"red"狀態. 這是因為es主節點重啟, 則主節點在轉移到其他節點過程中, 分片分片也會轉移過去; 如果分片比較多, 資料量比較大, 則需要耗費一定的時間. 需要等到unassign減到0時, 表明分片已經完全轉移到新的主節點上, 則此時檢視elk的健康狀態就是green了.
[root@elk-node02 system]# curl -XGET 'http://10.0.8.47:9200/_cat/health?v' epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1554691187 10:39:47 kevin-elk red 3 3 4460 3878 0 8 4660 935 5.7m 48.9% [root@elk-node02 system]# curl -XGET 'http://10.0.8.47:9200/_cat/health?v' epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1554691187 10:39:47 kevin-elk red 3 3 4466 3882 0 8 4654 944 5.7m 48.9% ................ ................ 等到"unassign"數值為0時, 再次檢視es狀態 [root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cat/health?v' epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1554692772 11:06:12 kevin-elk green 3 3 9118 4559 0 0 0 0 - 100.0% 如果es狀態此時還是red, 則需要找出red狀態的索引並且刪除 (這個時候的red狀態的索引應該是少部分) [root@elk-node02 system]# curl -XGET "http://10.0.8.45:9200/_cat/indices?v"|grep -w "red" 比如找出的red狀態的索引名為"10.0.61.24-vfc-intf-ent-order.log-2019.03.04", 刪除它即可 [root@elk-node02 system]# curl -XDELETE http://10.0.8.44:9200/10.0.61.24-vfc-intf-ent-order.log-2019.03.04
需要特別注意: 如果elasticSearch叢集節點中es資料所在的磁碟使用率超過了一定比例(比如85%), 則就會出現無法再為副分片分片的情況, 這也會導致elasticSearch叢集監控狀態也會出現"red"情況!!! 這個時候只需要增大這塊磁碟的空間, 磁碟空間夠用了, elasticSearch就會自動恢復資料!!!
六. Elasticsearch常見錯誤
錯誤1: Exception in thread "main" SettingsException[Failed to load settings from [elasticsearch.yml]]; nested: ElasticsearchParseException[malformed, expected settings to start with 'object', instead was [VALUE_STRING]];
原因:elasticsearch.yml檔案配置錯誤導致 解決:引數與引數值(等號)間需要空格 [root@elk-node03 ~]# vim /etc/elasticsearch/elasticsearch.yml ............... #node.name:elk-node03.kevin.cn #錯誤 node.name: elk-node03.kevin.cn #正確 #或者如下配置 #node.name ="elk-node03.kevin.cn" #錯誤 #node.name = "elk-node03.kevin.cn" #正確 然後重啟elasticsearch服務
錯誤2: org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root
原因:處於對root使用者的安全保護,需要使用其他使用者組進行授權啟動 解決: 使用者組進行授權啟動 [root@elk-node03 ~]# groupadd elasticsearch [root@elk-node03 ~]# useradd elasticsearch -g elasticsearch -p elasticsearch [root@elk-node03 ~]# chown -R elasticsearch.elasticsearch /data/es-data #給es的資料目錄授權, 否則es服務啟動報錯 [root@elk-node03 ~]# chown -R elasticsearch.elasticsearch/var/log/elasticsearch #給es的日誌目錄授權, 否則es服務啟動報錯 以上是yum安裝elasticsearch情況, 需要給elasticsearch的資料目錄和日誌目錄授權, 如果elasticsearch是編譯安裝, 則需要給它的安裝目錄也授權 接著重啟elasticsearch服務即可
錯誤3: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot a ...'(errno=12);
原因:jvm要分配最大記憶體超出系統記憶體 解決:適當調整指定jvm記憶體, 編輯elasticsearch 的jvm配置檔案 # vim /data/elasticsearch/config/jvm.options -Xms8g -Xmx8g 如果是yum安裝的elasticsearch, 則修改如下配置檔案 [root@elk-node03 ~]# vim /etc/sysconfig/elasticsearch # Heap size defaults to 256m min, 1g max #最小為1g # Set ES_HEAP_SIZE to 50% of available RAM, but no more than 31g #設定為實體記憶體的50%, 但不要操作31g ES_HEAP_SIZE=8g 然後重啟elasticsearch服務即可
錯誤4: ERROR: [3] bootstrap checks failed
詳細報錯: [INFO ][o.e.b.BootstrapChecks ] [SUcoFrg] bound or publishing to a non-loopback address, enforcing bootstrap checks ERROR: [3] bootstrap checks failed [1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] [2]: max number of threads [3802] for user [elsearch] is too low, increase to at least [4096] [3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] [2019-02-20T02:35:47,170][INFO ][o.e.n.Node ] [SUcoFrg] stopping ... [2019-02-20T02:35:47,316][INFO ][o.e.n.Node ] [SUcoFrg] stopped [2019-02-20T02:35:47,316][INFO ][o.e.n.Node ] [SUcoFrg] closing ... [2019-02-20T02:35:47,336][INFO ][o.e.n.Node ] [SUcoFrg] closed 原因:虛擬機器限制使用者的執行記憶體 解決: [1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] [2]: max number of threads [3802] for user [elasticsearch] is too low, increase to at least [4096] 修改安全限制配置檔案 (使用root最高許可權 修改安全配置 在檔案末尾加入) [root@elk-node03 ~]# vim /etc/security/limits.conf elasticsearch hard nofile 65536 elasticsearch soft nofile 65536 * soft nproc 4096 * hard nproc 4096 修改系統配置檔案 [3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] [root@elk-node03 ~]# /etc/sysctl.conf #注意下面的引數值大於錯誤提示值 vm.max_map_count = 655360 然後重啟elasticsearch服務即可
錯誤5: org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: failed to obtain node locks, tried [[/home/elasticsearch-6.3.0/data/elasticsearch]] with lock id [0]; maybe these locations are not writable or multiple nodes were started without increasing [node.max_local_storage_nodes] (was [1])?
詳細報錯: [2019-02-20T04:23:25,003][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main] org.elasticsearch.bootstrap.StartupException: java.lang.IllegalStateException: failed to obtain node locks, tried [[/home/elasticsearch-6.3.0/data/elasticsearch]] with lock id [0]; maybe these locations are not writable or multiple nodes were started without increasing [node.max_local_storage_nodes] (was [1])? at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:140) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:127) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[elasticsearch-cli-6.3.0.jar:6.3.0] at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:86) ~[elasticsearch-6.3.0.jar:6.3.0] Caused by: java.lang.IllegalStateException: failed to obtain node locks, tried [[/home/elasticsearch-6.3.0/data/elasticsearch]] with lock id [0]; maybe these locations are not writable or multiple nodes were started without increasing [node.max_local_storage_nodes] (was [1])? at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:243) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.node.Node.<init>(Node.java:270) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.node.Node.<init>(Node.java:252) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:213) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:213) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:326) ~[elasticsearch-6.3.0.jar:6.3.0] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:136) ~[elasticsearch-6.3.0.jar:6.3.0] ... 6 more 原因:執行緒佔用 解決:重新啟動 [root@elk-node03 ~]# ps -ef|grep elasticsearch|awk -F" " '{print $2}'|xargs kill -9 [root@elk-node03 ~]# systemctl start elasticsearch [root@elk-node03 ~]# systemctl restart elasticsearch [root@elk-node03 ~]# ps -ef|grep -v grep|grep elasticsearch elastic+ 15586 1 11 Apr08 ? 03:06:12 /bin/java -Xms8g -Xmx8g -Djava.awt.headless=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -Djna.nosys=true -Des.path.home=/usr/share/elasticsearch -cp /usr/share/elasticsearch/lib/elasticsearch-2.4.6.jar:/usr/share/elasticsearch/lib/* org.elasticsearch.bootstrap.Elasticsearch start -Des.pidfile=/var/run/elasticsearch/elasticsearch.pid -Des.default.path.home=/usr/share/elasticsearch -Des.default.path.logs=/var/log/elasticsearch -Des.default.path.data=/var/lib/elasticsearch -Des.default.path.conf=/etc/elasticsearch 一定要確保elasticsearch是用非root賬號啟動的
錯誤6: [Godfrey Calthrop] All shards failed for phase: [query] [jr-2018.08.06][[jr-2018.08.06][2]] NoShardAvailableActionException[null]
詳細報錯: [2019-02-06 18:27:24,553][DEBUG][action.search ] [Godfrey Calthrop] All shards failed for phase: [query] [jr-2018.08.06][[jr-2018.08.06][2]] NoShardAvailableActionException[null] at org.elasticsearch.action.search.AbstractSearchAsyncAction.start(AbstractSearchAsyncAction.java:129) at org.elasticsearch.action.search.TransportSearchAction.doExecute(TransportSearchAction.java:115) at org.elasticsearch.action.search.TransportSearchAction.doExecute(TransportSearchAction.java:47) at org.elasticsearch.action.support.TransportAction.doExecute(TransportAction.java:149) at org.elasticsearch.action.support.TransportAction.execute(TransportAction.java:137) at org.elasticsearch.action.support.TransportAction.execute(TransportAction.java:85) at org.elasticsearch.client.node.NodeClient.doExecute(NodeClient.java:58) at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:359) at org.elasticsearch.client.FilterClient.doExecute(FilterClient.java:52) at org.elasticsearch.rest.BaseRestHandler$HeadersAndContextCopyClient.doExecute(BaseRestHandler.java:83) at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:359) at org.elasticsearch.client.support.AbstractClient.search(AbstractClient.java:582) at org.elasticsearch.rest.action.search.RestSearchAction.handleRequest(RestSearchAction.java:85) at org.elasticsearch.rest.BaseRestHandler.handleRequest(BaseRestHandler.java:54) at org.elasticsearch.rest.RestController.executeHandler(RestController.java:205) at org.elasticsearch.rest.RestController.dispatchRequest(RestController.java:166) at org.elasticsearch.http.HttpServer.internalDispatchRequest(HttpServer.java:128) at org.elasticsearch.http.HttpServer$Dispatcher.dispatchRequest(HttpServer.java:86) at org.elasticsearch.http.netty.NettyHttpServerTransport.dispatchRequest(NettyHttpServerTransport.java:449) at org.elasticsearch.http.netty.HttpRequestHandler.messageReceived(HttpRequestHandler.java:61) 問題解決 通過以上排查大概知道是歷史索引資料處於 open 狀態過多,從而導致ES的CPU,記憶體佔用過高導致的不可用。 關閉不需要的索引,減少記憶體佔用 [root@elk-node03 ~]# curl -XPOST "http://10.0.8.44:9200/index_name/_close" 如果發現在關閉非熱點索引資料後,elasticSearch叢集的健康值依然是"red"狀態,這時候要想到: 可能索引的"red"狀態可能會影響ES的狀態. 接著檢視elasticSearch索引健康狀態, 發現果不其然 [root@elk-node03 ~]# curl GET http://10.0.8.44:9200/_cluster/health?level=indices { "cluster_name": "kevin-elk", "status": "red", "timed_out": false, "number_of_nodes": 3, "number_of_data_nodes": 3, "active_primary_shards": 660, "active_shards": 660, "relocating_shards": 0, "initializing_shards": 0, "unassigned_shards": 9, "delayed_unassigned_shards": 0, "number_of_pending_tasks": 0, "number_of_in_flight_fetch": 0, "task_max_waiting_in_queue_millis": 0, "active_shards_percent_as_number": 98.65470852017937, "indices": { "jr-2019.02.06": { "status": "red", "number_of_shards": 3, "number_of_replicas": 0, "active_primary_shards": 0, "active_shards": 0, "relocating_shards": 0, "initializing_shards": 0, "unassigned_shards": 3 } } } 解決方法,刪除上面命令中檢視的有問題的那條索引資料(這條資料是排查問題期間產生的髒資料,索引直接刪除) [root@elk-node03 ~]# curl -XDELETE 'http://10.0.8.44:9200/jr-2019.02.06' 注意: 應注意elasticSearch的索引狀態以及伺服器的監控,及時清理或者關閉不必要的索引資料,避免這種情況發生。
七. Elasticsearch叢集監控狀態監控
1) 通過簡單shell命令監控elasticsearch叢集狀態
原理:使用curl命令模擬訪問任意一個elasticsearch叢集, 就可以反饋出elasticsearch叢集狀態,叢集的狀態需要為green
[root@elk-node03 ~]# curl -XGET 'http://10.0.8.47:9200/_cluster/stats?human&pretty' { "timestamp" : 1554792101956, "cluster_name" : "kevin-elk", "status" : "green", "indices" : { "count" : 451, "shards" : { "total" : 4478, "primaries" : 2239, "replication" : 1.0, "index" : { "shards" : { "min" : 2, "max" : 10, "avg" : 9.929046563192905 }, "primaries" : { "min" : 1, "max" : 5, "avg" : 4.964523281596453 }, "replication" : { "min" : 1.0, "max" : 1.0, "avg" : 1.0 } } }, "docs" : { "count" : 10448854, "deleted" : 3 }, "store" : { "size" : "5gb", "size_in_bytes" : 5467367887, "throttle_time" : "0s", "throttle_time_in_millis" : 0 }, "fielddata" : { "memory_size" : "0b", "memory_size_in_bytes" : 0, "evictions" : 0 }, "query_cache" : { "memory_size" : "0b", "memory_size_in_bytes" : 0, "total_count" : 364053, "hit_count" : 0, "miss_count" : 364053, "cache_size" : 0, "cache_count" : 0, "evictions" : 0 }, "completion" : { "size" : "0b", "size_in_bytes" : 0 }, "segments" : { "count" : 16635, "memory" : "83.6mb", "memory_in_bytes" : 87662804, "terms_memory" : "64.5mb", "terms_memory_in_bytes" : 67635408, "stored_fields_memory" : "6.3mb", "stored_fields_memory_in_bytes" : 6624464, "term_vectors_memory" : "0b", "term_vectors_memory_in_bytes" : 0, "norms_memory" : "6.1mb", "norms_memory_in_bytes" : 6478656, "doc_values_memory" : "6.6mb", "doc_values_memory_in_bytes" : 6924276, "index_writer_memory" : "448.1kb", "index_writer_memory_in_bytes" : 458896, "index_writer_max_memory" : "4.5gb", "index_writer_max_memory_in_bytes" : 4914063972, "version_map_memory" : "338b", "version_map_memory_in_bytes" : 338, "fixed_bit_set" : "0b", "fixed_bit_set_memory_in_bytes" : 0 }, "percolate" : { "total" : 0, "time" : "0s", "time_in_millis" : 0, "current" : 0, "memory_size_in_bytes" : -1, "memory_size" : "-1b", "queries" : 0 } }, "nodes" : { "count" : { "total" : 3, "master_only" : 0, "data_only" : 0, "master_data" : 3, "client" : 0 }, "versions" : [ "2.4.6" ], "os" : { "available_processors" : 24, "allocated_processors" : 24, "mem" : { "total" : "13.8gb", "total_in_bytes" : 14859091968 }, "names" : [ { "name" : "Linux", "count" : 3 } ] }, "process" : { "cpu" : { "percent" : 1 }, "open_file_descriptors" : { "min" : 9817, "max" : 9920, "avg" : 9866 } }, "jvm" : { "max_uptime" : "1.1d", "max_uptime_in_millis" : 101282315, "versions" : [ { "version" : "1.8.0_131", "vm_name" : "Java HotSpot(TM) 64-Bit Server VM", "vm_version" : "25.131-b11", "vm_vendor" : "Oracle Corporation", "count" : 3 } ], "mem" : { "heap_used" : "7.2gb", "heap_used_in_bytes" : 7800334800, "heap_max" : "23.8gb", "heap_max_in_bytes" : 25560612864 }, "threads" : 359 }, "fs" : { "total" : "1.1tb", "total_in_bytes" : 1241247670272, "free" : "1tb", "free_in_bytes" : 1206666141696, "available" : "1tb", "available_in_bytes" : 1143543336960 }, "plugins" : [ { "name" : "bigdesk", "version" : "master", "description" : "bigdesk -- Live charts and statistics for Elasticsearch cluster ", "url" : "/_plugin/bigdesk/", "jvm" : false, "site" : true }, { "name" : "head", "version" : "master", "description" : "head - A web front end for an elastic search cluster", "url" : "/_plugin/head/", "jvm" : false, "site" : true }, { "name" : "kopf", "version" : "2.0.1", "description" : "kopf - simple web administration tool for Elasticsearch", "url" : "/_plugin/kopf/", "jvm" : false, "site" : true } ] } } 以上監控命令列印的叢集統計資訊包含: Elasticsearch叢集的分片數,文件數,儲存空間,快取資訊,記憶體作用率,外掛內容,檔案系統內容,JVM 作用狀況,系統 CPU,OS 資訊,段資訊。
2) 利用指令碼監控elasticSearch叢集健康值green yellow red狀態
[root@elk-node03 ~]# curl 10.0.8.47:9200/_cat/health 1554864073 10:41:13 qwkg-elk green 3 3 4478 2239 0 0 0 0 - 100.0% 編寫python指令碼, 監控elasticsearch的健康狀態 [root@elk-node03 ~]# vim /opt/es_health_monit.py import commands command = 'curl 10.0.8.47:9200/_cat/health' (a, b) = commands.getstatusoutput(command) status= b.split(' ')[157] if status=='red': healthy=0 else: healthy=1 print healthy 手動執行指令碼, 列印出elasticsearch健康狀態 [root@elk-node03 ~]# chmod 755 /opt/es_health_monit.py [root@elk-node03 ~]# python /opt/es_health_monit.py 1 然後在指令碼中結合sendemail進行郵件報警 或者 新增到zabbix監控裡.