Elasticsearch 集羣和索引健康狀態及常見錯誤說明

 

以前在IDC機房環境部署了一套ELK日誌集中分析系統, 這裏簡單總結下ELK中Elasticsearch健康狀態相關問題, Elasticsearch的索引狀態和集羣狀態傳達着不一樣的意思。html

一.  Elasticsearch 集羣健康狀態
一個 Elasticsearch 集羣至少包括一個節點和一個索引。或者它 可能有一百個數據節點、三個單獨的主節點,以及一小打客戶端節點——這些共同操做一千個索引(以及上萬個分片)。可是無論集羣擴展到多大規模,你都會想要一個快速獲取集羣狀態的途徑。Cluster Health API 充當的就是這個角色。你能夠把它想象成是在一萬英尺的高度鳥瞰集羣。它能夠告訴你安心吧一切都好,或者警告你集羣某個地方有問題。Elasticsearch 裏其餘 API 同樣,cluster-health 會返回一個 JSON 響應。這對自動化和告警系統來講,很是便於解析。響應中包含了和你集羣有關的一些關鍵信息:java

查看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集羣至少一個主分片(以及它的所有副本)都在缺失中。這意味着你在缺乏數據:搜索只能返回部分數據,而分配到這個分片上的寫入請求會返回一個異常。node

Elasticsearch 集羣不健康時的排查思路
->  首先確保 es 主節點最早啓動,隨後啓動數據節點;
->  容許 selinux(非必要),關閉 iptables;
->  確保數據節點的elasticsearch配置文件正確;
->  系統最大打開文件描述符數是否夠用;
->  elasticsearch設置的內存是否夠用 ("ES_HEAP_SIZE"內存設置 和 "indices.fielddata.cache.size"上限設置);
->  elasticsearch的索引數量暴增 , 刪除一部分索引(尤爲是不須要的索引);python

二.  Elasticsearch索引狀態linux

查看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與集羣的健康狀態解釋是同樣的!web

三.  Elasticsearch 相關概念面試

-  Elasticsearch集羣與節點
節點(node)是你運行的Elasticsearch實例。一個集羣(cluster)是一組具備相同cluster.name的節點集合,它們協同工做,共享數據並提供故障轉移和擴展功能,當有新的節點加入或者刪除節點,集羣就會感知到並平衡數據。集羣中一個節點會被選舉爲主節點(master),它用來管理集羣中的一些變動,例如新建或刪除索引、增長或移除節點等;固然一個節點也能夠組成一個集羣。 算法

-  Elasticsearch節點通訊
能夠與集羣中的任何節點通訊,包括主節點。任何一個節點互相知道文檔存在於哪一個節點上,它們能夠轉發請求到咱們須要數據所在的節點上。咱們通訊的節點負責收集各節點返回的數據,最後一塊兒返回給客戶端。這一切都由Elasticsearch透明的管理。shell

-  Elasticsearch集羣生態
-> 同集羣中節點之間能夠擴容縮容;
-> 主分片的數量會在其索引建立完成後修正,可是副本分片的數量會隨時變化; 
-> 相同的分片不會放在同一個節點上;bootstrap

-  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監控裏.

八.  Elasticsearch配置中防止腦裂的配置

Master和DataNode未分離,致使集羣不穩定
在ES集羣中,節點分爲Master、DataNode、Client等幾種角色,任何一個節點均可以同時具有以上全部角色,其中比較重要的角色爲Master和DataNode:
1. Master主要管理集羣信息、primary分片和replica分片信息、維護index信息。
2. DataNode用來存儲數據,維護倒排索引,提供數據檢索等。

能夠看到元信息都在Master上面,若是Master掛掉了,該Master含有的全部Index都沒法訪問,文檔中說,爲了保證Master穩定,須要將Master和Node分離。而構建master集羣可能會產生一種叫作腦裂的問題,爲了防止腦裂,須要設置最小master的節點數爲eligible_master_number/2 + 1

腦裂的概念:
若是有兩個Master候選節點,並設置最小Master節點數爲1,則當網絡抖動或偶然斷開時,兩個Master都會認爲另外一個Master掛掉了,它們都被選舉爲主Master,則此時集羣中存在兩個主Master,即物理上一個集羣變成了邏輯上的兩個集羣,而當其中一個Master再次掛掉時,即使它恢復後回到了原有的集羣,在它做爲主Master期間寫入的數據都會丟失,由於它上面維護了Index信息。

根據以上理論,能夠對集羣作了以下更改,額外選取三個獨立的機器做爲Master節點,修改elasticsearch.yml配置

node.master = true
node.data = false
discovery.zen.minimum_master_nodes = 2

修改其餘節點配置,將其設置爲DataNode,最後依次重啓

node.master = false
node.data = true
相關文章
相關標籤/搜索