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
相关文章
相关标签/搜索