elasticsearch7.x滚动扩缩容-停机维护(不影响业务)

2,139 阅读6分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

image.png

前言

因业务的调整,elasticsearch需要扩容或者缩容的

因磁盘故障或停电,需要停机维护等需要关机重启的

在这方面因elasticsearch无中心化的特点,在扩缩容,停机维护方面可以让业务无感知,正常读写es集群

要实现以上功能,节点数必需在3个或5个以上,要么3个节点都是master,其他都是data节点。要么有3个节点既是master也是data

参数

es的数据冗余需要依靠一个参数: "number_of_replicas": "1",

假设你的集群是3个节点,上述参数设置为1 ,那就是有一个主分片和一个副本分片,总共有两份

如果一台节点挂掉,不影响集群读写。如果挂掉两个节点,那么有部分索引将无法写入,部分索引读取时只返回部分数据

状态

es分为三个状态:

  • Green 所有的主分片和副本分片都已分配。集群100% 可用的。
  • Yellow 所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的。高可用性在某种程度上被弱化,集群此时还可以写入
  • Red 至少一个主分片(以及它的全部副本)都在缺失,搜索只能返回部分数据,而分配到这个分片上的写入请求会返回一个异常

停机维护

停机维护的操作和集群升级相似,就是节点数据是不动的,节点关机再启动之后,马上可以投入服务,继续使用

但是因es无中心化特点,如果节点一旦关机,为保证服务可用性,数据会自动飘移到正常的节点,如果你的数据很大,这个动作很耗时间,且集群IO会很高,为此,需要在维护期间禁用分配

官网文档: www.elastic.co/guide/en/el…

分片文档: www.elastic.co/guide/en/el…

以下动作在kibana dev tools里面执行,后面的同样

1. 停止分配

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": "primaries"
  }
}

2. 执行同步
此步是可选的, 可不执行,等待集群自动完成

POST _flush/synced

3. 停机维护

停止es服务,然后关掉机器,接下来就可以更换磁盘,维护操作等后续操作

停止节点后,你的集群状态应该为Yellow,如果是Red说明有问题,查看所有索引副本是否设置为1

节点维护好之后,启动机器,启动服务,检查集群状态

systemctl stop elasticsearch.service
systemctl start elasticsearch.service

GET _cat/health
GET _cat/nodes

4. 启用分配

启用分配后,查看恢复进度

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": null
  }
}

GET _cat/recovery

扩缩容

扩容

新增一个节点,配置和原集群一样,启动服务,当节点加入集群后,会自动发现集群并由集群重新组织,均匀的分配数据到节点

官方文档: www.elastic.co/guide/en/el…

缩容

要进行缩容,请确保在缩容后你的节点数据大于副本数,且是奇数

且确保现有的索引 副本数大于或等于1,如果副本数为0,且分片又在缩容机上,会导致该索引数据丢失

可以利用集群级分片分配筛选来剔除节点,关闭节点之前移除它的碎片,等分片迁移完成后,就可以停止节点了

PUT _cluster/settings
{
  "transient" : {
    "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
  }
}

GET _cat/health

官方文档: www.elastic.co/guide/en/el…

故障排除

由于异常死机或其它原因导致节点挂掉,或者没有执行禁用分配,就长时间的停掉一个节点。就会出现故障

UNASSIGNED

大部分的故障是数据问题,要么没有分配,要么分配次数到了,要么磁盘快满,不分配了等等

image.png

  • 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 :确定更好的副本位置被标定使用,导致现有的副本分配被取消,出现未分配

排错命令

查看集群状态

GET _cluster/health

查看分片的状态

GET /_cluster/health?level=shards

查看没有分配的原因

GET _cluster/allocation/explain?pretty

下面的请求返回 unassigned.reason 列,该列指示未分配分片的原因。

GET _cat/shards?h=index,shard,prirep,state,unassigned.reason

查看正在恢复的分片

curl http://127.0.0.1:9200/_cat/recovery?active_only=true

查看所有索引的副本数

curl http://127.0.0.1:9200/_cluster/health?level=indices | jq .indices > test2222.txt
cat test2222.txt | jq .[].number_of_replicas | grep 0

查看所有分片的详情

curl http://127.0.0.1:9200/_cat/shards?v  > shared111.txt

查看各节点文件打开数限制

GET _nodes/stats/process?filter_path=**.max_file_descriptors

查看节点详情

GET _nodes/process

分配重试次数达上限

如果停机时间过长,可能会造成分配次数达上限,导致后面机器启动了也不分配

错误信息提取

点击head插件上面灰色的方块,查看错误信息,或者查看es日志

image.png

解决方案

官方文档: www.elastic.co/guide/en/el…

然后重试分配由于太多后续分配失败而阻塞的分片

POST _cluster/reroute?retry_failed=true

分片数已达到设置的值

reached the limit of incoming shard recoveries [2]

出现上面的报错,是因为停机时没有设置禁用分配,机器在重启过程中,已经有一部分分片副本被复制了,此时产生了3个副本。

此问题不需要手动干预,只需要等一会集群自动重新组织,会主动删除多余的数据(一般删除最早的数据,也就是停机的那台)

分配被禁止

replica allocations are forbidden due to cluster setting [cluster.routing.allocation.enable=primaries

如果出现以上错误,是因为分配被禁止了,一般是手动禁止了,有可能是前面操作忘记开启分配了,

执行开启分配

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": null
  }
}

主副分片不能存在同一个节点

the shard cannot be allocated to the same node on which a copy of the shard already exists

因为主分片和副本是不能在同一个节点的,如果报错,可以等集群自动调节,如果长时间未恢复,可手动指定分片到指定节点

官方文档: www.elastic.co/guide/en/el…

未实操过,且执行reroute时会有丢失数据风险,请注意不要在生产执行

POST /_cluster/reroute
{
    "commands":[{
        "allocate_replica":{
            "index":"索引名",
            "shard":4,
            "node":"节点ID"
        }
    }]
}