CentOS 7 单机部署 Elasticsearch 7.17.29:启动报错排查与 CRUD 验证

为什么选 7.17.29 这个版本

Elasticsearch 8.x 默认开启安全认证、强制 TLS,单机快速验证时配置成本不低。7.17 是 7.x 的最后一个功能维护分支,官方仍在提供补丁版本,7.17.29 属于该分支较新的一个。对只想在单台 CentOS 7 机器上跑通搜索功能、又不打算引入证书体系的场景来说,7.17.x 是相对省事的选择。

需要提前说清楚一点:7.17.x 已经进入维护阶段,新项目如果没有历史包袱,建议直接评估 8.x。本文的场景是"已有的 CentOS 7 环境 + 需要快速验证 ES 能力",所以选 7.17.29。

环境信息如下:

项目 内容
操作系统 CentOS 7.9 x86_64
内存 4 GB
CPU 2 核
JDK Elasticsearch 自带 JDK(解压包内置)
ES 版本 7.17.29

下载与目录规划

Elasticsearch 官方提供 tar.gz 和 rpm 两种分发方式。rpm 会注册 systemd 服务,但目录结构固定;tar.gz 更适合自定义路径。这里用 tar.gz。

bash 复制代码
cd /opt
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.29-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.29-linux-x86_64.tar.gz.sha512
shasum -a 512 -c elasticsearch-7.17.29-linux-x86_64.tar.gz.sha512

校验通过后再解压:

bash 复制代码
tar -xzf elasticsearch-7.17.29-linux-x86_64.tar.gz
mv elasticsearch-7.17.29 /usr/local/elasticsearch

目录规划上,我把数据目录和日志目录单独拆出来,方便后续备份和清理:

bash 复制代码
mkdir -p /data/es/data /data/es/logs
chown -R es:es /data/es

专用用户和系统参数

Elasticsearch 从 2.x 起就禁止以 root 身份启动,这不是可选项,是硬性检查。所以先建一个专用用户:

bash 复制代码
useradd es
chown -R es:es /usr/local/elasticsearch

真正容易让服务起不来的,是两个系统级参数。

第一个是 vm.max_map_count。ES 的 Lucene 段文件使用 mmap 方式读取,默认值 65530 在高写入场景下会触发 max virtual memory areas vm.max_map_count [65530] is too low 报错。永久生效要写进 sysctl:

bash 复制代码
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p

第二个是文件句柄数。ES 需要同时打开大量文件,默认 1024 明显不够。修改 /etc/security/limits.conf:

bash 复制代码
es soft nofile 65536
es hard nofile 65536
es soft nproc  4096
es hard nproc  4096

改完之后,用 su - es 重新登录再用 ulimit -n 验证,否则当前 shell 里还是旧值。这一点我实际遇到过------直接 su es 不加载登录环境,limits 不生效,得用 su - es。

配置文件改动

编辑 /usr/local/elasticsearch/config/elasticsearch.yml,单机场景主要改这几项:

yaml 复制代码
cluster.name: es-single
node.name: node-1
path.data: /data/es/data
path.logs: /data/es/logs
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node

几个点值得展开说。

network.host 设成 0.0.0.0 是为了让外部能访问。如果只写 localhost,那只有本机能连。这里要注意:一旦 network.host 不是回环地址,ES 会自动触发生产模式检查(bootstrap checks),很多启动报错就是这一步冒出来的。

discovery.type: single-node 是 7.x 单机部署的关键。不写这个,节点会尝试做集群选主,单节点环境下可能长期处于 red 或者反复重试。设成 single-node 后,ES 跳过选主流程直接进入可用状态。

path.data 和 path.logs 指向刚才单独创建的目录,注意属主必须是 es 用户,否则启动时会报权限错误。

启动报错排查

第一次启动我用前台方式跑,方便直接看日志:

bash 复制代码
su - es
cd /usr/local/elasticsearch
./bin/elasticsearch

报错一:bootstrap checks failed

日志里出现类似内容:

复制代码
ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

这个就是前面提到的 vm.max_map_count 没生效。确认方式:

bash 复制代码
sysctl vm.max_map_count
cat /proc/sys/vm/max_map_count

如果输出还是 65530,说明 sysctl -p 没执行或者写错了文件。改完再启动即可。这个报错本身很直白,日志已经把要改的值写在里面了,照着改就行。

报错二:JDK 版本问题

另一类常见报错和 Java 有关。7.17.x 官方 tar.gz 包里自带 JDK,正常情况不需要系统装 Java。但如果机器上设置了 JAVA_HOME 指向一个低版本 JDK(比如 JDK 8),ES 可能会用错。

判断方式:

bash 复制代码
echo $JAVA_HOME
./bin/elasticsearch -V

7.17.x 要求 JDK 11 及以上。如果 JAVA_HOME 指向 JDK 8,启动会报 Unsupported class file major version 之类。解决办法是 unset 掉 JAVA_HOME,让 ES 用自带的 JDK:

bash 复制代码
unset JAVA_HOME

或者在 bin/elasticsearch-env 里显式指定。我倾向于直接 unset,改动最小。

这里补充一句:我没有在 CentOS 7 上测过 ES 8.x 自带 JDK 与系统 JDK 冲突的具体表现,不同小版本行为可能有差异,如果你用的是 8.x,建议单独查对应版本的 release notes。

启动成功的判断

前台启动看到类似输出就算起来了:

复制代码
[INFO ][o.e.n.Node] [node-1] started

新开一个终端验证端口:

bash 复制代码
curl -X GET "localhost:9200/?pretty"

返回里能看到 "version" : { "number" : "7.17.29" } 和 "tagline" : "You Know, for Search",说明服务正常。

【踩坑提醒】如果 curl 返回 Connection refused,先确认 ES 进程还在不在(前台方式关掉终端进程就没了),再看 network.host 是否配置正确。后台运行可以加 -d -p pid 参数,或者自己写 systemd unit。

CRUD 验证

服务起来之后,用 curl 走一遍增删改查,确认读写链路通。下面用 book 索引做示例。

创建索引

bash 复制代码
curl -X PUT "localhost:9200/book?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  }
}'

单机场景把副本数设成 0。默认是 1,单节点下副本分片无法分配,集群健康状态会一直是 yellow。设成 0 后就是 green。

【关键结论】单机部署时 number_of_replicas 设为 0,否则健康状态永远不是 green。这不是故障,是分片分配机制决定的。

写入文档

bash 复制代码
curl -X POST "localhost:9200/book/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "title": "Elasticsearch 实战",
  "author": "张三",
  "price": 59.9,
  "publish_date": "2024-01-15"
}'

返回里 result 字段是 created,_version 是 1。再写一条 id 为 2 的:

bash 复制代码
curl -X POST "localhost:9200/book/_doc/2?pretty" -H 'Content-Type: application/json' -d'
{
  "title": "Python 后端开发",
  "author": "李四",
  "price": 79.0,
  "publish_date": "2024-03-20"
}'

查询文档

按 id 直接取:

bash 复制代码
curl -X GET "localhost:9200/book/_doc/1?pretty"

用 _search 做条件查询:

bash 复制代码
curl -X GET "localhost:9200/book/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "title": "Elasticsearch"
    }
  }
}'

返回的 hits.total.value 是 1,hits.hits[0]._source.title 就是刚才写的内容。这里注意 match 会对中文做分词,如果用的是默认分词器,中文是按单字切的。"Elasticsearch" 这种英文词能正常匹配。

更新文档

部分更新用 _update:

bash 复制代码
curl -X POST "localhost:9200/book/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 49.9
  }
}'

返回 result 是 updated,_version 变成 2。_update 只改指定字段,其他字段保留。如果直接用 PUT /book/_doc/1 覆盖,会把没写的字段清掉,这个区别要留意。

删除文档和索引

删文档:

bash 复制代码
curl -X DELETE "localhost:9200/book/_doc/2?pretty"

删索引:

bash 复制代码
curl -X DELETE "localhost:9200/book?pretty"

删索引是不可逆操作,会连同数据一起清掉。生产环境建议先做快照。

绑定固定公网地址

前面 network.host: 0.0.0.0 只是让 ES 监听所有网卡,能不能从公网访问还取决于两件事:云服务商的安全组,以及系统防火墙。

防火墙放行

CentOS 7 默认用 firewalld。放行 9200:

bash 复制代码
firewall-cmd --zone=public --add-port=9200/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-ports

最后一条能列出 9200/tcp 就说明生效了。

如果机器用的是 iptables 而不是 firewalld,规则写法不同,这里不展开,按实际环境处理。

验证公网连通

从外部机器访问:

bash 复制代码
curl -X GET "公网IP:9200/?pretty"

如果卡住不动,通常是安全组没开。如果立刻返回 Connection refused,多半是 ES 没监听在那个网卡上,回去看 network.host。如果返回 No route to host,检查系统防火墙。

【注意】把 9200 直接暴露到公网是有安全风险的。7.17.x 默认没有认证,任何人拿到地址都能读写甚至删索引。如果只是临时验证,验证完记得关掉端口;如果要长期对外,至少加上 X-Pack 基础认证或者前面挂一层 Nginx 做访问控制。这一点在 8.x 里默认就开启了认证,7.x 需要手动配置。

固定地址的另一种做法

如果机器有多个网卡,想让 ES 只监听其中一个固定 IP,可以把 network.host 写成那个具体地址而不是 0.0.0.0:

yaml 复制代码
network.host: 192.168.1.100

这样 ES 只绑这一个网卡,减少暴露面。缺点是 IP 变了就得改配置。

后台运行与开机自启

前台跑只是调试方便,实际用要放后台。tar.gz 方式没有自带 systemd unit,需要自己写一个。放在 /etc/systemd/system/elasticsearch.service:

ini 复制代码
[Unit]
Description=Elasticsearch
After=network.target

[Service]
Type=simple
User=es
Group=es
Environment=ES_HOME=/usr/local/elasticsearch
Environment=ES_PATH_CONF=/usr/local/elasticsearch/config
ExecStart=/usr/local/elasticsearch/bin/elasticsearch
Restart=on-failure

[Install]
WantedBy=multi-user.target

然后:

bash 复制代码
systemctl daemon-reload
systemctl enable elasticsearch
systemctl start elasticsearch
systemctl status elasticsearch

【踩坑提醒】用 systemd 启动时,vm.max_map_count 这些系统参数必须在 systemd 之前就配置好。systemd 不会读取用户的 limits.conf,如果遇到句柄数报错,可能需要额外在 unit 文件里加 LimitNOFILE=65536。这一点和直接命令行启动的行为不一样。

收尾

整个流程走下来,真正会卡住的地方集中在三处:系统参数(vm.max_map_count、文件句柄数)、专用用户和目录权限、以及 network.host 改成非回环后触发的 bootstrap checks。CRUD 部分反而最简单,curl 几条命令就能验证。

有一点需要强调:7.17.x 默认无认证,绑定公网地址前一定要想清楚访问控制怎么做。临时验证就验证完关端口,长期用就老老实实配认证或者加反向代理。这不是可以"先跑起来再说"的事。

如果后续要做数据持久化和备份,可以研究一下 snapshot API 配合共享存储;如果要做中文搜索,默认分词器基本不够用,得引入 IK 之类的插件------这两块和本文的单机部署是两个独立话题,这里就不展开了。

相关推荐
SunShaoLu1 小时前
流程图工具怎么选:5 款产品的技术对比与选型实践
人工智能·职场和发展·流程图·效率工具
飞鸟真人1 小时前
AI应用入门(三)多模型路由与护栏问题
人工智能·ai·ai agent
回眸&啤酒鸭1 小时前
【回眸】HireKey 智能招聘全流程应用场景
开发语言·人工智能·python
博纬智能RFID1 小时前
园区多个关键卡口:如何用RFID门禁做好人员进出管控?
人工智能·物联网
175******631731 小时前
深度解读Work Agent长程任务执行机制
人工智能
一木 之林1 小时前
微信小程序开发全攻略·文章版|01 入门与环境搭建
人工智能·学习·计算机视觉·微信小程序·notepad++
迅为电子1 小时前
【迅为RK3588开发板+RK1828】交通监管例程:四宫格检测·目标跟踪·车牌识别·事故巡检
人工智能·计算机视觉·目标跟踪·rk3588开发板
归秋1421 小时前
Work Agent长程任务能力深度解读
大数据·人工智能
China_Yanhy1 小时前
AI Agent 实习生工作日记 — Day 2
人工智能