为什么选 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。
cd/optwgethttps://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.29-linux-x86_64.tar.gzwgethttps://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.29-linux-x86_64.tar.gz.sha512 shasum-a512-celasticsearch-7.17.29-linux-x86_64.tar.gz.sha512校验通过后再解压:
tar-xzfelasticsearch-7.17.29-linux-x86_64.tar.gzmvelasticsearch-7.17.29 /usr/local/elasticsearch目录规划上,我把数据目录和日志目录单独拆出来,方便后续备份和清理:
mkdir-p/data/es/data /data/es/logschown-Res:es /data/es专用用户和系统参数
Elasticsearch 从 2.x 起就禁止以 root 身份启动,这不是可选项,是硬性检查。所以先建一个专用用户:
useraddeschown-Res: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:
echo"vm.max_map_count=262144">>/etc/sysctl.confsysctl-p第二个是文件句柄数。ES 需要同时打开大量文件,默认 1024 明显不够。修改/etc/security/limits.conf:
es soft nofile65536es hard nofile65536es soft nproc4096es hard nproc4096改完之后,用su - es重新登录再用ulimit -n验证,否则当前 shell 里还是旧值。这一点我实际遇到过——直接su es不加载登录环境,limits 不生效,得用su - es。
配置文件改动
编辑/usr/local/elasticsearch/config/elasticsearch.yml,单机场景主要改这几项:
cluster.name:es-singlenode.name:node-1path.data:/data/es/datapath.logs:/data/es/logsnetwork.host:0.0.0.0http.port:9200discovery.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 用户,否则启动时会报权限错误。
启动报错排查
第一次启动我用前台方式跑,方便直接看日志:
su- escd/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没生效。确认方式:
sysctlvm.max_map_countcat/proc/sys/vm/max_map_count如果输出还是 65530,说明sysctl -p没执行或者写错了文件。改完再启动即可。这个报错本身很直白,日志已经把要改的值写在里面了,照着改就行。
报错二:JDK 版本问题
另一类常见报错和 Java 有关。7.17.x 官方 tar.gz 包里自带 JDK,正常情况不需要系统装 Java。但如果机器上设置了JAVA_HOME指向一个低版本 JDK(比如 JDK 8),ES 可能会用错。
判断方式:
echo$JAVA_HOME./bin/elasticsearch-V7.17.x 要求 JDK 11 及以上。如果JAVA_HOME指向 JDK 8,启动会报Unsupported class file major version之类。解决办法是 unset 掉JAVA_HOME,让 ES 用自带的 JDK:
unsetJAVA_HOME或者在bin/elasticsearch-env里显式指定。我倾向于直接 unset,改动最小。
这里补充一句:我没有在 CentOS 7 上测过 ES 8.x 自带 JDK 与系统 JDK 冲突的具体表现,不同小版本行为可能有差异,如果你用的是 8.x,建议单独查对应版本的 release notes。
启动成功的判断
前台启动看到类似输出就算起来了:
[INFO ][o.e.n.Node] [node-1] started新开一个终端验证端口:
curl-XGET"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索引做示例。
创建索引
curl-XPUT"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。这不是故障,是分片分配机制决定的。
写入文档
curl-XPOST"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 的:
curl-XPOST"localhost:9200/book/_doc/2?pretty"-H'Content-Type: application/json'-d' { "title": "Python 后端开发", "author": "李四", "price": 79.0, "publish_date": "2024-03-20" }'查询文档
按 id 直接取:
curl-XGET"localhost:9200/book/_doc/1?pretty"用_search做条件查询:
curl-XGET"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:
curl-XPOST"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覆盖,会把没写的字段清掉,这个区别要留意。
删除文档和索引
删文档:
curl-XDELETE"localhost:9200/book/_doc/2?pretty"删索引:
curl-XDELETE"localhost:9200/book?pretty"删索引是不可逆操作,会连同数据一起清掉。生产环境建议先做快照。
绑定固定公网地址
前面network.host: 0.0.0.0只是让 ES 监听所有网卡,能不能从公网访问还取决于两件事:云服务商的安全组,以及系统防火墙。
防火墙放行
CentOS 7 默认用 firewalld。放行 9200:
firewall-cmd--zone=public --add-port=9200/tcp--permanentfirewall-cmd--reloadfirewall-cmd --list-ports最后一条能列出9200/tcp就说明生效了。
如果机器用的是 iptables 而不是 firewalld,规则写法不同,这里不展开,按实际环境处理。
验证公网连通
从外部机器访问:
curl-XGET"公网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:
network.host:192.168.1.100这样 ES 只绑这一个网卡,减少暴露面。缺点是 IP 变了就得改配置。
后台运行与开机自启
前台跑只是调试方便,实际用要放后台。tar.gz 方式没有自带 systemd unit,需要自己写一个。放在/etc/systemd/system/elasticsearch.service:
[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然后:
systemctl daemon-reload systemctlenableelasticsearch 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 之类的插件——这两块和本文的单机部署是两个独立话题,这里就不展开了。