ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Ubuntu 18.04上Elasticsearch安装与配置全攻略

Ubuntu 18.04上Elasticsearch安装与配置全攻略

1. 安装前的环境准备与版本考量

1.1 先聊聊为什么要关注版本搭配

先说一个老生常谈但又必须强调的点:安装ElasticSearch之前,一定要先确认版本匹配关系。很多初次接触ES的人上来就直接apt install elasticsearch,结果装完启动报错、插件装不上、或者跟已有的数据不兼容,折腾半天才发现是版本问题。

以Ubuntu 18.04为例,这个系统版本本身并不算新,但它依然是一个非常稳定的生产环境选项。ES官方对操作系统有自己的兼容性矩阵,不同版本的ES对Linux内核、glibc、Java版本都有明确要求。比如ES 7.x系列要求Java 11+,而ES 6.x系列则基于Java 8。如果你在Ubuntu 18.04上安装了系统自带的OpenJDK 11,然后去跑ES 6.8.x的包,启动阶段就会直接报出Unsupported Java version之类的错误。

我的建议是:先确定你要用的ES版本,再反推Java版本,最后决定安装方式。这个顺序不要乱。比如常用的ES 7.10.2,对应的Java版本是11,JDK 8也能运行但会有警告信息,而JDK 15、16这类过高版本反而可能不被支持。类似这种版本间的"隐性门槛",光看官方文档不一定能一次搞清楚,实际踩坑之后才会记住。

另外还需要确认你的服务器内存。ES是基于JVM运行的搜索引擎,默认堆内存设置是1GB,这个数值在测试环境还凑合,生产环境几乎必然要调。如果服务器内存只有2GB,建议把堆内存调到1GB左右,给操作系统和文件缓存留出余量;如果内存充足,比如16GB的机器,可以设置4GB到8GB的堆内存,但最好不要超过物理内存的一半,因为Lucene本身还需要大量堆外内存做文件缓存。

1.2 Java环境:最容易被忽略的环节

Ubuntu 18.04上安装Java的方式其实有好几种,但实际经验告诉我,最容易踩坑的是安装了一个版本不对的JDK,导致后续ES启动报错。推荐的做法是使用OpenJDK,而不是Oracle JDK,原因是ES官方对OpenJDK的兼容性验证比较充分,而且OpenJDK在Ubuntu的软件源里可以直接安装,省去了配置PPA的麻烦。

sudo apt update sudo apt install openjdk-11-jdk

安装完成之后,检查Java版本:

java -version

正常会输出类似下面的内容:

openjdk version "11.0.22" 2024-01-16 OpenJDK Runtime Environment (build 11.0.22+7-post-Ubuntu-0ubuntu118.04.1) OpenJDK 64-Bit Server VM (build 11.0.22+7-post-Ubuntu-0ubuntu118.04.1)

这里有个细节值得多说一句:有时候你执行java -version发现已经是JDK 11了,但ES启动后依然报Java版本错误。这通常是因为你的JAVA_HOME环境变量没有设置,或者指向了错误的路径。ES启动脚本会优先读取JAVA_HOME,如果你没设置它,就会去PATH里找java命令,两者不一致时就会出问题。

因此建议安装完成后,把JAVA_HOME写进/etc/profile.d/java.sh这个文件里:

export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 export PATH=$PATH:$JAVA_HOME/bin

然后执行source /etc/profile.d/java.sh让配置立即生效,再用echo $JAVA_HOME验证一下。这一步看着简单,但很多莫名的启动异常都是从这里开始的。

如果你的项目计划使用ES 8.x,那JDK版本就要求17了。Ubuntu 18.04默认软件源里可能没有OpenJDK 17,需要手动添加第三方源或者直接从官网下载JDK 17的tar包解压安装。相比之下,我推荐先把ES版本定在7.10.x,因为它在Ubuntu 18.04上的兼容性验证最为成熟,资料也多,遇到问题容易搜到解决方案。

2. 正式安装:两种常用方式的完整对比

2.1 通过APT仓库安装(推荐)

ES官方提供了APT仓库,配置好之后可以直接用apt install elasticsearch来安装,好处是后续版本升级比较方便,而且软件包已经做好了systemd服务脚本,安装完成就能用systemctl管理。

首先安装apt-transport-https这个工具,以保证可以走HTTPS协议访问ES的软件源:

sudo apt install apt-transport-https

然后导入ES官方的GPG密钥:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

接着添加仓库源。这里要注意,不要直接把网上复制的命令无脑粘贴,因为不同ES大版本对应的仓库地址是不同的。以7.x为例,需要编辑/etc/apt/sources.list.d/elastic-7.x.list这个文件,写入下面这行内容:

deb https://artifacts.elastic.co/packages/7.x/apt stable main

如果你打算用8.x,那就要把7.x替换成8.x。这个细节看起来不起眼,但如果你之前装过6.x然后又想升级到7.x,就会因为仓库地址没更新而装到旧版本。

配置完成之后,更新软件源并安装:

sudo apt update sudo apt install elasticsearch

安装过程会自动创建elasticsearch用户和用户组,也会把相关文件放到标准路径下。装完之后,可以用下面的命令确认安装版本:

/usr/share/elasticsearch/bin/elasticsearch --version

输出内容会显示完整的版本号和构建信息。我实测过好几次,这个方式在Ubuntu 18.04上非常稳定,基本没有依赖冲突的问题。

2.2 手动解压安装(更灵活的方式)

如果你对安装路径有特殊要求,或者想装一个本地测试环境、不想污染系统目录,那手动解压安装是更合适的选择。这种方式没有系统包的自动化配置,所有路径都由自己控制,理解起来也更透彻。

首先下载对应版本的tar.gz包。比如要装7.10.2:

cd /opt wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.2-linux-x86_64.tar.gz tar -zxvf elasticsearch-7.10.2-linux-x86_64.tar.gz mv elasticsearch-7.10.2 /opt/elasticsearch

解压完成之后,建议手动创建一个专门运行ES的系统用户,而不是直接用root用户运行。ES本身出于安全考量,明确禁止以root身份启动,所以这个用户是必需的:

useradd -m -s /bin/bash elasticsearch chown -R elasticsearch:elasticsearch /opt/elasticsearch

切换到elasticsearch用户并启动:

su - elasticsearch /opt/elasticsearch/bin/elasticsearch

这里需要注意,如果直接以root用户执行/opt/elasticsearch/bin/elasticsearch,会得到一个非常明确的报错信息:can not run elasticsearch as root。这是ES的自我保护机制,千万不能通过修改配置强行绕过,否则会产生严重的安全风险。

两种安装方式的取舍,我给一个简单的对比表,方便你根据自己场景做决策:

对比项APT安装手动解压
安装速度快中等
版本管理方便,支持apt upgrade需要手动管理
路径规划固定的系统路径完全自主控制
systemd脚本自动生成需手动配置
适合场景生产环境推荐测试环境、学习实验

3. 核心配置文件解读与实践调整

3.1 elasticsearch.yml里的关键项

ES的配置文件位于/etc/elasticsearch/elasticsearch.yml(APT安装)或者$ES_HOME/config/elasticsearch.yml(手动解压安装)。这个文件里的配置项非常多,但实际日常用到的也就是那么十几个,这里挑几个必调的项逐一拆解。

node.name

节点名称,默认为主机名。在单机环境里不修改也可以,但如果你后续要搭建集群,就必须给每个节点起一个唯一的名字,否则节点之间会因为重名而无法正常加入集群。

path.data 和 path.logs

数据目录和日志目录。APT安装默认分别是/var/lib/elasticsearch和/var/log/elasticsearch。生产环境强烈建议把数据目录放到独立的磁盘分区上,一方面避免系统盘空间被ES数据撑爆,另一方面便于备份和扩容。

path.data: /data/es/data path.logs: /data/es/logs

注意设置好目录属主,确保elasticsearch用户有读写权限,不然启动时会报access denied。

network.host

绑定地址。默认是127.0.0.1,只能本机访问,测试没问题。但如果你需要通过局域网访问ES服务,就要改成0.0.0.0或者指定具体的内网IP。

network.host: 0.0.0.0

这里有个容易被忽略的后果:一旦你设置了非loopback的地址,ES会自动把运行模式切换为生产模式,随之而来的是一堆自检项,比如上面提到vm.max_map_count、文件描述符限制、线程数限制等,任何一个不满足都会导致启动失败。这一块我会在后面的问题排查部分专门展开。

discovery.seed_hosts 和 cluster.initial_master_nodes

这两个配置涉及集群发现机制。单机环境下,通常只需要设置discovery.type: single-node来告诉ES我们不需要跨节点发现,否则在默认配置下ES会试图寻找其他节点并可能因为超时而报错。

discovery.type: single-node

如果是多机集群,则要取消这个配置,改成:

discovery.seed_hosts: ["node1:9300", "node2:9300", "node3:9300"] cluster.initial_master_nodes: ["node1"]

3.2 JVM堆内存设置:别小看这两行

JVM堆内存的配置在jvm.options文件里,主要关注-Xms和-Xmx这两个参数,分别代表初始堆内存和最大堆内存。ES官方要求这两个值必须相等,目的是避免JVM运行时动态扩缩堆导致性能抖动。

-Xms4g -Xmx4g

选多大合适?我的经验公式是:物理内存的一半以内。比如服务器有8GB内存,设4GB比较合适;如果服务器只有4GB,建议设2GB。不要贪大,因为ES的Lucene索引读写还会使用大量操作系统文件缓存,这些内存不归JVM管,如果堆内存占比过高,反而可能导致系统整体性能下降。

另外,堆内存超过32GB还有一个隐藏的坑:JVM的压缩指针机制会失效,导致内存占用膨胀,垃圾回收效率下降,性能反而变差。所以即便你有一台64GB内存的机器,也建议把ES堆内存设成31GB以内,剩下的内存留给操作系统做文件缓存。

4. 启动、验证与开机自启

4.1 前台启动与后台守护

如果你是手动解压安装,最直接的启动方式就是前台运行:

/opt/elasticsearch/bin/elasticsearch

前台启动的优势在于日志会直接打到终端上,方便调试。看到类似下面的输出,说明ES正在正常初始化:

[2025-01-15T14:22:31,123][INFO ][o.e.n.Node] [node-1] initialized [2025-01-15T14:22:31,456][INFO ][o.e.n.Node] [node-1] starting ...

前台启动并不适合长期运行服务,我们应该把它做成systemd服务。作为参考,APT安装的ES已经自带了/usr/lib/systemd/system/elasticsearch.service文件,直接就能用:

sudo systemctl daemon-reload sudo systemctl start elasticsearch sudo systemctl status elasticsearch

如果是手动解压安装,可以参考下面的模板手动创建服务文件:

[Unit] Description=Elasticsearch After=network.target [Service] Type=forking User=elasticsearch Group=elasticsearch ExecStart=/opt/elasticsearch/bin/elasticsearch -d -p /var/run/elasticsearch.pid ExecStop=/opt/elasticsearch/bin/elasticsearch-stop Restart=always LimitNOFILE=65535 [Install] WantedBy=multi-user.target

保存到/etc/systemd/system/elasticsearch.service后,执行systemctl daemon-reload使配置生效。

4.2 验证安装是否成功

服务启动后,直接用curl请求ES的REST API接口,这是最直观的验证方式:

curl http://localhost:9200

正常情况下会返回一串JSON,类似:

{ "name" : "node-1", "cluster_name" : "elasticsearch", "cluster_uuid" : "xxxxxx", "version" : { "number" : "7.10.2", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "xxxxx", "build_date" : "2021-01-13T00:42:29.402Z", "build_snapshot" : false, "lucene_version" : "8.7.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }

看到这个返回,基本就说明ES已经正常工作了。另外还可以查看集群健康状态:

curl http://localhost:9200/_cluster/health?pretty

返回的status字段为green,说明一切正常;如果是刚创建完索引后立刻查看,偶尔会出现短暂yellow,这是分片副本还没分配完毕,稍等片刻再查就好。

4.3 配置systemd服务实现开机自启

无论用上面哪种方式安装,最后都要配置开机自启,避免服务器重启后ES没有拉起。APT安装的版本可以执行:

sudo systemctl enable elasticsearch

手动解压安装的话,在完成上面的.service文件配置之后,一样可以执行systemctl enable。之后可以通过下面的命令确认生效:

systemctl is-enabled elasticsearch

输出enabled就说明没问题了。

5. 常见问题与实战排查记录

5.1 启动报错:max virtual memory areas vm.max_map_count

这个问题出现的频率极高,按概率算能占到ES启动失败原因的六成以上。报错信息通常长这样:

ERROR: [1] bootstrap checks failed [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

原因很简单:ES底层使用Lucene,而Lucene在索引和搜索过程中会创建大量内存映射文件(mmap),Linux内核通过vm.max_map_count参数限制了进程可以拥有的内存映射区域数量。默认值65530在很多场景下不够用,ES要求至少262144。

解决办法是临时调整系统参数:

sudo sysctl -w vm.max_map_count=262144

但这个修改在系统重启后就会失效,所以要写入/etc/sysctl.conf:

echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf

再执行sudo sysctl -p让配置立刻生效。我之前遇到过一种情况:sysctl -p执行后更新了当前值,但ES启动时依然报同样的错,最后发现是因为ES进程是被systemd拉起的环境,而systemd环境里的参数是启动时读取的,需要systemctl restart才能完全生效。

5.2 外网访问不了9200端口

这个问题的典型场景是:配置文件里已经设置了network.host: 0.0.0.0,本机curl也能正常访问,但从其他机器就是连不上9200端口。

排查顺序是固定的。先看防火墙,Ubuntu 18.04默认使用ufw:

sudo ufw status

如果是开启状态,放行9200端口:

sudo ufw allow 9200/tcp

再看ES有没有监听在正确的网卡上:

netstat -tlnp | grep 9200

正常输出会是0.0.0.0:9200或具体的内网IP,如果显示127.0.0.1:9200,说明配置没有生效,需要确认network.host所在配置文件的层级。ES的yaml配置是按层级缩进解析的,network.host必须写在最顶层,不能缩进到其他配置项下面,否则会被当成子属性直接忽略。

还有一种容易被忽略的情况:服务器上有多个网卡,ES绑定了内网IP,但你从公网IP访问。这种情况要么把network.host改成公网IP,要么在前面挂一层代理转发。一般情况下,ES本身的管理接口不建议直接暴露公网,绑定内网IP然后在应用层做拦截是更安全稳妥的做法。

5.3 单机多实例启动失败

有些情况下需要在一台机器上跑多个ES实例,比如模拟集群环境做测试。很多人直接复制一份ES目录,改一下配置就启动第二个实例,结果报端口冲突。

ES默认使用9200端口做HTTP通信,9300端口做节点间通信。单机多实例时,这两个端口都必须手动错开。第二个实例的配置至少需要改下面几项:

node.name: node-2 path.data: /data/es2/data path.logs: /data/es2/logs http.port: 9201 transport.port: 9301

同时要确保两个实例的数据目录、日志目录完全分离,否则后启动的实例会因为数据目录被占用而崩溃。

另外要提醒一点:单机多实例时,discovery.type: single-node要谨慎使用,因为每个实例都会认为自己是独立的单节点集群,它们之间不会自动组成集群。如果想要让多个实例互相发现并组成集群,需要删除这个配置,改设discovery.seed_hosts和cluster.initial_master_nodes,并且设置相同的cluster.name。

5.4 内存不足导致节点启动即崩

ES对系统资源的消耗还是比较可观的,尤其是堆内存之外的文件缓存。如果服务器内存本身比较小,比如2GB,又照搬网上的配置把-Xms2g -Xmx2g直接填进去,就会出现启动过程中JVM内存分配失败,节点瞬间退出。

报错信息可能是:

There is insufficient memory for the Java Runtime Environment to continue. Native memory allocation (mmap) failed to map 2147483648 bytes for committing reserved memory.

定位思路很简单:先看物理内存总量和当前可用内存:

free -h

确认之后把堆内存调低,比如改成-Xms1g -Xmx1g。还有一个更隐蔽的情况:默认配置中ES的bootstrap.memory_lock如果开启的话,JVM启动时会尝试锁住堆内存空间,内存不足时同样会失败。排查时可以临时把该项设成false,或者关掉不必要的进程释放内存。

5.5 常见问题速查表

为了方便实际操作时快速定位,我把上面提到的几个典型问题整理成一张速查表:

问题现象常见原因快速处理办法
启动报vm.max_map_count过低内核参数默认值不足设置vm.max_map_count=262144并写入/etc/sysctl.conf
外网无法访问9200端口防火墙未放行或绑定地址错误ufw allow 9200;检查network.host层级
以root用户启动失败ES安全机制禁止root运行创建elasticsearch用户并切换运行
启动后自动退出JVM堆内存设置超出物理内存调整jvm.options里的-Xms和-Xmx
多个实例同时启动失败端口或数据目录冲突修改http.port、transport.port和数据目录
集群状态为yellow分片副本未全部分配检查数据节点是否在线,等待分片恢复

6. 生产环境落地的一些额外建议

6.1 安全配置优先做

ES在默认配置下是没有任何身份认证的,只要网络能通,任何人都可以对你集群里的数据执行任意读写操作。这在开发环境没什么问题,但一旦涉及生产环境,尤其是部署到云服务器上,安全隐患就很明显了。

这里我提供一个最小化安全方案。第一,不要将9200端口暴露到公网,只监听内网地址;第二,在所有节点上配置防火墙,仅允许应用服务器的IP访问9200端口;第三,如果需要更细粒度的权限控制,可以考虑启用ES自带的Security功能(需要许可证支持)或者使用反向代理层做认证。

从合规和实际风险应对的角度来看,先把网络层面收口,再考虑应用层认证,这是一个不会出错的顺序。

6.2 数据备份要落地

很多人在ES上做完数据索引就觉得万事大吉,直到一次误删或者磁盘故障才意识到备份的重要性。ES提供了快照和恢复功能,操作方式比较简单,建议至少配置一个本地快照仓库。

首先在elasticsearch.yml中指定仓库路径:

path.repo: /data/es/backups

然后创建快照仓库:

curl -X PUT "localhost:9200/_snapshot/my_backup" -H 'Content-Type: application/json' -d' { "type": "fs", "settings": { "location": "/data/es/backups" } }'

手动打一个快照:

curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_20250115"

如果是重要索引,建议配合定时任务定期执行快照,比如每日凌晨打一次,保留最近七天的快照,兼顾数据安全和存储成本。

6.3 监控与日志关注点

ES自身提供了_cat/indices、_nodes/stats这些API,可以快速查看索引状态和节点资源使用情况。日常巡检主要看几个指标:索引健康状态、堆内存使用率、搜索和索引的QPS、磁盘使用率。

如果发现堆内存使用率持续偏高,而且GC频繁,首要考虑的是调整查询逻辑或增加节点,而不是简单调大堆内存。堆内存本身并不是越大越好,这又回到了前面说的内存分配思路——留足系统缓冲,平衡JVM和文件缓存的资源分配。

另外,ES运行日志默认按天滚动,保留周期可以自行设置。我建议保留至少30天的日志,便于问题回溯。默认配置下日志文件可能只保留一周,遇到突发问题时往往会发现历史日志被清理掉了,影响排查效率。这个不算技术难点,但确实是运维中容易忽视的细节。

写在最后

从环境准备到安装,从配置调优到问题排查,再到生产环境的安全与备份建议,整个流程走下来,你会发现ES的安装本身并不复杂,真正的门槛在于理解每个配置项背后的原理。知其然再知其所以然,后续无论是调优还是排查问题,都会从容很多。

我个人在Ubuntu 18.04上把整个过程跑过很多遍,踩过最多的坑就是版本不匹配和内核参数未调整。如果你在安装过程中遇到了本文没有覆盖到的问题,先去看日志总不会错——日志文件在/var/log/elasticsearch/elasticsearch.log(APT安装)或$ES_HOME/logs/elasticsearch.log(手动解压),大部分启动失败的根因都会清晰地写在里面,定位起来比盲猜要高效得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进