为什么选 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 之类的插件------这两块和本文的单机部署是两个独立话题,这里就不展开了。