引导检查

edit

总的来说,我们有很多用户因为未配置重要设置而遇到意外问题的经验。在之前的Elasticsearch版本中,这些设置的错误配置会被记录为警告。可以理解的是,用户有时会忽略这些日志消息。为了确保这些设置得到应有的关注,Elasticsearch在启动时会进行引导检查。

这些引导检查会检查各种Elasticsearch和系统设置,并将它们与安全运行Elasticsearch的值进行比较。如果Elasticsearch处于开发模式,任何失败的引导检查都会在Elasticsearch日志中显示为警告。如果Elasticsearch处于生产模式,任何失败的引导检查都会导致Elasticsearch拒绝启动。

有一些引导检查总是被强制执行,以防止Elasticsearch在设置不兼容的情况下运行。这些检查都有单独的文档说明。

开发模式 vs. 生产模式

edit

默认情况下,Elasticsearch 绑定到环回地址以进行 HTTP 和传输(内部)通信。这对于下载和试用 Elasticsearch 以及日常开发来说是可以的, 但对于生产系统来说是无用的。要加入集群,Elasticsearch 节点必须可以通过传输通信访问。要通过非环回地址加入集群,节点必须将传输绑定到非环回地址, 并且不使用 单节点发现。因此,如果 Elasticsearch 节点无法通过非环回地址与另一台机器形成集群, 我们认为它处于开发模式,否则如果它可以通过非环回地址加入集群,则处于生产模式。

请注意,HTTP和传输可以通过http.hosttransport.host独立配置;这对于配置单个节点以便通过HTTP进行测试目的而不会触发生产模式非常有用。

单节点发现

edit

我们认识到一些用户需要将传输绑定到外部接口以测试远程集群配置。为此情况,我们提供了发现类型 single-node(通过将 discovery.type 设置为 single-node 来配置);在这种情况下,节点将选举自己为主节点,并且不会与其他任何节点加入集群。

强制引导检查

edit

如果你在生产环境中运行单个节点,可以通过不将传输绑定到外部接口,或者将传输绑定到外部接口并设置发现类型为single-node来规避引导检查。在这种情况下,你可以通过在JVM选项中将系统属性es.enforce.bootstrap.checks设置为true来强制执行引导检查。如果你处于这种特定情况,我们强烈建议你这样做。此系统属性可用于强制执行引导检查,而不依赖于节点配置。

堆大小检查

edit

默认情况下,Elasticsearch 会根据节点的 角色和总内存自动调整 JVM 堆大小。如果您手动覆盖默认设置并以不同的初始和最大堆大小启动 JVM,JVM 可能会在系统使用期间调整堆大小时暂停。如果您启用了 bootstrap.memory_lock,JVM 会在启动时锁定初始堆大小。如果初始堆大小不等于最大堆大小,则在调整大小后,某些 JVM 堆可能不会被锁定。为了避免这些问题,请以初始堆大小等于最大堆大小的方式启动 JVM。

文件描述符检查

edit

文件描述符是Unix系统中用于跟踪打开的“文件”的构造。在Unix中,一切都是文件。例如,“文件”可以是物理文件、虚拟文件(例如,/proc/loadavg)或网络套接字。Elasticsearch需要大量的文件描述符(例如,每个分片由多个段和其他文件组成,加上与其他节点的连接等)。此引导检查在OS X和Linux上强制执行。要通过文件描述符检查,您可能需要配置文件描述符

内存锁定检查

edit

当JVM进行一次主要的垃圾回收时,它会触及堆的每一页。如果这些页面中的任何一个被交换到磁盘上,它们将不得不被交换回内存中。这会导致大量的磁盘抖动,而Elasticsearch更愿意用这些资源来服务请求。有几种方法可以配置系统以禁止交换。一种方法是通过mlockall(Unix)或虚拟锁(Windows)请求JVM将堆锁定在内存中。这是通过Elasticsearch设置bootstrap.memory_lock完成的。然而,在某些情况下,这个设置可以传递给Elasticsearch,但Elasticsearch无法锁定堆(例如,如果elasticsearch用户没有memlock unlimited权限)。内存锁检查验证了如果启用了bootstrap.memory_lock设置,JVM是否能够成功锁定堆。要通过内存锁检查,您可能需要配置bootstrap.memory_lock

最大线程数检查

edit

Elasticsearch 通过将请求分解为多个阶段并将其交给不同的线程池执行器来执行请求。Elasticsearch 中有不同的 线程池执行器 用于各种任务。因此,Elasticsearch 需要能够创建大量线程。最大线程数检查确保 Elasticsearch 进程在正常使用下有权创建足够的线程。此检查仅在 Linux 上强制执行。如果你在 Linux 上,要通过最大线程数检查,你必须配置系统以允许 Elasticsearch 进程至少创建 4096 个线程。这可以通过 /etc/security/limits.conf 使用 nproc 设置来完成(注意你可能还需要增加 root 用户的限制)。

最大文件大小检查

edit

作为单个分片组件的段文件和作为事务日志组件的事务日志生成可能会变得很大(超过多个千兆字节)。在Elasticsearch进程创建的文件的最大大小受限的系统上,这可能导致写入失败。因此,最安全的选项是最大文件大小不受限制,这也是最大文件大小引导检查所强制执行的。要通过最大文件检查,您必须配置系统以允许Elasticsearch进程能够写入无限大小的文件。这可以通过使用fsize设置为unlimited/etc/security/limits.conf来完成(请注意,您可能还需要增加root用户的限制)。

最大虚拟内存检查

edit

Elasticsearch 和 Lucene 使用 mmap 非常有效地将索引的部分映射到 Elasticsearch 地址空间中。这使得某些索引数据不在 JVM 堆上,但在内存中以实现极快的访问。为了有效,Elasticsearch 应具有无限的地址空间。最大虚拟内存大小检查强制 Elasticsearch 进程具有无限的地址空间,并且仅在 Linux 上执行。要通过最大虚拟内存大小检查,您必须配置系统以允许 Elasticsearch 进程具有无限的地址空间。这可以通过将 - as unlimited 添加到 /etc/security/limits.conf 来完成。这可能还需要您增加 root 用户的限制。

最大映射计数检查

edit

从上一个继续,为了有效使用mmap,Elasticsearch还需要能够创建许多内存映射区域。最大映射计数检查确保内核允许一个进程至少拥有262,144个内存映射区域,并且仅在Linux上强制执行。要通过最大映射计数检查,您必须通过sysctlvm.max_map_count配置为至少262144

或者,仅当您将索引的存储类型设置为mmapfshybridfs时,才需要进行最大映射计数检查。如果您不允许使用mmap,则不会强制执行此引导检查。

客户端 JVM 检查

edit

OpenJDK派生的JVM提供了两种不同的JVM:客户端JVM和服务器JVM。这些JVM使用不同的编译器从Java字节码生成可执行的机器代码。客户端JVM针对启动时间和内存占用进行了优化,而服务器JVM则针对最大化性能进行了优化。这两种虚拟机之间的性能差异可能很大。客户端JVM检查确保Elasticsearch不在客户端JVM中运行。要通过客户端JVM检查,您必须使用服务器虚拟机启动Elasticsearch。在现代系统和操作系统上,服务器虚拟机是默认的。

使用串行收集器检查

edit

OpenJDK派生的JVM有多种垃圾收集器,适用于不同的工作负载。特别是串行收集器最适合单逻辑CPU机器或极小的堆,这两者都不适合运行Elasticsearch。在Elasticsearch中使用串行收集器可能会对性能造成灾难性的影响。串行收集器检查确保Elasticsearch未配置为使用串行收集器运行。要通过串行收集器检查,您不得使用串行收集器启动Elasticsearch(无论是来自您使用的JVM的默认设置,还是您已明确使用-XX:+UseSerialGC指定)。请注意,Elasticsearch附带的默认JVM配置在JDK14及更高版本中配置Elasticsearch使用G1GC垃圾收集器。对于较早的JDK版本,配置默认使用CMS收集器。

系统调用过滤器检查

edit

Elasticsearch 根据操作系统安装不同类型的系统调用过滤器(例如,Linux 上的 seccomp)。这些系统调用过滤器被安装以防止执行与分叉相关的系统调用,作为防御 Elasticsearch 上任意代码执行攻击的机制。系统调用过滤器检查确保如果启用了系统调用过滤器,那么它们已成功安装。要通过系统调用过滤器检查,您必须修复系统上阻止系统调用过滤器安装的任何配置错误(检查您的日志)。

OnError 和 OnOutOfMemoryError 检查

edit

JVM 选项 OnErrorOnOutOfMemoryError 允许在 JVM 遇到致命错误(OnError)或 OutOfMemoryErrorOnOutOfMemoryError)时执行任意命令。然而,默认情况下,Elasticsearch 系统调用过滤器(seccomp)是启用的,这些过滤器阻止了进程分叉。因此,使用 OnErrorOnOutOfMemoryError 与系统调用过滤器是不兼容的。OnErrorOnOutOfMemoryError 检查会阻止 Elasticsearch 启动,如果使用了这些 JVM 选项并且启用了系统调用过滤器。此检查始终强制执行。要通过此检查,请不要启用 OnErrorOnOutOfMemoryError;而是升级到 Java 8u92 并使用 JVM 标志 ExitOnOutOfMemoryError。虽然这没有 OnErrorOnOutOfMemoryError 的全部功能,但在启用 seccomp 的情况下将不支持任意分叉。

早期访问检查

edit

OpenJDK 项目提供了即将发布的早期访问快照。这些版本不适合用于生产环境。早期访问检查会检测这些早期访问快照。要通过此检查,您必须在 JVM 的发布版本上启动 Elasticsearch。

所有权限检查

edit

全权限检查确保在引导过程中使用的安全策略不会授予Elasticsearch java.security.AllPermission。以授予全权限运行等同于禁用安全管理器。

发现配置检查

edit

默认情况下,当Elasticsearch首次启动时,它会尝试发现同一主机上运行的其他节点。如果在几秒钟内无法发现选定的主节点,那么Elasticsearch将形成一个集群,该集群包括任何已发现的其他节点。在开发模式下,无需任何额外配置即可形成此集群非常有用,但这不适合生产环境,因为可能会形成多个集群并因此丢失数据。

此引导检查确保发现功能未使用默认配置运行。可以通过设置以下属性中的至少一个来满足此检查:

  • discovery.seed_hosts
  • discovery.seed_providers
  • cluster.initial_master_nodes

请注意,在集群首次启动后,您必须从每个节点的配置中移除 cluster.initial_master_nodes。相反,配置 discovery.seed_hostsdiscovery.seed_providers。如果您不需要任何发现配置,例如在运行单节点集群时,设置 discovery.seed_hosts: [] 以禁用发现并满足此引导检查。