这个问题困扰过我一段时间,它其实是说未能选举出一个主节点,最后在官网教程中找到答案。
首先是启动(链接):
总结下来就是,如果ES集群是第一次启动,那么需要 cluster.initial_master_nodes 配置指定一个master类型的节点列表来进行选举一个主节点.
另外,已经加入集群的几点信息保存在data目录下,以供下次启动使用,这样也就是说cluster.initial_master_nodes就不在起作用了。
接着是选举配置(链接)
大致意思是说,每个ES集群都维护一个选举配置集合(Voting Configurations),这个选举集合由可以选举为主节点的master类型节点组成。
它除了提供选举功能,还决定者集群的状态,当选举配置集合中超过一半的节点存活时,集群才提供服务(也就是过半原则,通常集群解决脑裂问题都是采用这种方式)
我们可以通过ES提供的API接口来查看选举配置集合中有哪些节点:
curl -X GET "http://localhost:9200/_cluster/state?filter_path=metadata.cluster_coordination.last_committed_config&pretty"
基于这两点,如果是第一次启动集群,往往是因为没有配置 cluster.initial_master_nodes 参数导致的。如果不是第一次启动,也就是说集群启动的节点不满足过半原则,不能选举出主节点,这样只需要将过半的节点启动就可以了。
但是这便有了另一个问题,但如果不愿意启动多个节点,也就是要将多节点集群降级,也就是如何减少集群中的节点数呢?
发现很多推荐做法是清空data目录,确实这样相当于重新启动而创建一个全新的集群,可以解决问题,但是结果是导致所有的数据丢失。后来在官网上也找到了解决办法(链接):
大致说了3点重要信息: 1、一次性删除节点不要太多,比如我们原来集群选举有7个master类型的节点,如果要缩减到只有3个节点的集群,如果直接关掉4个节点,会发现集群挂了,因为不满足过半原则,同时抛出警告:master not discovered or elected yet。 2、建议一个个的删除节点,然后留给集群足够的时间,让它自动调整Voting Configurations中的配置 3、如果只剩下最后两个节点了,那么都不能删除,如果要删除,就要配置Voting configuration exclusions来实现
事实上,ES有个cluster.auto_shrink_voting_configuration配置,默认是true,表示当节点挂掉之后是否调整Voting Configurations,也就是说自动将挂掉的节点从Voting Configurations中剔除,这样也会影响过半原则的判定,比如本来Voting Configurations中有5个节点,它最多可容忍2个节点丢失,如果停了2个节点,那么等ES自动调整Voting Configurations后,集群中还有3个节点,这也就是说还能容忍一个节点丢失,所以我们可以一台一台的停止一些节点,让ES自动从Voting Configurations中剔除掉停止了的节点(切记不要一次停止过多节点,否则可能在Voting Configurations自动调整前而导致不满足过半原则而导致集群停止服务),但是需要注意的是,它旨在master节点大于等于3时有效,也就是说Voting Configurations中至少会保存3个master类型的节点信息。
可能这与上面的描述有点差入,自动调整只能将Voting Configurations中的节点减少到3个,但是当Voting Configurations中有3个master类型节点时,虽然Voting Configurations不会再自动减少节点数,当有一个节点挂掉时,集群还是可以提供服务的,因为它满足过半原则,所以可能作者认为2个和3个节点是一样的吧。
换句话说,对于只有2个或者3个节点的集群,我们就要结合Voting configuration exclusions还实现了。
举个例子,假如现在我们有3台服务器的集群(192.168.209.128,192.168.209.129,192.168.209.130),各节点配置如下:
192.168.209.128
# 节点名称 node.name: node-128 # 节点列表 discovery.seed_hosts: ["192.168.209.128", "192.168.209.129", "192.168.209.130"] # 初始化时master节点的选举列表 cluster.initial_master_nodes: [ "node-128", "node-129", "node-130" ] # 集群名称 cluster.name: cluster-name
192.168.209.129
# 节点名称 node.name: node-129 # 节点列表 discovery.seed_hosts: ["192.168.209.128", "192.168.209.129", "192.168.209.130"] # 初始化时master节点的选举列表 #cluster.initial_master_nodes: [ "node-128", "node-129", "node-130" ] # 集群名称 cluster.name: cluster-name
192.168.209.130
# 节点名称 node.name: node-130 # 节点列表 discovery.seed_hosts: ["192.168.209.128", "192.168.209.129", "192.168.209.130"] # 初始化时master节点的选举列表 #cluster.initial_master_nodes: [ "node-128", "node-129", "node-130" ] # 集群名称 cluster.name: cluster-name
现在要将它降为单节点集群,如果我们直接关闭两个节点,那么集群因为不满足过半原则而无法提供服务。
Voting configuration exclusions是一个类似于Voting configuration的集合,只是处于这个排除列表中的节点不会被选举,,等同于从选举集合中删除了(链接):
# 查看排除列表 curl -X GET "http://localhost:9200/_cluster/state?filter_path=metadata.cluster_coordination.voting_config_exclusions&pretty" # 添加排除,也就是从配置集合中删除,可以使用节点Id(node_ids)或者节点名称(node_names)来排除,如果执行失败,加上参数 wait_for_removal=false 试试 curl -X POST "http://localhost:9200/_cluster/voting_config_exclusions?node_names=<node_names>" curl -X POST "http://localhost:9200/_cluster/voting_config_exclusions?node_ids=<node_ids>" # 清空排除列表 curl -X DELETE "http://localhost:9200/_cluster/voting_config_exclusions"
如果执行结果返回:timed out waiting for removal of nodes; if nodes should not be removed, set waitForRemoval to false
可以在执行时在url中添加参数 wait_for_removal=false,比如我这里因为要保留192.168.209.128,所在在192.168.209.128上执行:
# 添加到排除列表 curl -X POST "http://192.168.209.128:9200/_cluster/voting_config_exclusions?node_names=node-129,node-130" # 清空排除列表 curl -X DELETE "http://192.168.209.128:9200/_cluster/voting_config_exclusions?wait_for_removal=false"
上面我这里将node-129,node-130加入到排除列表之后,node-128就会被选举为主节点,这个时候就可以将node-129和node-130停掉,而后node-128还是正常提供服务的
注:操作完成之后,记得清空Voting configuration exclusions
这样,我们就从一个3个节点的集群降级为单节点集群了,之后只启动node-128节点也就是单节点集群了。