1. 安装方案这么选:别一上来就敲命令
先交代一下背景。Ubuntu 18.04 这个系统至今还有不少存量机器在跑,尤其是一些内部日志平台、爬虫数据管道和中小公司的测试环境。而它默认仓库里的 ElasticSearch 版本往往旧得离谱,如果你直接 apt install,装出来大概率是 6.x 甚至更老的版本,跟后续要用的客户端、Kibana、插件对不上。真正稳妥的姿势是手动下载 tar 包,自己控制目录、版本和配置,这也是我在 Ubuntu 18.04 上装 ElasticSearch 一直用的方式。
安装之前我强烈建议先想清楚一个问题:你到底要单机玩玩,还是要搭一个多节点集群。因为 ElasticSearch 单机和集群的配置差别很大,启动参数和系统参数的要求也不一样。很多人装完单机一切正常,一扩集群就各种报错,根子就在前期方案没定清楚。
1.1 tar 包安装和 apt 源安装怎么权衡
apt 仓库安装的最大优点是省事,依赖会自动处理,理论上 sudo apt install elasticsearch 就能跑起来。但实际操作中你会发现几个痛点:官方 apt 源在国内访问速度不稳定,经常下载到一半断掉;版本锁定不灵活,同一个源里往往只有一个大版本,想要 7.17 或者 8.x 的最新维护版,你得先手动改源地址;还有一点是 apt 装出来的目录结构是散的,配置文件在 /etc/elasticsearch,数据在 /var/lib/elasticsearch,日志在 /var/log/elasticsearch,排查问题的时候翻起来比较费劲。
tar 包安装则完全相反,所有文件都集中在同一个目录下,迁移、升级、多实例部署都非常方便。你要启动第二个节点,直接把整个目录复制一份,改掉配置里的 node.name 和 data 目录就能跑。这在做压测、搭集群模拟环境的时候几乎是必需的能力。所以在 Ubuntu 18.04 上,我最终选择的是官方 tar.gz 包,而不是 apt。
1.2 版本选择:7.17 还是 8.x
ElasticSearch 目前主流的选择是 7.17 和 8.x 两条线。7.17 是 7.x 系列的最后一个维护版本,功能稳定,插件生态最丰富,网上能搜到的问题答案也最多。它对 JDK 的要求相对宽松,8.x 开始默认开启安全认证,很多老用户第一次上手会被用户名密码、证书这些东西搞得晕头转向。
如果是搭建新的日志系统,且团队里没有人熟悉 ElasticSearch,我更倾向于 7.17。理由很简单:默认配置下 7.17 可以直接 curl 访问,不需要处理账号密码;IK 分词器、各种监控插件基本都是为 7.x 优化的,兼容性有保障。如果是全新项目且长期维护,那么 8.x 也可以,但你要接受配置习惯的差异,尤其是安全这块必须从第一天就规划好。
我自己在 Ubuntu 18.04 上装的是 7.17.22,这个版本捆绑了 JDK,所以系统里有没有 Java 其实都不重要。这一点很多人容易忽略,后面专门说。
2. 装之前的环境准备:JDK 和系统内核参数
很多新手一上来就解压、改配置、启动,然后报错一串串的。我见过最多的报错是 bootstrap checks failed,这个基本上都是系统参数没调好导致的。所以我建议在真正执行安装命令之前,先花十分钟把环境和依赖捋一遍。
2.1 JDK 到底需不需要单独装
这个问题我在社区里被问过很多次。答案分成两种情况:如果你用的是 7.17 及以上版本,不需要,因为官方 tar 包里已经自带了一套 JDK,位于 jdk 目录下;如果你用的是 6.x,那可能需要系统里安装 JDK 8,但这个版本太老,不推荐再用。
有些场景下你确实想指定系统自己的 JDK,比如公司强制统一 Java 版本,或者你需要在同一台机器上跑多个不同插件。此时 ES 会通过 JAVA_HOME 环境变量来找 JDK。在 Ubuntu 18.04 上,你可以在 /etc/profile.d/elasticsearch.sh 里写一行 export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64,然后 source 一下。
这里要提醒一个坑:ES 对 JDK 版本有严格校验,版本不满足会直接启动失败。与其折腾系统 JDK,不如直接用自带的,省心。我早期维护日志平台那批机器时,就是因为一台机器系统 JDK 从 8 被误升到 11,导致 ES 启动报错,后来统一改成默认自带 JDK 才彻底消停。
2.2 三个必须提前调整的系统参数
ElasticSearch 启动时会做一系列检查,叫做 bootstrap checks,这些检查不通过,进程会直接退出。其中最常触发的是下面三个参数。
第一个是 vm.max_map_count。ES 的 Lucene 底层会用大量内存映射文件,默认值 65530 不够用,必须调到 262144。修改方式是在 /etc/sysctl.conf 里追加一行,然后执行 sysctl -p 让它立即生效。这个参数如果不改,启动日志里会出现 max virtual memory areas vm.max_map_count [65530] is too low 的报错。
第二个是进程可以打开的文件描述符数量 nofile。ES 需要打开大量文件,默认的 1024 太小,需要设置成 65535。这里有两个地方要改:一个是 /etc/security/limits.conf,另一个是 systemd 服务文件里的 LimitNOFILE。很多人在 limits.conf 里改了没用,就是因为跑 ES 用的 systemd 服务会单独覆盖这个设置。
第三个是内存锁 mlockall。ES 建议把堆内存锁定在物理内存里,防止被交换到 swap,造成严重的性能抖动。在配置文件里设置 bootstrap.memory_lock: true 后,系统还得允许用户锁内存,否则会报 memory locking requested for elasticsearch process but memory is not locked 的错误。同一台机器如果还跑着其他业务,我一般不建议开这个,宁可让操作系统正常管理内存,也不要因为锁内存导致其他应用申请不到内存。
2.3 swap 和防火墙怎么处理
Ubuntu 18.04 的默认安装往往带着 swap 分区,特别是在虚拟机里。ES 对 swap 非常敏感,一旦内存被换出,查询延迟会飙升,甚至出现节点假死。最简单的处理方式是临时关闭 swap:sudo swapoff -a。想永久关闭就去改 /etc/fstab,把 swap 那一行注释掉。如果是容器环境,这个操作可能受限,那就必须开启 mlockall 来保命。
防火墙这边,只要是测试环境,很多人直接关了 iptables,但生产环境千万不能这样。9200 端口是 ES 的 HTTP 端口,9300 是集群节点间通信端口,只应该对可信 IP 开放。Ubuntu 18.04 默认用的是 ufw,可以执行 sudo ufw allow from 192.168.1.0/24 to any port 9200 来限制访问范围。这个动作很多人不做,结果 ES 裸奔到公网,被勒索挖矿脚本一扫一个准。
3. 安装配置全流程实操记录
环境准备好了,接下来就是正儿八经的安装环节。下面这一套是我在 Ubuntu 18.04 上反复跑过多次的流程,每一步都写了为什么这么做,方便你理解而不是照着敲一遍就完事。
3.1 下载解压与目录规划
先在官网下载页面找到对应版本的 tar.gz 包。我这里用的版本号是 7.17.22,你可以根据实际需要替换。下载完以后强烈建议校验一下文件完整性,用 sha512sum 比对官网提供的校验值,防止下载过程丢包。
cd /opt curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.22-linux-x86_64.tar.gz sha512sum elasticsearch-7.17.22-linux-x86_64.tar.gz tar -zxvf elasticsearch-7.17.22-linux-x86_64.tar.gz解压之后不要急着用 root 去启动。ES 明确禁止以 root 身份运行,这是出于安全考虑,因为 Java 进程可以直接操作文件系统,权限过大会增加风险。所以我们要新建一个专用用户:
useradd -m esuser chown -R esuser:esuser /opt/elasticsearch-7.17.22很多人喜欢把数据目录和程序目录分开,这是好习惯。升级版本时只需要替换程序目录,数据目录保留,数据就不会丢。我在实际部署中习惯这样组织目录:
mkdir -p /data/es-data mkdir -p /data/es-logs chown -R esuser:esuser /data/es-data /data/es-logs最后进入 elasticsearch 目录,你会发现里面有 bin、config、jdk、lib、logs 等目录。config 下最关键的文件有两个:elasticsearch.yml 和 jvm.options。下面逐个拆解。
3.2 elasticsearch.yml 关键配置项拆解
打开 elasticsearch.yml,里面是一大堆注释模板,真正需要改的其实就那么几个字段。我把生产环境常用的配置贴出来并逐行解释:
cluster.name: es-prod node.name: node-1 path.data: /data/es-data path.logs: /data/es-logs network.host: 0.0.0.0 http.port: 9200 discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"] cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]cluster.name 是集群名字,同一个集群里的所有节点这个名字必须一致,否则各节点互不认识,会各自形成单节点集群。node.name 是当前节点的名字,集群内必须唯一。path.data 和 path.logs 指向之前建好的数据目录和日志目录,目录权限要确认已经交给 esuser。
network.host 这个字段很关键,默认是 127.0.0.1,只允许本机访问。想对外提供服务就得改成 0.0.0.0,但一旦改成非本机地址,ES 会自动开启生产模式,bootstrap checks 也会全部生效。这时候如果系统参数没调好,启动就会报错。所以我的建议是:单机测试保持默认不折腾;集群环境再改 0.0.0.0,并且确保 2.2 节里的参数全部到位。
discovery.seed_hosts 是集群发现用的地址列表,写其他节点的 IP 或者主机名。cluster.initial_master_nodes 是集群引导时的初始 master 候选节点,只用于集群第一次启动,正常运行时不需要,甚至如果每台节点都填上了,反而可能出现脑裂相关的问题。这一点很多人不懂,后面常见问题里我还会细说。
3.3 jvm.options 堆内存怎么设
jvm.options 里最常见的是 -Xms 和 -Xmx 这两个参数,分别表示 JVM 堆内存的初始值和最大值,默认是物理内存的一半。我见过不少人直接把两个值都改成 30g,结果机器总内存才 32g,系统本身和其他进程还有开销,分分钟 OOM。
一个合理的经验法则是:堆内存不要超过物理内存的 50%,同时上限不要超过 31g。为什么是 31g?因为 JVM 的压缩指针技术,超过这个值后对象指针从一个字节变成两个字节,内存效率反而下降。假设你有一台 4 核 8G 的测试机,我建议设置:
-Xms4g -Xmx4g两个值保持一致,避免 JVM 在运行中动态扩容堆导致停顿。如果机器内存是 16G,那设置 8g 也没问题,但要记住给操作系统和 page cache 留余地。ES 查询过程大量依赖文件系统缓存,堆设得太大反而让缓存没有空间,性能会下降,这是一般人容易犯的错。
3.4 首次启动与验证
配置完成后,切换到 esuser 用户,前台启动一次,目的是看清启动日志:
sudo -u esuser /opt/elasticsearch-7.17.22/bin/elasticsearch启动日志会让你看到很多信息,包括 ElasticSearch 版本、JVM 参数、节点名称、集群名称等。等到出现 started 字样,说明启动成功。按 Ctrl+C 停掉,再改用后台方式启动:
sudo -u esuser /opt/elasticsearch-7.17.22/bin/elasticsearch -d -p /tmp/es.pid-d 表示守护进程方式,-p 把进程号写到文件里。以后想停止节点,可以用kill $(cat /tmp/es.pid)。验证节点是否存活,最直接的办法是 curl 一下:
curl http://localhost:9200正常情况下会返回一段 JSON,包含 name、cluster_name、version 等信息。再检查集群健康状态:
curl http://localhost:9200/_cluster/health?pretty返回的 status 如果是 green,说明主分片和副本都分配成功;如果是 yellow,说明主分片没问题但副本没分配,单节点出现 yellow 是正常的,因为你只有一个节点,副本没法放;如果是 red,那就要小心了,说明有主分片都没分配,得看日志排查。
4. 开机自启与服务化:用 systemd 管起来
手动敲命令启动适合临时测试,真正要长时间运行,还是要做成 systemd 服务,否则机器重启后 ES 不会自动起来,某个服务挂了你也不知道。
4.1 编写 service 单元文件
Ubuntu 18.04 使用 systemd,服务文件放在 /etc/systemd/system/elasticsearch.service。一个可用的配置文件如下:
[Unit] Description=Elasticsearch After=network.target [Service] Type=simple User=esuser Group=esuser LimitNOFILE=65535 Restart=always RestartSec=10 ExecStart=/opt/elasticsearch-7.17.22/bin/elasticsearch -d -p /tmp/es.pid ExecStop=/bin/kill $(cat /tmp/es.pid) [Install] WantedBy=multi-user.target这里有几个细节:User 和 Group 指定成 esuser,确保进程不以 root 运行。LimitNOFILE 设置打开文件数上限,之前提到过,这个值在 systemd 环境下必须在 service 文件里单独设,光改 limits.conf 没用。Restart=always 表示进程异常退出后自动拉起,RestartSec 是重启间隔,防止 ES 启动失败时无限循环快速重启。
写完文件后执行:
systemctl daemon-reload systemctl enable elasticsearch systemctl start elasticsearch systemctl status elasticsearch看 status 输出里的 Active 字段是不是 active (running)。如果启动失败,不要反复 restart,直接看日志:
journalctl -u elasticsearch -n 200日志里会明确告诉你失败原因,权限不对、配置文件语法错误、端口被占用这些都能看到。
4.2 目录权限和日志查看
很多人第一次配置 systemd 时遇到 Permission denied 报错,第一反应是去改 service 文件的权限,其实方向搞反了。最常见原因是 /data/es-data 目录的所有者不是 esuser,你如果用 root 解压 tar 包再直接改配置,数据目录很可能还是 root 所有。执行一下 chown -R esuser:esuser /data 就好。
日志文件的位置在 path.logs 配置的目录下,默认文件名是 集群名.log。除了看 journalctl,ES 自己的日志是排查问题的第一手资料,里面的异常栈会告诉你具体是哪个环节出了问题。我把查看日志的命令记成 alias,比如alias eslog='tail -f /data/es-logs/es-prod.log',排查起来会快很多。
5. 常见问题与排查实战
这部分是实打实的踩坑记录。我在 Ubuntu 18.04 上部署 ES 的这几年,遇到的高频问题基本都集中在下面这几类,整理成一个速查表,方便你直接对照。
5.1 高频报错速查表
| 报错信息 | 原因 | 解决办法 |
|---|---|---|
| max virtual memory areas vm.max_map_count [65530] is too low | 内核参数不足 | sysctl -w vm.max_map_count=262144 并写入 /etc/sysctl.conf |
| max file descriptors [4096] for elasticsearch process is too low | 文件描述符限制 | 在 limits.conf 和 service 文件里设置 65535 |
| memory locking requested but mlockall failed | 锁内存失败 | 给 esuser 设置 memlock unlimited,或者关掉 bootstrap.memory_lock |
| data path is locked by another process | 数据目录被占用 | 检查是否有残留进程,ps -ef 找到旧进程 kill 掉 |
| Validation Failed: 1: no nodes found for {cluster_name} | 节点之间无法发现 | 检查 discovery.seed_hosts 的 IP、端口、防火墙 |
| failed to send join request to master | 节点名称冲突或网络不通 | 确认 node.name 唯一,检查 9300 端口连通性 |
| not all nodes joined the cluster | 初始 master 配置不对 | 只在第一个节点配置 cluster.initial_master_nodes,且只能用于首次启动 |
| java.lang.IllegalArgumentException: node.name must not be empty | 配置没读取到 | 确认 elasticsearch.yml 不是全注释状态,检查启动目录 |
这里我最想提醒的是 "data path is locked by another process" 这个报错。很多人明明没启动 ES,却报数据目录被锁,原因是上次用 kill -9 强制杀掉了进程,文件锁没释放干净。解决办法是先查进程再删锁文件,不要直接把整个 data 目录删了,否则数据就没了。
5.2 实战案例:一次磁盘打满带来的集群故障
有一段时间我的三节点集群突然大量报错,写入请求全部返回 403,索引状态变成 read_only_allow_delete。查了半天才发现是磁盘使用率超过了默认高水位线 85%,ES 为了自我保护,自动把索引切成了只读模式。
这个机制很多人不了解,以为是权限问题。处理分三步:先把大索引删除或者清理磁盘,腾出空间;然后手动解除只读限制:
curl -XPUT 'http://localhost:9200/_all/_settings' \ -H 'Content-Type: application/json' \ -d '{"index.blocks.read_only_allow_delete": null}'最后检查 _cluster/health,确认分片重新分配完成。这个案例说明一件事:ES 的自我保护机制是一把双刃剑,它避免了在磁盘写满时出现更严重的数据损坏,但也可能让你在第一时间误判方向。遇到这类问题时,先看磁盘再调配置,不要一上来就重启节点。
5.3 集群模式下的几个配置细节
如果你搭的是三节点集群,每个节点的 elasticsearch.yml 里 node.name 必须不同,比如 node-1、node-2、node-3。cluster.name 三个节点保持一致。data 目录各自独立。千万别把三个节点的 data 目录指向同一个路径,那样会互相锁死,后果就是启动一个之后,另外两个全部报 data path is locked。
cluster.initial_master_nodes 是新手最容易搞错的配置。它只在集群第一次启动的时候起作用,用来选出一个初始 master。正确做法是只在每个节点的配置里都列出初始 master 候选,比如三个节点的名字都写上,然后同一时间启动所有节点。如果集群已经形成,再重启节点时没必要动这个配置;你改了反而可能触发 split brain 相关的问题。
另外,三个节点最好是同时启动,不要让 node-1 先跑起来再启动另外两个,虽然也能形成集群,但可能出现发现超时,报错日志里全是 join 失败的信息。
5.4 安全认证和端口保护的建议
ES 7.x 默认没有开启安全认证,也就是说只要 network.host 设置为 0.0.0.0,任何人都能通过 9200 端口访问你的数据。我见过不止一个团队把 ES 部署在公网服务器上,几天后数据就被删光了,原因就是没做任何访问控制。
最轻量的做法是用防火墙限制来源 IP,只有内网网段能访问。稍微重一点的做法是开启 x-pack 安全功能,创建用户和密码,但这需要配置证书,首次上手有一定成本。如果是 Ubuntu 18.04 的测试环境,至少要做到:不用 root 跑服务、9200 端口不暴露公网、不给 ES 配置外网 IP。这三条做到,已经能挡住绝大多数攻击。
如果你使用的是 8.x 版本,安全认证默认开启,启动时控制台会打印初始密码,第一次登录后要尽快修改。很多刚从 7.x 迁移过来的人不适应这个变化,启动后 curl 一下发现返回 401 就以为装坏了,其实不是,只是需要先通过认证。
最后再分享两个我自己常用的技巧
先说配置批量同步。搭三节点集群时,不可能每个节点都手动去改 elasticsearch.yml。我的习惯是把 node-1 配好,然后把除 node.name 之外的配置作为模板,再用 sed 替换节点名批量生成。比如:
sed 's/node-1/node-2/' /opt/elasticsearch-7.17.22/config/elasticsearch.yml > /tmp/es-node2.yml这样能大幅减少配置错误,尤其是 cluster.name 或者 path 目录写错这种低级问题。
再说测试环境快速重置。如果你只是练习,搞坏了想重来,不要删数据目录然后重建,直接把整个 /opt/elasticsearch-7.17.22 目录删了重新解压会更快。程序目录、数据目录分离的意义就在这里,重装程序不影响数据。反过来说,如果你就是想清空所有数据重新开始,那就只清 data 目录,程序目录保留,启动后它会自动重建空索引结构。
Ubuntu 18.04 上装 ElasticSearch 本身不难,难的是把系统参数、JVM 配置、集群发现这几件事一次都想清楚。把这篇文章里提到的内容过一遍,你至少能避开我踩过的八成坑。装好之后,下一步就可以考虑接 Kibana 做可视化,或者配置 Beats 采集日志,那是另一个话题了。