为什么选 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 GBCPU2 核JDKElasticsearch 自带 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报错。永久生效要写进 sysctlechovm.max_map_count262144/etc/sysctl.confsysctl-p第二个是文件句柄数。ES 需要同时打开大量文件默认 1024 明显不够。修改/etc/security/limits.confes 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 8ES 可能会用错。判断方式echo$JAVA_HOME./bin/elasticsearch-V7.17.x 要求 JDK 11 及以上。如果JAVA_HOME指向 JDK 8启动会报Unsupported class file major version之类。解决办法是 unset 掉JAVA_HOME让 ES 用自带的 JDKunsetJAVA_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-XGETlocalhost: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-XPUTlocalhost:9200/book?pretty-HContent-Type: application/json-d { settings: { number_of_shards: 1, number_of_replicas: 0 } }单机场景把副本数设成 0。默认是 1单节点下副本分片无法分配集群健康状态会一直是 yellow。设成 0 后就是 green。【关键结论】单机部署时number_of_replicas设为 0否则健康状态永远不是 green。这不是故障是分片分配机制决定的。写入文档curl-XPOSTlocalhost:9200/book/_doc/1?pretty-HContent-Type: application/json-d { title: Elasticsearch 实战, author: 张三, price: 59.9, publish_date: 2024-01-15 }返回里result字段是created_version是 1。再写一条 id 为 2 的curl-XPOSTlocalhost:9200/book/_doc/2?pretty-HContent-Type: application/json-d { title: Python 后端开发, author: 李四, price: 79.0, publish_date: 2024-03-20 }查询文档按 id 直接取curl-XGETlocalhost:9200/book/_doc/1?pretty用_search做条件查询curl-XGETlocalhost:9200/book/_search?pretty-HContent-Type: application/json-d { query: { match: { title: Elasticsearch } } }返回的hits.total.value是 1hits.hits[0]._source.title就是刚才写的内容。这里注意match会对中文做分词如果用的是默认分词器中文是按单字切的。“Elasticsearch” 这种英文词能正常匹配。更新文档部分更新用_updatecurl-XPOSTlocalhost:9200/book/_update/1?pretty-HContent-Type: application/json-d { doc: { price: 49.9 } }返回result是updated_version变成 2。_update只改指定字段其他字段保留。如果直接用PUT /book/_doc/1覆盖会把没写的字段清掉这个区别要留意。删除文档和索引删文档curl-XDELETElocalhost:9200/book/_doc/2?pretty删索引curl-XDELETElocalhost:9200/book?pretty删索引是不可逆操作会连同数据一起清掉。生产环境建议先做快照。绑定固定公网地址前面network.host: 0.0.0.0只是让 ES 监听所有网卡能不能从公网访问还取决于两件事云服务商的安全组以及系统防火墙。防火墙放行CentOS 7 默认用 firewalld。放行 9200firewall-cmd--zonepublic --add-port9200/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.0network.host:192.168.1.100这样 ES 只绑这一个网卡减少暴露面。缺点是 IP 变了就得改配置。后台运行与开机自启前台跑只是调试方便实际用要放后台。tar.gz 方式没有自带 systemd unit需要自己写一个。放在/etc/systemd/system/elasticsearch.service[Unit] DescriptionElasticsearch Afternetwork.target [Service] Typesimple Useres Groupes EnvironmentES_HOME/usr/local/elasticsearch EnvironmentES_PATH_CONF/usr/local/elasticsearch/config ExecStart/usr/local/elasticsearch/bin/elasticsearch Restarton-failure [Install] WantedBymulti-user.target然后systemctl daemon-reload systemctlenableelasticsearch systemctl start elasticsearch systemctl status elasticsearch【踩坑提醒】用 systemd 启动时vm.max_map_count这些系统参数必须在 systemd 之前就配置好。systemd 不会读取用户的 limits.conf如果遇到句柄数报错可能需要额外在 unit 文件里加LimitNOFILE65536。这一点和直接命令行启动的行为不一样。收尾整个流程走下来真正会卡住的地方集中在三处系统参数vm.max_map_count、文件句柄数、专用用户和目录权限、以及network.host改成非回环后触发的 bootstrap checks。CRUD 部分反而最简单curl 几条命令就能验证。有一点需要强调7.17.x 默认无认证绑定公网地址前一定要想清楚访问控制怎么做。临时验证就验证完关端口长期用就老老实实配认证或者加反向代理。这不是可以先跑起来再说的事。如果后续要做数据持久化和备份可以研究一下 snapshot API 配合共享存储如果要做中文搜索默认分词器基本不够用得引入 IK 之类的插件——这两块和本文的单机部署是两个独立话题这里就不展开了。