继续跟中华石杉老师学习ES,第68篇
课程地址: https://www.roncoo.com/view/55
理想情况下,es应该单独在一个服务器上运行,能够使用服务器上的所有资源。为了达到上述目标,我们需要配置操作系统,来允许用户运行es并且获取比默认情况下更多的资源。
在生产环境中下面的一些设置必须配置一下:
(1)禁止swapping
(2)确保拥有足够的虚拟内存
(3)确保拥有足够的线程数量
https://www.elastic.co/guide/en/elasticsearch/reference/current/system-config.html#dev-vs-prod
默认情况下,es会假设你是在开发模式下运行的。如果上面的任何配置没有正确的设置,那么会输出一些warning到日志文件中,但是我们还是可以启动es进程的。
从5.0开始,ES加入了Bootstrap Checks ,Elasticsearch 会在启动时进行 Bootstrap Checks。Bootstrap Checks 会检查很多 Elasticsearch 和系统的配置。在开发模式下,所有没通过的检查都会报 warnings 并写进日志文件,即使检查没通过,依然可以启动节点运行 Elasticsearch;而在生产模式下,任何没通过的 Bootstrap Checks 都会报异常并阻止 Elasticsearch 启动 。
比如我们配置了网络设置,比如network.host,es会认为我们是运行在生产环境中的,然后就会将上述warning升级为exception。这些exception会阻止我们的es节点启动。
这是一个重要的安全保障措施来确保我们不会因为错误的配置了es server,而导致数据丢失。
比如你可能碰到
ERROR: [1] bootstrap checks failed
[1]: initial heap size [1073741824] not equal to maximum heap size [2147483648]; this can cause resize pauses and prevents mlockall from locking the entire heap
setting-system-settings: https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-system-settings.html
在/etc/security/limits.conf中,可以配置系统设置 ,也可以用ulimit临时配置系统设置
在linux操作系统中,ulimit可以用来临时的改变资源限制。通常需要用root权限来设置ulimit。
举例,如果要设置file descriptor为65536,可以用如下的命令来设置:
ulimit -n 65536
但是在linux操作系统中,实际上永久性的资源限制可以通过编辑**/etc/security/limits.conf**文件来设置。比如要设置file descriptor,可以再limits.conf中加入下面的行:
elasticsearch - nofile 65536
在下一次elasticsearch用户开启一个新的会话时就会生效
https://www.elastic.co/guide/en/elasticsearch/reference/current/file-descriptors.html
一般建议通过jvm.options配置文件来设置es的jvm option。默认的地址是config/jvm.options
每行是一个jvm argument
此外,如也可以通过ES_JAVA_OPTS环境变量来设置jvm option,比如下面的命令:
export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djava.io.tmpdir=/path/to/temp/dir"
官网指导: https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration-memory.html
大多数操作系统都会使用尽量多的内存来进行file system cache,并且尽量将不经常使用的java应用的内存swap到磁盘中去。这会导致jvm heap的部分内存,甚至是用来执行代码的内存页被swap到磁盘中去。下次读取 ,内存中不存在又需要从磁盘重新读取,必然影响性能。
swapping对于性能来说是非常差劲的,为了es节点的稳定性考虑,应该尽量避免这种swapping。因为swapping会导致gc过程从毫秒级变成分钟级,在gc的时候需要将内存从磁盘中swapping到内存里,特别耗时,这会导致es节点响应请求变得很慢,甚至导致es node跟cluster失联。
在一个弹性的分布式系统中,让操作系统kill掉某一个节点,是很高效的。
有三种方法可以disable swapping。推荐的option是彻底禁用swap,如果做不到的化,也得尽量最小化swappiness的影响,比如通过lock memory的方法。
通常来说,es进程会在一个节点上单独运行,那么es进程的内存使用是由jvm option控制的。
可以使用下面的命令临时性禁止swap:swapoff -a
要永久性的禁止swap,需要修改/etc/fstab
文件,然后将所有包含swap的行都注释掉
另外一个方法就是通过sysctl,将vm.swappiness设置为1,这可以尽量减少linux内核swap的倾向,在正常情况下,就不会进行swap,但是在紧急情况下,还是会进行swap操作。sysctl -w vm.swappiness=1
最后一个选项,就是用mlockall,将es jvm进程的address space锁定在内存中,阻止es内存被swap out到磁盘上去。
在config/elasticsearch.yml中,可以配置:
bootstrap.memory_lock: true
GET _nodes?filter_path=**.mlockall
,通过这行命令可以检查mlockall是否开启了
如果发现mlockall是false,那么意味着mlockall请求失败了。会看到一行日志,unable to lock jvm memory。
最大可能的原因,就是在linux系统中,启动es进程的用户没有权限去lock memory,需要通过以下方式进行授权:
ulimit -l unlimited
/etc/security/limits.conf
,memlock设置为unlimited
另外一个原因可能是临时目录使用noexec option来mount了。可以通过指定一个新的临时目录来解决
export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djava.io.tmpdir=/path/to/temp/dir"
当然也可以通过在jvm.options文件中来设置java.io.tmpdir
官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html
es使用mmapfs 目录来存储index数据,操作系统的默认mmap count限制是很低的,可能会导致内存耗尽的异常。
需要提升mmap count的限制:sysctl -w vm.max_map_count=262144
如果要永久性设置这个值,要修改**/etc/sysctl.conf**,将vm.max_map_count的值修改一下,重启过后,用sysctl vm.max_map_count来验证一下数值是否修改成功
官方指导: https://www.elastic.co/guide/en/elasticsearch/reference/current/max-number-of-threads.html
es用了很多线程池来应对不同类型的操作,在需要的时候创建新的线程是很重要的。要确保es用户能创建的最大线程数量至少在4096以上。
可以通过ulimit -u 4096
来临时设置,也可以在/etc/security/limits.con
f中设置nproc为4096来永久性设置。
https://www.elastic.co/guide/en/elasticsearch/reference/current/networkaddress-cache-ttl.html
Elasticsearch在适当的位置运行安全管理器。
有了安全管理器,JVM默认将无限期地缓存正主机名解析,并且默认将十秒内缓存负主机名解析。
Elasticsearch使用默认值覆盖此行为,以将正向查找缓存六十秒,并将负向查找缓存十秒。这些值应适用于大多数环境,包括DNS分辨率随时间变化的环境。
如果没有,您可以 在JVM选项中编辑值es.networkaddress.cache.ttl
和es.networkaddress.cache.negative.ttl
。需要注意的是价值 和 在 Java安全策略由Elasticsearch忽略,除非你删除的设置 和。
es.networkaddress.cache.negative.ttlnetworkaddress.cache.ttl=<timeout>
networkaddress.cache.negative.ttl=<timeout>
es.networkaddress.cache.ttles.networkaddress.cache.negative.ttl
这仅与Linux有关。
Elasticsearch使用Java本机访问(JNA)库来执行一些平台相关的本机代码。
在Linux上,在运行时从JNA存档中提取支持该库的本机代码。默认情况下,此代码被提取到Elasticsearch临时目录,该目录默认为的子目录 /tmp。或者,可以使用JVM标志来控制此位置 -Djna.tmpdir=
。
由于本机库以可执行文件的形式映射到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。如果看到这样的错误消息,则必须重新挂载JNA所用的临时目录,以使其无法挂载noexec。