Elasticsearch 配置详解

ES在默认的配置下就能很好的工作, 只需要很少的配置, 并且大部分的配置都可以在运行的集群上动态设置,
使用使用集群更新API

配置文件应该包含两部分: node本身的设置(例如node.name 以及 paths) 以及 集群的设置(例如cluster.name 以及 network.host)。

配置文件的位置

ES有两个配置文件:

  1. elasticsearch.yml 用来配置ES本身
  2. log4j2.properties 用来配置ES的日志

这两个文件位于config文件夹下, 默认在$ES_HOME/config/. Debian 和 RPM包安装的话, 配置目录位于 /etc/elasticsearch.

配置目录可以在运行的时候通过path.conf 设置更改:

./bin/elasticsearch -Epath.conf=/path/to/my/config/

配置文件格式

配置文件格式为YAML. 下面以一个例子来展示修改数据和日志的路径:

path:
    data: /var/lib/elasticsearch
    logs: /var/log/elasticsearch

也可以用下面扁平化的配置:

path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

环境变量替换

在配置文件里面使用${...} 来引用环境变量, 例如:

node.name:    ${HOSTNAME}
network.host: ${ES_NETWORK_HOST}

提示设置

提示设置, 叫做启动的时候设置 可能更准确一些。对于不想存储在配置文件中的配置, 你可以使用${prompt.text}或者${prompt.secret} 并且前台启动ES。
${prompt.secret}不会再终端上显示你输入的内容, 而${prompt.text} 则会把你的输入显示在终端上面。 例如:

node:
  name: ${prompt.text}

然后在启动ES的时候, ES会提示你输入真实的值:

Enter value for [node.name]:

如果ES是后台启动的,但是配置文件中使用了${prompt.text}${prompt.secret}, ES将不会启动。

设置默认设置

新的默认值可以在命令行通过default.前缀设置。 这个指定的值会被用作默认值, 除非配置文件中配置了。 例如:

./bin/elasticsearch -Edefault.node.name=My_Node

node.name 的值就是 My_Node, 除非在命令行中使用es.node.name 或者 配置文件中使用node.name 覆盖了此值。

日志配置

ES使用Log4j2 记录日志。 Log4j2可以通过log4j2.properties来配置。 ES在配置文件中暴露了一个属性${sys:es.logs}
可以用来指定ES的日志, 这个值在运行的时候将被解析为日志文件的前缀。

例如, 如果你的日志目录path.logs/var/log/elasticsearch并且你的集群名是production 那么${sys:es.logs}
将被解析为/var/log/elasticsearch/production.

appender.rolling.type = RollingFile
appender.rolling.name = rolling
# /var/log/elasticsearch/production.log
appender.rolling.fileName = ${sys:es.logs}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n
# /var/log/elasticsearch/production-yyyy-MM-dd.log
appender.rolling.filePattern = ${sys:es.logs}-%d{yyyy-MM-dd}.log
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1
appender.rolling.policies.time.modulate = true

如果你在appender.rolling.filePattern的值上添加.gz或者.zip, 日志在滚动的时候会被按照格式压缩。

日志文件可以有多个(加载的时候会被合并)。 只要他们名字为log4j2.properties 并且在ES的config目录的子孙目录下面即可,
这对于一些插件暴露的其他logger很有用。logger节点包含了java的包以及对应的日志级别。 appender节点包含了日志的输出目标,
其他关于如何配置logging以及支持的appender可以参考log4j文档.

废弃日志

除了常规的日志, ES还允许指定废弃日志的行为(即用于告诉你哪一项特性将在未来版本中被废弃)。
这个特性可以用于提前确定未来是否需要迁移某些功能。默认情况下废弃日志级别为WARN,

logger.deprecation.level = warn

这个配置将会在日志目录里创建一个废弃日志文件。 你需要经常检查此文件,尤其当你想升级一个新的主版本的时候。

默认的日志滚动策略是在1GB后压缩, 并且保持5份之日冗余(4份归档后的, 1份当前正在用的)。

可以通过将config/log4j2.properties配置废弃日志级别为ERROR.

ES重要配置

尽管ES只需要很少的配置, 但是将ES投入到生产环境之前还是需要人工手动的配置很多属性。主要有:

  1. path.data 以及 path.logs
  2. cluster.name
  3. node.name
  4. bootstrap.memory_lock
  5. network.host
  6. discovery.zen.ping.unicast.hosts
  7. discovery.zen.minimum_master_nodes

path.datapath.logs

如果你使用的.zip 或者 .tar.gz 压缩包, data 以及 logs 目录是$ES_HOME的一个子目录。 如果这些重要的目录
就在默认的位置,当你升级ES版本时很容易把他们删除掉。 所以在生产环境中, 你应该修改这两个目录到其他位置:

path:
  logs: /var/log/elasticsearch
  data: /var/data/elasticsearch

RPM 以及 Debian 包已经为datalogs 使用了自定义路径。

path.data 可以配置为使用多个路径, 这种情况下所有的路径都会用于存储数据(同一个分片的文件会在同一个目录下):

path:
  data:
    - /mnt/elasticsearch_1
    - /mnt/elasticsearch_2
    - /mnt/elasticsearch_3

cluster.name

一个节点只有设置自己的cluster.name与其他节点相同才能加入一个集群。 默认的集群名是elasticsearch, 但是你应该将此值修改为
描述集群目的的值:

cluster.name: logging-prod

注意集群名没有与其他集群冲突, 否则你可能会加入到错误的集群。

node.name

默认情况下, ES使用随机生成的UUID的前7位作为节点id。 注意节点id会持久化, 节点重启的时候不会改变, 因此默认的节点名也不会改变。
所以最好为node.name设置一个更有意义的名字。

node.name: prod-data-2

node.name 也可以设置为服务器的hostname:

node.name: ${HOSTNAME}

bootstrap.memory_lock

对于一个节点的健康状态来说,让jvm的内存不被写到磁盘是极其重要的。 达到这个目的的方式之一就是设置bootstrap.memory_locktrue.

为了使此设置生效, 需要先配置一些其他系统设置。 详情参考
启用bootstrap.memory_lock.

network.host

默认情况下, ES仅仅绑定在本地的回环地址(loopback address) - 例如 127.0.0.1 以及 ::1. 如果在服务器上运行一个开发节点已经足够了。

TIP: 事实上,在同一个服务器节点上的相同的$ES_HOME可以启动多个节点。 这个特性可以用来测试ES的集群能力, 但是不推荐用在生产环境。

为了与其他服务器上的节点形成集群通讯, 需要把你的节点上ES绑定到其他非回环地址上。 尽管有很多网络设置
, 但是通常情况下你只需要配置network.host:

network.host: 192.168.1.10

network.host 配置项还能理解一些其他的特殊值, 比如_local_,_site_,_global_ 以及其他修饰词例如:ipv4:ipv6, 更多特殊值可以参考这里
network.host的特殊值.

Important: 一旦你提供了network.host的自定义配置, ES就认为你正在讲开发节点升级为生产环境节点, 然后将一系列系统启动时候的检查由警告升级为异常。
可以看这一章开发模式 VS 生产模式了解更多信息。

discovery.zen.ping.unicast.hosts

ES提供了开箱即用的功能, 在不设置任何网络配置的情况下, ES将绑定在本机可用的回环地址然后扫描本机的9300 - 9305 端口来尝试连接同样运行在本机上的其他ES实例。
这就提供了在不需要任何配置的自动集群的功能。

然而在需要与其他服务器上面的ES实例进行集群的时候, 你需要提供一个种子列表, 这些种子是在集群中的活跃并且可以连接的节点实例。可以如下设置:

discovery.zen.ping.unicast.hosts:
   - 192.168.1.10:9300
   - 192.168.1.11
   - seeds.mydomain.com

上面如果不填端口, 则默认是transport.profiles.default.porttransport.tcp.port

如果主机名可以被解析为多个ip, 那么每个ip都会被尝试连接。

discovery.zen.minimum_master_nodes

为了防止数据丢失, 生产环境下非常有必要配置discovery.zen.minimum_master_nodes, 告诉ES集群至少有几个master节点可用才能形成集群。

如果没有配置此项, 那么在网络不好的情况下, 集群就存在脑裂的风险 - 一个集群可能会分成两个独立的集群, 这就导致了数据丢失。 更详细的解决方案请参考
使用minimum_master_nodes避免脑裂

为了避免脑裂问题, 这个值应该按照如下规则设置:

(master_eligible_nodes / 2) + 1

即如果集群种有三个master节点, 那么那么最小master节点应该设置为(3 / 2) + 1 = 2:

discovery.zen.minimum_master_nodes: 2

系统重要配置

理想情况下, ES应该单独运行在一台服务器上面, 尽可能的充分利用服务器上面的资源。 但是默认情况下ES能使用资源有限, 的所以我们需要一些系统级别的配置来使ES
突破默认限制。

在上生产环境之前, 必须配置以下项目:

  1. 设置jvm堆大小
  2. 禁用交换内存
  3. 增加文件描述符
  4. 保证足够的虚拟内存
  5. 保证足够的线程

开发模式 VS 生产模式

默认情况下, ES认为工作在开发模式下。 如果上面的任何一项没有配置好, 那么ES会将日志以WARN级别记录在日志文件。 但是ES实例是可以启动的。

一旦你配置了网络设置, 例如network.host, ES就会认为工作在了生产模式下, 会将上述的WARN日志升级为异常。 抛出异常ES的实例就无法启动。
这是一个很重要的安全措施, 保证在错误的配置下不会丢失数据。

配置操作系统设置

如何配置操作系统设置取决于你的ES是用什么方式安装的以及你的操作系统版本。

当使用.zip 以及 .tar.gz 的时候, 系统设置可以在下面的位置配置:

  1. 临时的ulimit.
  2. 永久的/etc/security/limits.conf.

如果使用的RPM或者Debian安装包,
大部分的系统设置位于下面说的sysconfig文件中
, 不过如果使用的systemd来管理服务的, 需要在下面说的sysconfig 文件里面配置。

ulimit

在linux系统, ulimit 命令可以临时修改资源限制。 通常需要先切换到root用户配置好这些限制, 然后切换到elasticsearch用户启动ES。 例如
要设置打开文件的句柄数(ulimit -n)为65536, 你可以这么做:

//切换为root
sudo su
// 修改句柄数量
ulimit -n 65536
// 切换回elasticsearch用户
su elasticsearch

这个配置只对当前的会话有效。 可以使用 ulimit -a 查看当前的所有限制。

/etc/security/limits.conf

在Linux系统, 可以编辑/etc/security/limits.conf持久化对每个用户的限制。 例如将elasticsearch用户最大打开的文件句柄数修改为65536, 只需要在
limits.conf 文件加一行:

elasticsearch  -  nofile  65536

这个修改在elasticsearch用户打开一个新的会话的时候生效。

NOTE. Ubuntu与limits.conf, 对于通过init.d启动起来的进程, ubuntu系统会忽略limits.conf. 如果要启用这个文件,
需要打开/etc/pam.d/su 然后将下面一行取消注释:

# session    required   pam_limits.so

sysconfig 文件

当使用RPM以及Debian包的时候, 系统设置以及环境设置可以在下面的文件中配置:

  1. /etc/sysconfig/elasticsearch RPM
  2. /etc/default/elasticsearch Debian

但是由systemd管理的服务, 需要通过systemd来配置。

systemd 配置

systemd的服务描述文件(/usr/lib/systemd/system/elasticsearch.service)包含了默认情况下的限制。

可以通过添加一个文件/etc/systemd/system/elasticsearch.service.d/elasticsearch.conf来重写这些配置, 例如:

[Service]
LimitMEMLOCK=infinity

设置JVM参数

设置JVM参数比较推荐的方式是修改jvm.options文件。 此文件的默认位置位于config/jvm.options(.zip或者tar安装的)
或者/etc/elasticsearch/jvm.options(RPM或者Debian安装的)。 这个文件包含了以行为分隔符的jvm配置,每行都要以-开头。
你可以自定义JVM参数, 并且将此文件放在版本管理系统中(git/svn)。

另外一种设置JVM参数的方式就是通过环境变量ES_JAVA_OPTS来设置:

export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djava.io.tmpdir=/path/to/temp/dir"
./bin/elasticsearch

当使用RPM或者Debian的时候, ES_JAVA_OPTS可以通过上面说的方式设置。

continue: https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html

Q.E.D.