理想情况下,Elasticsearch 应该在服务器上单独运行并使用所有可用资源。为此,需要将操作系统配置为允许运行 Elasticsearch 的用户访问比默认允许更多的资源。
在投入生产之前,必须考虑以下设置:
开发模式 vs 生产模式
默认情况下,Elasticsearch 假定在开发模式下工作。如果上述任何设置未正确配置,则会在日志文件中写入警告,但能够启动和运行 Elasticsearch 节点。
一旦配置了类似network.host
的网络设置,Elasticsearch 就会假定正在进入生产环境,并将上述警告升级为异常。这些异常将阻止 Elasticsearch 节点启动。这是一项重要的安全措施,可确保不会因为服务器配置错误而丢失数据。
配置系统设置
在哪里配置系统设置取决于安装的 Elasticsearch 软件包以及使用的操作系统。
使用.zip
或.tar.gz
包时,可进行如下配置系统设置:
- 使用
ulimit
进行临时配置 - 在
/etc/security/limits.conf
.中永久配置
使用 RPM 或 Debian 软件包时,大多数系统设置都在系统配置文件中设置 。但是,使用 systemd 的系统要求在systemd 配置文件中指定系统限制 。
ulimit
在 Linux 系统上,ulimit
可用于临时更改资源限制。通常需要在切换到运行 Elasticsearch 的用户之前,使用root
设置限制。例如,要将打开的文件句柄数 ( ulimit -n
) 设置为 65,536,可以执行以下操作:
sudo su
ulimit -n 65535
su elasticsearch
第一行切换到root用户
第二行修改最大打开文件数
第三行切换到elasticsearch用户,然后启动elasticsearch
新限制仅在当前会话期间应用。
可以使用ulimit -a
查阅所有当前应用的限制。
/etc/security/limits.conf
在 Linux 系统上,可以通过编辑/etc/security/limits.conf
文件为特定用户设置永久限制。要将elasticsearch
用户的最大打开文件数设置为 65,535,将以下行添加到limits.conf
文件中:
elasticsearch - nofile 65535
此更改只会在elasticsearch
用户下次打开新会话时生效。
NOTE
Ubuntu 和
limits.conf
Ubuntu 对由
init.d
启动进程忽略limits.conf
. 要启用limits.conf
文件,需编辑/etc/pam.d/su
并取消注释以下行:# session required pam_limits.so
系统配置文件
使用 RPM 或 Debian 软件包时,可以在系统配置文件中指定系统设置和环境变量,该文件位于:
RPM:/etc/sysconfig/elasticsearch
Debian:/etc/default/elasticsearch
但是,对于使用systemd
的系统,需要通过systemd指定系统限制。
系统配置
在使用systemd 的系统上使用 RPM 或 Debian 软件包时 ,必须通过 systemd 指定系统限制。
systemd 服务文件 ( /usr/lib/systemd/system/elasticsearch.service
) 包含默认应用的限制。
要覆盖它们,请添加一个名为/etc/systemd/system/elasticsearch.service.d/override.conf
(或者,可以运行sudo systemctl edit elasticsearch
在默认编辑器中自动打开文件)的文件 。设置此文件中的任何更改,例如:
[Service]
LimitMEMLOCK=infinity
完成后,运行以下命令以重新加载单位:
sudo systemctl daemon-reload
禁用swapping
大多数操作系统尝试将尽可能多的内存用于文件系统缓存,及时地换出未使用的应用程序内存。这可能会导致部分 JVM 堆甚至其可执行页面被swap到磁盘。
swap对性能和节点稳定性非常不利,应该不惜一切代价避免。它可能导致垃圾收集持续几分钟而不是几毫秒,并可能导致节点响应缓慢甚至与集群断开连接。在弹性分布式系统中,让操作系统杀死节点更有效。
有三种方法可以禁用交换。首选选项是完全禁用交换。此外最小化交换与内存锁定,如何选择取决于具体的环境。
禁用所有交换文件
通常 Elasticsearch 是唯一运行在机器上的服务,它的内存使用由 JVM 选项控制,不需要启用swap。
在 Linux 系统上,可以通过运行以下命令暂时禁用swap:
sudo swapoff -a
这不需要重新启动 Elasticsearch。
要永久禁用它,需要编辑/etc/fstab
文件并注释掉包含swap
单词的行.
在 Windows 上,可以通过完全禁用分页文件来实现,System Properties → Advanced → Performance → Advanced → Virtual memory
.
配置 swappiness
Linux 系统上另一个可用的方案是将 sysctl 值 vm.swappiness
设置为1
。这减少了内核swap的权重,并且在正常情况下不应该导致swap,同时仍然允许整个系统在紧急情况下swap。
开启 bootstrap.memory_lock
另一种选择是在 Linux/Unix 系统上使用mlockall,或 在 Windows上 使用 VirtualLock,尝试将进程地址空间锁定到 RAM 中,防止任何 Elasticsearch 内存被换出。这可以通过将这一行添加到config/elasticsearch.yml
文件中来完成:
bootstrap.memory_lock: true
警告
mlockall
如果 JVM 或 shell 会话尝试分配的内存多于可用内存,则可能会导致它退出!
启动 Elasticsearch 后,可以通过检查mlockall
此请求的输出中的值来查看此设置是否成功应用:
GET _nodes?filter_path=**.mlockall
如果看到的mlockall
是false
,则表示mlockall
请求失败。日志中会有一行包含更多信息的日志Unable to lock JVM Memory
。
在 Linux/Unix 系统上,最可能的原因是运行 Elasticsearch 的用户没有锁定内存的权限。这可以作如下授权:
.zip
和 .tar.gz
在启动 Elasticsearch 之前, 用root设置为ulimit -l unlimited
,或在 /etc/security/limits.conf
中设置memlock
为unlimited
。
RPM 和 Debian
在 系统配置文件中 设置MAX_LOCKED_MEMORY
为unlimited
(或参见下面的系统使用systemd
)。
系统使用 systemd
在systemd 配置中 设置LimitMEMLOCK
为infinity
。
另一个可能mlockall
失败的原因是 JNA 临时目录(通常是 /tmp
的子目录 )使用了noexec
选项挂载。这可以通过使用ES_JAVA_OPTS
环境变量为 JNA 指定一个新的临时目录来解决:
export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djna.tmpdir=<path>"
./bin/elasticsearch
或者在 jvm.options 配置文件中设置这个 JVM 标志。
文件描述符
NOTE
这仅与 Linux 和 macOS 相关,如果在 Windows 上运行 Elasticsearch,则可以安全地忽略它。在 Windows 上,JVM 使用API仅受可用资源限制的 。
Elasticsearch 使用了很多文件描述符或文件句柄。耗尽文件描述符可能是灾难性的,并且很可能会导致数据丢失。需确保运行 Elasticsearch 的用户的打开文件描述符数量限制增加到 65,536 或更高。
对于.zip
和.tar.gz
包,在启动 Elasticsearch 之前使用root设置为 ulimit -n 65535
,或者在 /etc/security/limits.conf
中设置nofile
为65535
。
在 macOS 上,还必须将 JVM 选项-XX:-MaxFDLimit
传递给 Elasticsearch,以便它使用更高的文件描述符限制。
RPM 和 Debian 软件包已将文件描述符的最大数量默认为 65535,不需要进一步配置。
可以使用Nodes stats API检查每个节点配置的max_file_descriptors
,如下:
GET _nodes/stats/process?filter_path=**.max_file_descriptors
虚拟内存
Elasticsearch默认使用目录mmapfs来存储它的索引。操作系统对 mmap 计数的默认限制可能太低,这可能会导致内存不足异常。
在 Linux 上,可以通过root
运行以下命令来增加限制 :
sysctl -w vm.max_map_count=262144
要永久设置此值,请更新/etc/sysctl.conf
中的vm.max_map_count
设置 。运行sysctl vm.max_map_count,
可在重新启动后进行验证.
RPM 和 Debian 软件包将自动配置此设置。无需进一步配置。
线程数
Elasticsearch 使用多个线程池来进行不同类型的操作。重要的是它能够在需要时创建新线程。确保 Elasticsearch 用户可以创建的线程数至少为 4096。
在启动 Elasticsearch 之前通过root设置ulimit -u 4096
来完成,或者在/etc/security/limits.conf
中设置nproc
为4096
。
作为基于systemd
的服务运行时的包会自动配置 Elasticsearch 进程的线程数。不需要额外的配置。
DNS 缓存设置
Elasticsearch 运行时有一个安全管理器。有了安全管理器,JVM 默认会无限期缓存正主机名解析,默认缓存负主机名解析 10 秒。Elasticsearch 使用默认值覆盖此行为,将正查找缓存 60 秒,并将负查找缓存 10 秒。这些值应该适用于大多数环境,包括 DNS 解析随时间变化的环境。如果没有,可以在JVM选项中编辑值es.networkaddress.cache.ttl和
es.networkaddress.cache.negative.ttl
。需要注意的是在 Java安全策略中 networkaddress.cache.ttl=<timeout>
和 networkaddress.cache.negative.ttl=<timeout>
的值会被Elasticsearch忽略,除非你删除 es.networkaddress.cache.ttl
和es.networkaddress.cache.negative.ttl
配置。
JNA 临时目录未挂载noexec
NOTE
这仅与 Linux 相关。
Elasticsearch 使用 Java Native Access (JNA) 库来执行一些与平台相关的本机代码。在 Linux 上,支持此库的本机代码在运行时从 JNA 存档中提取。默认情况下,此代码被提取到 Elasticsearch 临时目录,该目录默认为 /tmp
的子目录。或者,可以使用 JVM 标志-Djna.tmpdir=<path>
来控制此位置 。由于本机库作为可执行文件映射到 JVM 虚拟地址空间中,因此不得使用此代码提取到的位置的底层挂载点进行noexec
挂载,因为这会阻止 JVM 进程将此代码映射为可执行文件。在某些强化的 Linux 安装中,/tmp
是默认挂载选项。底层挂载被noexec
挂载的一个迹象是,在启动时 JNA 将无法加载,会出现一条异常java.lang.UnsatisfiedLinkerError
并包含消息failed to map segment from shared object
。请注意,异常消息可能因 JVM 版本而异。此外,依赖于通过 JNA 执行本机代码的 Elasticsearch 组件将失败并显示消息,表明它是because JNA is not available
. 如果看到此类错误消息,必须重新以非noexec
的方式挂载用于 JNA 的临时目录。