如何处理elasticsearch集群red问题
1 | GET /_cluster/health?pretty |
1 | { |
elasticsearch 分片的状态有3种:
- green:已分配所有分片
- yellow: 表示主分片已分配但有副本未分配
- red: 有主分片未被分配
索引级别状态由最差的分片状态控制。群集状态由最差的索引状态控制。可以通过下面两个接口查看出问题的index和shard,如果出问题的index是可以删除的,那么删除该索引可以直接解决问题。若不能删除,那么需要手动reroute。
1 | GET /_cluster/health?pretty&level=indices |
什么是分片分配
分片分配是将分片分配给群集中的节点的过程。为了扩展到庞大的文档集并在节点失败时提供高可用性,Elasticsearch将索引的文档拆分为分片,每个分片驻留在集群中的节点上。
- 如果无法分配主分片,则索引将缺少数据和/或不能将新文档写入索引。
- 如果无法分配副本分片,则在存在主分片的节点发生永久性故障(例如,损坏的磁盘)的情况下,群集可能会丢失数据。
- 如果分片分配到慢速节点,则高流量索引将受到位于较慢机器上的分片的影响,并且群集的性能将降低。
分片分配对于新建索引和已有索引的逻辑是不同的。在这两种情况下,Elasticsearch都有两个主要组件参与其中:分配器和决策器。分配器尝试找到保存分片的最佳节点,并且决策者是否允许分配给节点。
对于新创建的索引,分配器查找其上具有最少量分片的节点,并返回按分片权重排序的节点列表,其中具有最少分片权重的节点首先出现。分配器对新创建的索引的目标是以一种导致最平衡的集群的方式将索引的分片分配给节点。然后,决策者按顺序获取每个节点,并决定是否允许将该分片分配给该节点。例如,如果设置过滤器分配规则以防止节点A保存索引idx的任何分片,那么过滤器决策器将阻止分配idx的分片到节点A(即使A是最优节点)。注意,分配器仅考虑每个节点的分片数,而不是每个分片的大小。其中一个决策者的工作是阻止分配超过特定磁盘占用率阈值的节点。
对于现有索引,我们必须进一步区分主分片和副本分片。对于主分片,分配器将仅允许分配给已经拥有该分片的已知良好副本的节点。如果分配器没有采取这样的步骤,那么将主分片分配给尚未具有该分片的最新副本的节点将导致数据丢失!在副本分片的情况下,分配器首先查看是否已经存在其他节点上的分片(甚至是过时副本)的副本。如果是这样,分配器将优先将分片分配给其中一个持有副本的节点,因为副本一旦分配就需要与主节点同步,并且节点已经有一些分片数据意味着少量数据必须从主数据库复制到副本。
unassigned reason
查看未分配的shards:
1 | $ curl -s "http://{ESIP}:9200/_cat/shards" | grep UNASSIGNED |
查看shard unassigned的原因:
1 | GET _cat/shards?h=index,shard,prirep,state,unassigned.reason |
通过上面的接口,我们可以看到shard未分配的根本原因。共有下面几种原因:
reason | desc |
---|---|
INDEX_CREATED | Unassigned as a result of an API creation of an index. |
CLUSTER_RECOVERED | Unassigned as a result of a full cluster recovery. |
INDEX_REOPENED | Unassigned as a result of opening a closed index. |
DANGLING_INDEX_IMPORTED | Unassigned as a result of importing a dangling index. |
NEW_INDEX_RESTORED | Unassigned as a result of restoring into a new index. |
EXISTING_INDEX_RESTORED | Unassigned as a result of restoring into a closed index. |
REPLICA_ADDED | Unassigned as a result of explicit addition of a replica. |
ALLOCATION_FAILED | Unassigned as a result of a failed allocation of the shard. |
NODE_LEFT | Unassigned as a result of the node hosting it leaving the cluster. |
REROUTE_CANCELLED | Unassigned as a result of explicit cancel reroute command. |
REINITIALIZED | When a shard moves from started back to initializing, for example, with shadow replicas. |
REALLOCATED_REPLICA | A better replica location is identified and causes the existing replica allocation to be cancelled. |
cluster allocation explain
集群分配说明API的目的是为集群中的分片分配提供解释.对于未分配的分片,explain API提供了分片未分配原因的说明。对于已分配的分片,explain API提供了有关分片在其当前节点上保留但未移动或重新平衡到另一个节点的原因的说明。在尝试诊断分片未分配的原因或者为什么分片会继续保留在当前节点上时,这个API非常有用。
可以使用index和shard id来指定你想要explain的shard。primary标志着是否解释给定shard id 的主分片,或是它的其中一个副本分片。
1 | GET /_cluster/allocation/explain |
同样我们可以指定current_node来explain在当前node上的一个分片
1 | GET /_cluster/allocation/explain |
一种更方便的使用方式如下,这可以解释ES找到的第一个未分配的分片。
1 | GET /_cluster/allocation/explain |
有关explain的返回的详细解释可以查看cluster allocation explain
reroute unassigned shards
重新路由命令允许手动更改群集中各个分片的分配。例如,可以显式地将分片从一个节点移动到另一个节点,可以取消分配,并且可以将未分配的分片显式分配给特定节点。
1 | POST /_cluster/reroute |
要注意,在处理任何重新路由命令之后,Elasticsearch将正常执行重新平衡(如果值cluster.routing.rebalance.enable设置为true,该值默认为true)以保持平衡状态。例如,如果将分片从node1中移动到node2后,reblance可能导致分片从node2后退node1,以实现均匀分布。
为了避免这个问题,可以用?dry_run参数,这将使集群不执行实际的reroute操作,而是返回应用reroute和rebalance后的群集状态。
在实际执行时,可以使用?explain参数,响应中会包含有关命令可执行或不执行的原因的详细说明。
reroute 可以使用下面的3种命令:
- move:将已启动的分片从一个节点移动到另一个节点。接受索引名称index和分片编号shard,从from_node节点移动分片,以及将分片移动到to_node节点。
- cancel:取消分配碎片(或恢复)。接受索引名称index和分片编号shard,以及取消分片分配的节点node。这可以用于强制从主分片重新同步现有副本,并允许它们通过标准恢复过程重新初始化。默认情况下,只能取消副本分片分配。如果需要取消主分片的分配,则allow_primary标志也必须包含在请求中。
- allocate_replica:将未分配的副本分片分配给节点。接受索引名称index和分片编号shard,以及分配分片的node。
reroute 时还要考虑分片分配的一些配置(在分片分配的文章中会有详细介绍)
在放弃分配分片并导致分片未分配之前,群集将尝试连续分配最多index.allocation.max_retries 次分片(默认为5)。一旦引起分片失败的原因得到解决,可以通过手动调用 _cluster/reroute?retry_failed
来单次重试分配这些分片。
上面的allocate_replica 只是分配未分配的副本shard,还有两个命令可用于将主分片分配给节点。但是,这些命令应谨慎使用,因为主要分片分配通常由Elasticsearch完全自动处理。无法自动分配主分片的原因包括:
- 创建了一个新索引,但没有满足分配决策者的节点。
- 无法在群集中的当前数据节点上找到最新的数据分片副本。为防止数据丢失,系统不会自动将旧的分片副本提升为主分片。
两个命令很危险,可能会导致数据丢失。它们适用于无法恢复原始数据且集群管理员接受丢失的情况。要强调:如果执行了这些命令,然后某个节点加入了包含受影响的分片副本的集群,则将删除或覆盖新加入的节点上的副本。
- allocate_stale_primary:将主分片分配给包含过时副本的节点。接受索引名称index和分片shard编号,并将分片分配给node。使用此命令可能会导致提供的分片ID丢失数据。如果具有良好数据副本的节点稍后重新加入群集,则将使用此命令强制分配的过时副本的数据删除或覆盖该数据。为确保充分理解这些含义,此命令需要将标志 accept_data_loss显式设置为true。
- allocate_empty_primary:将空主分片分配给节点。接受索引名称index和分片shard编号,并将分片分配给node。如果先前已启动,则使用此命令会导致完全丢失已编入此分片的所有数据。如果稍后具有数据副本的节点重新加入群集,则将删除该数据。为确保充分理解这些含义,此命令需要将标志 accept_data_loss显式设置为true。
1 | { |
使用allocate_stale_primary,你需要知道unassigned 主分片 原来所在的节点,将该节点名设置为node的值
- cat shards
- elasticsearch blog