ElasticSearch集群部署

发布 : 2017-07-24 分类 : elasticsearch 浏览 :

CentOS 7中启用并使用”ifconfig”命令

1
yum install net-tools -y

ES集群

1
2
3
192.168.31.180 elasticsearch01
192.168.31.181 elasticsearch02
192.168.31.182 elasticsearch03

解压ES压缩文件&重命名

1
2
3
[root@elasticsearch01 ~]# tar -zxvf elasticsearch-5.5.0.tar.gz -C /usr/local
[root@elasticsearch01 ~]# cd /usr/local/
[root@elasticsearch01 local]# mv elasticsearch-5.5.0 elasticsearch

zen discovery集群发现机制

如何让多台机器上的多个es进程,互相发现对方,然后组成生产环境集群

默认情况下,es进程会绑定在自己的回环地址上,也就是127.0.0.1,然后扫描本机上的9300~9305端口号,尝试跟那些端口上启动的其他es进程进行通信,然后组成一个集群。这对于在本机上搭建es集群的开发环境是很方便的。但是对于生产环境下的集群是不行的,需要将每台es进程绑定在一个非回环的ip地址上,才能跟其他节点进行通信,同时需要使用集群发现机制来跟其他节点上的es node进行通信

在生产环境中的多台机器上部署es集群,涉及到es的discovery机制,也就是集群中各个节点互相发现后组成一个集群的机制,同时discovery机制负责es集群的master选举

master node和data node两种角色

es是一种peer to peer,p2p点对点的分布式系统架构(集群中的每个node直接跟其他节点进行通信,几乎所有API操作,如index,delete,search,都不是client跟master通信,而是client跟任何一个node进行通信,node再将请求转发给对应的node进行执行),不是hadoop生态采用的master-slave主从架构的分布式系统架构

两个角色,master node,data node。正常情况下,就只有一个master node

master node负责维护整个集群的状态信息[集群元数据信息],同时在node加入集群或者从集群中下限覅按时,重新分配shard,或者是创建或删除了一个索引。包括每次cluster state如果有改变的化,那么master都会负责将集群状态同步给所有的node

master node负责接收所有的cluster state相关的变化信息,将这个改变后的最新的cluster state推动给集群中所有的data node,集群中所有的node都有一份完整的cluster state,master node负责维护

data node负责数据的存储和读写的,写入索引,搜索数据

设置cluster.name

如果要让多个node组成一个es集群,第一个要设置的参数,是cluster.name,多个node的cluster.name一样,才满足组成一个集群的基本条件

这个cluster.name的默认值是elasticsearch,在生产环境中,一定要修改这个值,否则可能会导致未知的node无端加入集群,造成集群运行异常。

而es中默认的discovery机制,就是zen discovery机制

zen discovery机制提供了unicast discovery集群发现机制,集群发现时的节点间通信是依赖的transport module,也就是es底层的网络通信模块和协议。

es默认配置为使用unicast集群发现机制,以让经过特殊配置的节点可以组成一个集群,而不是随便哪个节点都可以组成一个集群。但是默认配置下,unicast是本机,也就是localhost,因此只能在一台机器上启动多个node来组成一个集群。虽然es还是会提供multicast plugin作为一个发现机制,但是已经不建议在生产环境中使用了。虽然我们可能想要multicast的简单性,就是所有的node可以再接收到一条multicast ping之后就立即自动加入集群。但是multicast机制有很多的问题,而且很脆弱,比如网络有轻微的调整,就可能导致节点无法发现对方。因此现在建议在生产环境中用unicast机制,提供一个es种子node作为中转路由节点就可以

master node、data node、network.host

给集群规划出专门的master eligible node和data node

master node,master eligible node,data node

配置多个node变成master eligible node,从这些master eligible node选举一个node出来作为master node,其他master eligible node只是接下来有那个master node故障的时候,接替他的资格,但是还是作为data node去使用的

一般建议master eligible node给3个即可:node.master: true,node.data: false
剩下的node都设置为data node:node.master: false,node.data: true

但是如果一个小集群,就10个以内的节点,那就所有节点都可以作为master eligible node以及data node即可,超过10个node的集群再单独拆分master和data node吧

如果你的节点数量小于10个,小集群,那所有的node,就不要做额外的配置了,master eligible node,同时也是data node

默认情况下,es会将自己绑定到127.0.0.1上,对于运行一个单节点的开发模式下的es是ok的。但是为了让节点间可以互相通信以组成一个集群,需要让节点绑定到一个ip地址上,非回环的地址,一般会配置:
network.host: 192.168.1.10

一旦我们配置了network.host,那么es就会认为我们从开发模式迁移到生产模式,同时会启用一系列的bootstrap check

ping

ping是一个node用discovery机制来发现其他node的一个过程

unicast

unicast discovery集群发现机制是要求配置一个主机列表,用来作为gossip(流言式)通信协议的路由器。这些机器如果通过hostname来指定,那么在ping的时候会被解析为ip地址。unicast discovery机制最重要的两个配置如下所示:

hosts:用逗号分割的主机列表
hosts.resolve_timeout:hostname被DNS解析为ip地址的timeout等待时长

简单来说,如果要让多个节点发现对方并且组成一个集群,那么就得有一个中间的公共节点,然后不同的节点就发送请求到这些公共节点,接着通过这些公共节点交换各自的信息,进而让所有的node感知到其他的node存在,并且进行通信,最后组成一个集群。这就是基于gossip流言式通信协议的unicast集群发现机制。

当一个node与unicast node list中的一个成员通信之后,就会接收到一份完整的集群状态,这里会列出集群中所有的node。接着那个node再通过cluster state跟master通信,并且加入集群中。这就意味着,我们的unicast list node是不需要列出集群中的所有节点的。只要提供少数几个node,比如3个,让新的node可以连接上即可。如果我们给集群中分配了几个节点作为专门的master节点,那么只要列出我们那三个专门的master节点即可。用如下的配置即可:discovery.zen.ping.unicast.hosts: [“host1”, “host2:port”]。

cluster.name
node.name
network.host
discovery.zen.ping.unicast.hosts

1
2
3
4
5
6
7
(1)通过network.host绑定到了非回环的ip地址,从而可以跟其他节点通信
(2)通过discovery.zen.ping.unicast.hosts配置了一批unicast中间路由的node
(3)所有node都可以发送ping消息到路由node,再从路由node获取cluster state回来
(4)接着所有node会选举出一个master
(5)所有node都会跟master进行通信,然后加入master的集群
(6)要求cluster.name必须一样,才能组成一个集群
(7)node.name就标识出了每个node我们自己设置的一个名称

master选举

在ping发现过程中,为集群选举出一个master也是很重要的,es集群会自动完成这个操作。设置discovery.zen.ping_timeout参数(默认是3s),如果网络慢或者拥塞,导致master选举超时,可以增加这个参数,确保集群启动的稳定性。

在完成一个集群的master选举之后,每次一个新的node加入集群,都会发送一个join request到master node,可以设置discovery.zen.join_timeout,保证node稳定加入集群,增加join的timeout等待时长,如果一次join不上,默认会重试20次

如果master node被停止了,或者自己宕机了,那么集群中的node会再次进行一次ping过程,并且选举出一个新的master。discovery.zen.master_election.ignore_non_master_pings设置为true,会强制区分master候选节点,如果node的node.master设置为了false,还来发送ping请求参与master选举,那么这些node会被忽略掉,因为他们没有资格参与。

discovery.zen.minimum_master_nodes参数用于设置对于一个新选举的master,要求必须有多少个master候选node去连接那个新选举的master。而且还用于设置一个集群中必须拥有的master候选node。如果这些要求没有被满足,那么master node就会被停止,然后会重新选举一个新的master。这个参数必须设置为我们的master候选node的quorum数量。一般避免说只有两个master候选node,因为2的quorum还是2。如果在那个情况下,任何一个master候选节点宕机了,集群就无法正常运作了。

集群故障的探查

es有两种集群故障探查机制

  • 第一种是通过master进行的,master会ping集群中所有的其他node,确保它们是否是存活着的
  • 第二种,每个node都会去ping master node来确保master node是存活的,否则就会发起一个选举过程。

有下面三个参数用来配置集群故障的探查过程:

  • ping_interval:每隔多长时间会ping一次node,默认是1s
  • ping_timeout:每次ping的timeout等待时长是多长时间,默认是30s
  • ping_retries:一个node被ping多少次都失败了,就会认为node故障,默认是3次

集群状态更新

master node是集群中唯一一个可以对cluster state进行更新的node。master node每次会处理一个集群状态的更新事件,应用这次状态更新,然后将更新后的状态发布到集群中所有的node上去。每个node都会接收publish message,ack这个message,但是不会应用这个更新。如果master没有在discovery.zen.commit_timeout指定的时间内(默认是30s),从至少discovery.zen.minimum_master_nodes个节点获取ack响应,那么这次cluster state change事件就会被reject,不会应用。

但是一旦在指定时间内,指定数量的node都返回了ack消息,那么cluster state就会被commit,然后一个message会被发送给所有的node。所有的node接收到那个commit message之后,接着才会将之前接收到的集群状态应用到自己本地的状态副本中去。接着master会等待所有节点再次响应是否更新自己本地副本状态成功,在一个等待超时时长内,如果接收到了响应,那么就会继续处理内存queue中保存的下一个更新状态。discovery.zen.publish_timeout默认是30s,这个超时等待时长是从plublish cluster state开始计算的。

不因为master宕机阻塞集群操作

如果要让集群正常运转,那么必须有一个master,还有discovery.zen.minimum_master_nodes指定数量的master候选node,都在运行

discovery.zen.no_master_block可以控制当master当即时,什么样的操作应该被拒绝。有下面两个选项:
all:一旦master当即,那么所有的操作都会被拒绝
write:这是默认的选项,所有的写操作都会被拒绝,但是读操作是被允许的

在三台机器上创建目录

1
2
3
4
5
6
7
8
9
10
11
mkdir -p /var/log/elasticsearch
mkdir -p /var/data/elasticsearch
mkdir -p /var/plugin/elasticsearch
mkdir -p /etc/elasticsearch

chown -R elasticsearch /usr/local/elasticsearch
chown -R elasticsearch /var/log/elasticsearch
chown -R elasticsearch /var/data/elasticsearch
chown -R elasticsearch /var/plugin/elasticsearch
chown -R elasticsearch /etc/elasticsearch
chown -R elasticsearch /usr/local/tmp

修改配置文件

1
2
3
4
[root@elasticsearch01 ~]# cp /usr/local/elasticsearch/config/elasticsearch.yml  /etc/elasticsearch/
[root@elasticsearch01 ~]# cp /usr/local/elasticsearch/config/log4j2.properties /etc/elasticsearch/
[root@elasticsearch01 ~]# cp /usr/local/elasticsearch/config/jvm.options /etc/elasticsearch/
[root@elasticsearch01 ~]# cd /etc/elasticsearch/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@elasticsearch01 elasticsearch]# vi elasticsearch.yml
# 与其他机器组成的集群名称
cluster.name: cluster-elasticsearch-prod
# 节点名称
node.name: node-elasticsearch-01
# bootstrap.memory_lock: false
# 绑定到非回环ip地址,可以与其他机器进行通信
network.host: 192.168.31.180
discovery.zen.ping.unicast.hosts: ["elasticsearch01", "elasticsearch02","elasticsearch03"]
discovery.zen.ping_timeout: 60s
discovery.zen.join_timeout: 60s
discovery.zen.master_election.ignore_non_master_pings: true
# 预防集群脑裂
discovery.zen.minimum_master_nodes: 3
# 设置数据文件目录
path.data: /var/data/elasticsearch
# 设置日志文件目录,可以指定多个目录,用逗号分隔即可
path.logs: /var/log/elasticsearch
# 设置插件存放目录
# path.plugins: /var/plugin/elasticsearch
# path.conf: /etc/elasticsearch
# 设置预防脑裂,预防一个集群中存在两个master
discovery.zen.minimum_master_nodes: 2
# es直到有足够的node都上线之后,再开始shard recovery的过程
gateway.recover_after_nodes: 2
# 设置一个集群中至少有多少个node
gateway.expected_nodes: 3
# 设置等待node的时间
gateway.recover_after_time: 5m

日志配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 配置了appender类型RollingFile
appender.rolling.type = RollingFile
appender.rolling.name = rolling
# 配置日志路径
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
# 配置基于时间的roll策略
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n
# 配置将日志每天写一份到/var/log/elasticsearch/production-2017-01-01.log文件中
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}.log
appender.rolling.policies.type = Policies
# 配置基于时间的roll策略
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
# 设置每天一份日志文件
appender.rolling.policies.time.interval = 1
# 设置根据自然天来划分文件,而不是24小时
appender.rolling.policies.time.modulate = true

日志配置

es使用log4j2来记录日志,log4j2可以通过log4j2.properties文件来进行配置

1
2
3
4
5
6
7
appender.rolling.strategy.type = DefaultRolloverStrategy 
appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
appender.rolling.strategy.action.condition.type = IfLastModified
appender.rolling.strategy.action.condition.age = 7D
appender.rolling.strategy.action.PathConditions.type = IfFileName
appender.rolling.strategy.action.PathConditions.glob = ${sys:es.logs.cluster_name}-*

禁止swapping

1
2
3
4
5
6
7
8
9
10
11
[root@elasticsearch01 ~]# vi /etc/fstab
#
# /etc/fstab
# Created by anaconda on Mon Jul 17 23:05:14 2017
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/cl-root / xfs defaults 0 0
UUID=bf320a34-67d2-4125-ba31-e3a76bac0480 /boot xfs defaults 0 0
# /dev/mapper/cl-swap swap swap defaults 0 0

指定一个新的临时目录

1
2
[root@elasticsearch01 ~]# mkdir -p /usr/local/tmp
[root@elasticsearch01 ~]# cd /etc/elasticsearch/
1
2
[root@elasticsearch01 elasticsearch]# vi jvm.options
-Djava.io.tmpdir=/usr/local/tmp

虚拟内存设置

es使用hybrid mmapfs / niofs目录来存储index数据,操作系统的默认mmap count限制是很低的,可能会导致内存耗尽的异常。

需要提升mmap count的限制:

1
sysctl -w vm.max_map_count=262144

如果要永久性设置这个值,要修改/etc/sysctl.conf,将vm.max_map_count的值修改一下,重启过后,用sysctl vm.max_map_count来验证一下数值是否修改成功

es同时会用NioFS和MMapFS来处理不同的文件,我们需要设置最大的map刷另,这样我们才能有足够的虚拟内存来给mmapped文件使用,可以用sysctl来设置:sysctl -w vm.max_map_count=262144。还可以再/etc/sysctl.conf中,对vm.max_map_count来设置

1
2
[root@elasticsearch01 ~]# sysctl -w vm.max_map_count=262144
vm.max_map_count = 262144
1
2
3
4
[root@elasticsearch01 ~]# vi /etc/sysctl.conf
vm.max_map_count=262144
# 配置swappiness
vm.swappiness=1

设置线程的数量,设置es用户能创建的最大线程数量至少在2048

1
2
3
4
5
6
7
es用了很多线程池来应对不同类型的操作
在需要的时候创建新的线程是很重要的
要确保es用户能创建的最大线程数量至少在2048以上。

可以通过ulimit -u 2048来临时设置
也可以在/etc/security/limits.conf中
设置nproc为2048来永久性设置。

配置/etc/security/limits.conf文件

1
2
3
4
5
6
7
8
[root@elasticsearch01 ~]# vi /etc/security/limits.conf
# 启动es进程的用户没有权限去lock memory,需要通过以下方式进行授权
elasticsearch hard memlock unlimited
elasticsearch soft memlock unlimited
# 设置线程的数量,设置es用户能创建的最大线程数量至少在2048
elasticsearch hard nproc 2048
elasticsearch hard nofile 65536
elasticsearch hard as unlimited

将ES配置文件发送到另外三台机器上

1
2
[root@elasticsearch01 ~]# scp -r /usr/local/elasticsearch/ root@elasticsearch02:/usr/local/elasticsearch/
[root@elasticsearch01 ~]# scp -r /usr/local/elasticsearch/ root@elasticsearch03:/usr/local/elasticsearch/
1
2
[root@elasticsearch01 ~]# scp -r /etc/security/limits.conf root@elasticsearch02:/etc/security/limits.conf
[root@elasticsearch01 ~]# scp -r /etc/security/limits.conf root@elasticsearch03:/etc/security/limits.conf
1
2
[root@elasticsearch01 ~]# scp -r /etc/elasticsearch/ root@elasticsearch02:/etc/
[root@elasticsearch01 ~]# scp -r /etc/elasticsearch/ root@elasticsearch03:/etc/

修改其余机器上ES配置文件中的节点名称、非回环地址

1
2
3
4
5
6
[root@elasticsearch02 ~]# cd /etc/elasticsearch/
[root@elasticsearch02 config]# vi elasticsearch.yml
# 节点名称
node.name: node-elasticsearch-02
# 配置主机上的非回环地址
network.host: 192.168.31.181
1
2
3
4
5
6
[root@elasticsearch03 ~]# cd /etc/elasticsearch/
[root@elasticsearch03 config]# vi elasticsearch.yml
# 节点名称
node.name: node-elasticsearch-03
# 配置主机上的非回环地址
network.host: 192.168.31.182

设置ES环境变量

1
2
3
4
[root@elasticsearch01 ~]# vi .bashrc
export ES_HOME=/usr/local/elasticsearch/
export PATH=$PATH:$ES_HOME/bin
[root@elasticsearch01 ~]# source .bashrc

切换到elasticsearch用户来启动es进程

1
su elasticsearch
1
2
cd /usr/local/elasticsearch/bin
elasticsearch -d -Epath.conf=/etc/elasticsearch

或者

1
2
3
[elasticsearch@elasticsearch01 ~]$ elasticsearch -d -Epath.conf=/etc/elasticsearch
[elasticsearch@elasticsearch02 ~]$ elasticsearch -d -Epath.conf=/etc/elasticsearch
[elasticsearch@elasticsearch03 ~]$ elasticsearch -d -Epath.conf=/etc/elasticsearch

查看elasticsearch日志

1
2
3
4
5
6
[elasticsearch@elasticsearch01 ~]$ ll /var/log/elasticsearch/
总用量 32
-rw-rw-r--. 1 elasticsearch elasticsearch 0 10月 15 23:10 cluster-elasticsearch-prod_deprecation.log
-rw-rw-r--. 1 elasticsearch elasticsearch 0 10月 15 23:10 cluster-elasticsearch-prod_index_indexing_slowlog.log
-rw-rw-r--. 1 elasticsearch elasticsearch 0 10月 15 23:10 cluster-elasticsearch-prod_index_search_slowlog.log
-rw-rw-r--. 1 elasticsearch elasticsearch 31979 10月 15 23:42 cluster-elasticsearch-prod.log

查看ES集群是否启动成功

在浏览器地址栏访问:http://192.168.31.180:9200/

All text

在浏览器地址栏访问:http://192.168.31.181:9200/

All text

在浏览器地址栏访问:http://192.168.31.182:9200/

All text

访问es

一般建议在管理机上安装一个curl工具,可以手工发送rest api请求

可以对启动了es的节点的9200端口,发送一个GET /请求,可以看看es是否启动成功

1
curl -XGET elasticsearch03:9200

All text

1
curl -XGET elasticsearch01:9200/_cat/nodes?v

All text

停止es

优雅的关闭es,可以确保es关闭的很干净,并且优雅关闭资源。
举例来说,如果node在一个合理的顺序下关闭了,首先会将自己从cluster中优雅移除,fsync translog日志到磁盘中去,然后执行其他相关的cleanup活动。

如果我们将es用service的方式来运行,那么可以通过server管理功能来停止es。

如果我们是直接启动es的,可以control-C停止es,或者是发送SEGTERM信号给es进程

1
2
3
[elasticsearch@elasticsearch01 elasticsearch]$ jps | grep Elasticsearch
3661 Elasticsearch
[elasticsearch@elasticsearch01 elasticsearch]$ kill -SIGTERM 3661

All text

如果es发生了fatal error,类似out of memory error,代码bug,或者io error,等等

当es发现jvm有一个fatal error,就会尝试记录在log里面,然后尝试去停止jvm。此时es是不会按照优雅关闭的模式去执行的,而是会直接关闭,并且返回一个错误码

JVM internal error 128
Out of memory error 127
Stack overflow error 126
Unknown virtual machine error 125
Serious I/O error 124
Unknown fatal error 1

本文作者 : Matrix
原文链接 : https://matrixsparse.github.io/2017/07/24/ElasticSearch集群部署/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

知识 & 情怀 | 二者兼得

微信扫一扫, 向我投食

微信扫一扫, 向我投食

支付宝扫一扫, 向我投食

支付宝扫一扫, 向我投食

留下足迹