ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Elasticsearch 安装教程:Linux、Docker 与生产调优避坑

Elasticsearch 安装教程:Linux、Docker 与生产调优避坑 1. 别急着敲命令先把安装位置和版本定下来Elasticsearch 这个名字在搜索、日志、可观测性这几个圈子里出现频率太高了但真到自己动手装的时候很多人第一步就走偏。我见过太多同事拿到一台机器就wget一个压缩包解压然后一路报错从内核参数一路改到 JVM 内存最后两个小时过去服务还没起来。ES 安装教程这类内容网上遍地都是但大多是复制粘贴的命令清单很少有人把为什么这么装讲透。这篇东西我想换个写法从选型开始把每一步的动机、参数的计算依据、以及我在真实环境里踩过的坑完整地摊开讲一遍。这篇文章适合三类人看完全没碰过 Elasticsearch、想在自己机器上跑一个来练手的新手需要给公司内网搭一套日志检索或者业务搜索、但对 Linux 系统调优不熟的后端同学以及那些装完能跑、但不清楚自己配置有没有留隐患、想回头补课的人。核心关键词就三个Elasticsearch、ES、安装教程所有内容都围绕怎么把它稳稳当当装起来这件事展开不扯远的。1.1 三种安装路径先想清楚你要哪一种装 ES 大致有三条路官方 tar 压缩包裸机部署、Docker 容器化部署、Windows 本地解压运行。这三者没有绝对优劣关键看你拿它干什么。如果你只是想在本机试试语法、跑几个_search请求那 Docker 一条命令最省事五分钟出结果玩完docker rm一删系统干干净净。如果是 Windows 办公电脑上做开发调试官方提供的 zip 包解压双击 bat 就能跑也不用装虚拟机。但如果你要部署到内网服务器、要长期跑、要调优、要考虑后续扩容成集群那就必须走 tar 包裸机部署这条路——因为容器里跑 ES 涉及内存锁定、文件句柄、数据卷挂载、内核参数透传一堆事出了问题排查链路太长而裸机部署的每一个参数你都能直接看到、直接改。还有一个容易被忽略的维度数据要不要保留。练手环境数据扔了无所谓生产环境的数据目录必须独立规划坚决不能跟系统盘、日志盘挤在一起。我见过有人把path.data放在/root下面结果磁盘写满直接把系统搞挂ES 进程和 sshd 一起罢工。所以选路径之前先问自己三个问题这是练手还是长期服务数据丢了要不要紧后面会不会加节点答案不同装法完全不一样。1.2 版本选型7.17 还是 8.xJDK 怎么绑版本这件事网上的搜索结果很容易把人带偏。有人搜elasticsearch 7.17.0下载有人问 8.x 的新特性还有人担心elasticsearch 9的某些功能是不是要企业版。我的建议很直接新项目一律上 7.17 之后的 8.x 稳定版除非你的下游组件比如某些同步工具、某些客户端 SDK明确不支持 8.x。为什么强调 7.17因为 8.0 开始 ES 默认开启了安全认证http.port不再是裸奔的首次启动会生成证书和一堆密钥文件。对新手来说这是劝退点但实际上这是好事——它逼你从一开始就把安全配好而不是等到上线前临时抱佛脚。很多人搜elasticsearch license担心收费问题这里说清楚基础功能Basic 授权是免费的包括搜索、聚合、索引、基础的安全认证个人和小团队用完全够需要付费的是部分高级特性你装完练手阶段根本碰不到不用纠结。JDK 这块有个必须记住的规则从 7.11 版本开始ES 的发行包里已经内置了 JDK你不需要自己装 Java也不建议用系统自带的 JDK 去覆盖它。官方 tar 包里有一个jdk目录启动脚本会自动用这个。为什么这么做因为 ES 对 JVM 版本和 GC 行为很敏感官方绑定 JDK 是为了避免你换了别的 JDK 导致堆外内存行为不一致这种玄学问题。所以看到JAVA_HOME相关的报错先别急着配环境变量先确认你解压的包里jdk目录在不在。有人为了省硬盘空间把jdk目录删了结果启动直接失败这种操作千万别干。数据库连接工具、es查询语法、es异步写入java这些热词背后反映的其实是同一件事大家装 ES 是为了让它接业务。既然是接业务版本就必须跟客户端对齐。Java 项目用RestHighLevelClient的老代码配 7.x 最稳新项目用 8.x 的ElasticsearchClient那就装 8.x。装之前先去翻一眼你项目里的客户端依赖版本比什么攻略都管用。2. 系统层面的准备工作跳过这步后面全是坑很多教程直接从解压开始讲这是不负责任的。ES 是个吃资源的主它对操作系统的要求写在官方文档里但文档写得比较散。我把这些要求归拢成两类内核参数和用户权限。这两块没弄好你压缩包解压得再漂亮启动脚本跑三秒就给你甩一堆bootstrap checks failed。先说清楚为什么要调。ES 底层用 Lucene 做索引索引文件通过内存映射mmap的方式读进内存一个索引分片会占用大量的内存映射区域操作系统对单个进程能创建的内存映射数量是有上限的默认值65530对 ES 来说远远不够所以第一件事就是把vm.max_map_count提上去。第二件事是文件句柄和进程数限制ES 要同时打开大量索引文件和网络连接ulimit -n默认 1024 也不够。这两条如果不提前配后面启动时一定会遇到那个经典报错max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]。看到它别慌就是参数没调回头补上重启即可。2.1 内核参数与资源限制命令和持久化都要做临时生效和永久生效是两回事很多人只做了临时那条重启机器后 ES 又起不来白白排查半天。下面这一组操作请成套执行。# 1. 内存映射区域数量262144 是官方建议值 sudo sysctl -w vm.max_map_count262144 # 2. 让它永久生效否则重启后失效 echo vm.max_map_count262144 | sudo tee -a /etc/sysctl.conf # 3. 验证是否写进去了 sysctl -p | grep max_map_count文件句柄和进程数走的是limits.conf。这里有个细节配置要同时写在/etc/security/limits.conf和/etc/security/limits.d/目录下并且要确认pam_limits.so被加载否则某些发行版上根本不生效。ES 官方的 systemd 服务文件里其实也带了LimitNOFILE65535但如果你是手动su切换用户启动那读的就是limits.conf两条路都得覆盖。# /etc/security/limits.conf 追加 esuser soft nofile 65535 esuser hard nofile 65535 esuser soft nproc 4096 esuser hard nproc 4096 esuser soft memlock unlimited esuser hard memlock unlimited最后那个memlock unlimited是给内存锁定用的跟后面bootstrap.memory_lock: true配套。如果你打算开启内存锁定强烈建议开这条不能不配否则启动时会报memory locking requested for elasticsearch process but memory is not locked。注意改完limits.conf后必须重新登录该用户才会生效su - esuser这种方式有时不会重新加载 PAM 限制最稳的做法是退出当前会话重新ssh登录。可以用ulimit -a确认max locked memory是不是 unlimited。2.2 目录规划、专用用户与权限ES 有个硬性规定不能用 root 用户启动。启动脚本里专门写了检查一旦检测到uid0就直接退出报错信息是can not run elasticsearch as root。这不是官方故意为难你而是出于安全考虑——ES 曾经爆出过远程代码执行漏洞用 root 跑等于把整台机器交出去。所以第一步是建一个专用系统用户建议去掉登录 shell减少被利用的面sudo useradd -r -m -s /bin/bash esuser # 确认创建成功 id esuser然后是目录规划。我的习惯是数据、日志、安装目录三者分离并且数据目录单独挂一块盘。三个目录的分工是这样的安装目录放程序文件升级时整个替换掉不影响数据数据目录是命根子备份策略围绕它做日志目录会疯狂增长必须能单独清理和轮转不能跟数据挤在一个分区里否则日志写满导致整个盘不可写ES 会直接进只读模式。sudo mkdir -p /opt/es/app /data/es/data /data/es/logs sudo chown -R esuser:esuser /opt/es /data/es sudo chmod 755 /opt/es /data/es假设你有一块独立的盘比如/dev/sdb那就先格式化成ext4或xfs再挂到/data。文件系统选哪个xfs 在大文件和高并发写入场景下表现更稳官方也比较推荐ext4 更通用运维熟悉度高。这个看团队习惯没有绝对答案但如果是新盘、新机器我一般直接上 xfs。提示/data/es/data这个目录的属主一定要是esuser。如果你是用 root 创建的目录但没改属主启动时会报AccessDeniedException日志里提示无法创建nodes目录这个报错比较容易误判成磁盘权限问题。3. Linux 环境下的完整安装流程准备工作做完接下来才是真正意义上的安装。我把这一节拆成四步下载校验、配置文件拆解、堆内存计算、启动验证。这四步里最容易出错的是第二步和第三步因为它们涉及大量参数而且很多参数有隐藏的联动关系。比如你改了network.host就会触发生产模式检查接着就要求你配discovery相关参数一环扣一环。先说一下下载渠道。官网elastic.co/downloads/elasticsearch页面能选版本和平台直接复制 tar.gz 的链接用wget拉就行。一定要校验 SHA512别嫌麻烦压缩包损坏导致解压后文件缺失、启动报一堆莫名错误的情况我遇到过不止一次校验一次能省你半小时。3.1 下载、校验与解压一步都别省cd /opt/es # 下载版本号按需替换 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.13.4-linux-x86_64.tar.gz wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.13.4-linux-x86_64.tar.gz.sha512 # 校验输出 OK 才算过 shasum -a 512 -c elasticsearch-8.13.4-linux-x86_64.tar.gz.sha512 # 解压 tar -zxvf elasticsearch-8.13.4-linux-x86_64.tar.gz # 把解压出来的目录改名为 current方便后续升级时做软链切换 mv elasticsearch-8.13.4 current # 属主交给专用用户 chown -R esuser:esuser /opt/es/current为什么要把目录改名成current这是为将来升级做铺垫。ES 的升级方式是下载新版本的完整包解压然后用滚动重启逐个替换节点。如果你用current做软链指向具体版本目录升级时只要把软链从current - 8.13.4改成current - 8.15.0配置文件和数据目录都不用动回滚也快。这个习惯在小规模部署里能省不少事。另外提醒一句解压完后先ls一下目录结构重点确认三样东西bin/elasticsearch启动脚本、config/elasticsearch.yml主配置、jdk/内置 JDK。这三样齐了后面的路就顺了。3.2 elasticsearch.yml 逐行拆解每个参数都有它的理由配置文件是最容易照抄抄错的地方。我不打算贴一份完整的 yml 让你复制而是把关键参数一条条讲清楚为什么这么配你自己再根据环境填。第一组是身份类参数cluster.name: prod-search # 集群名同一网段内集群名相同会互相发现务必唯一 node.name: node-1 # 节点名不配会自动生成但配了排查问题方便cluster.name这个参数要特别小心。默认值是elasticsearch如果你的内网里有两套 ES 集群都用默认值且网络互通它们会尝试组成一个集群节点数莫名其妙变多分片乱分配。生产环境第一件事就是把它改成有辨识度的名字比如带上业务线或者环境后缀。第二组是路径类参数一定要改成前面规划好的目录path.data: /data/es/data path.logs: /data/es/logs不改的话数据默认写在解压目录下的data/里升级时一替换目录数据就跟着没了。这是新手最容易犯的致命错误没有之一。第三组是网络类参数这组参数一改就会触发生产模式network.host: 0.0.0.0 # 监听所有网卡只允许本机访问就写 127.0.0.1 http.port: 9200 # REST 接口端口 transport.port: 9300 # 节点间通信端口这里有个关键机制需要理解ES 有两种启动模式开发模式和生产模式。当你把network.host设成0.0.0.0这种非回环地址时ES 认为你要对外提供服务会启动一整套bootstrap checks引导检查任何一项不通过就直接拒绝启动。这是保护机制防止你把一个没做安全配置的实例暴露到公网上。所以改了network.host之后discovery那组参数也必须一起配上这就是下一组。第四组是集群发现参数单节点和多节点配法不同# 单节点场景最简写法 discovery.type: single-node # 多节点集群场景 discovery.seed_hosts: [192.168.1.11:9300, 192.168.1.12:9300] cluster.initial_master_nodes: [node-1, node-2, node-3]cluster.initial_master_nodes这个参数有个非常经典的坑它只在集群第一次启动、还没有任何数据的时候需要。等集群形成、有了集群状态元数据之后这个参数就应该从配置里删掉或者注释掉否则节点重启时会报IllegalArgumentException: node is not in the initial master nodes list之类的错误。我见过有人重启节点起不来排查了半天就是忘了删这一行。还有一组安全相关的参数8.x 默认就开了xpack.security.enabled: true xpack.security.http.ssl.enabled: true xpack.security.transport.ssl.enabled: true首次启动时 ES 会自动生成 CA 证书和节点证书并打印elastic用户的初始密码。这个密码只打印一次一定要立刻复制下来存好丢了只能用bin/elasticsearch-reset-password -u elastic重置。3.3 堆内存到底给多少jvm.options 的计算过程堆内存配置是 ES 安装里技术含量最高的一块也是最能体现懂不懂的地方。配置文件在config/jvm.options.d/下建一个独立的.options文件最规范比如heap.options-Xms16g -Xmx16g为什么两行要写成一样的值因为堆内存动态调整会带来额外的 GC 开销和停顿生产环境追求的是稳定直接固定住最省心。这是第一原则。第二原则不超过物理内存的 50%且不超过 31GB。前半句好理解——ES 除了堆内存还要用堆外内存做文件缓存、mmap 索引文件堆外内存不够会导致频繁读磁盘性能断崖式下跌。留一半给系统是保守但稳妥的做法。一台 64G 内存的机器堆给 16G~24G 之间比较常见给到 32G 就开始吃紧了。后半句是个很多人不知道的细节JVM 在堆内存小于 32GB 时可以启用压缩普通对象指针Compressed Oops超过这个阈值指针会变成 8 字节反而更费内存。所以理论上堆越大越好是错的31GB 左右是那条收益曲线的拐点。官方文档里推荐的上限就是 31GB。具体怎么算给你一个我常用的对照表物理内存建议堆大小说明4 GB1 ~ 2 GB只够练手索引别放多8 GB4 GB小规模日志场景可用16 GB8 GB单节点中等负载的常见配置32 GB16 GB生产单节点入门档64 GB24 ~ 31 GB再往上堆收益很低考虑加节点128 GB 以上保持 31 GB加节点水平扩展比堆大更有效提示如果你前进方向里打算用向量检索dense_vector字段 kNN 查询堆内存和堆外内存都要比同等规模的普通搜索场景给得更宽裕因为向量索引构建阶段的内存占用相当可观。有人抱怨es向量检索时间太长很多时候根子不在查询语句而在安装阶段内存就给少了。改完堆内存别忘了bootstrap.memory_lockbootstrap.memory_lock: true它的作用是防止 JVM 堆被交换到磁盘swap上。一旦发生 swapES 的响应时间会从毫秒级跳到秒级而且是间歇性的排查起来非常折磨。开了这个参数后还要确认limits.conf里的memlock是 unlimited第 2.1 节配过了否则启动会报错。如果懒得配limits.conf用 systemd 管理服务时加LimitMEMLOCKinfinity也行但两种方式选一种覆盖到位。3.4 启动、看日志与首次连通性验证配置改完切换用户启动su - esuser cd /opt/es/current # 前台启动第一遍必须前台方便看日志 ./bin/elasticsearch第一遍一定要前台启动不要图省事加-d。因为 8.x 首次启动会生成证书、打印elastic用户密码和 enrollment token这些信息都在标准输出里后台跑容易漏掉。看到控制台打出message: started这类字样说明启动成功了。如果要用后台方式正确姿势是./bin/elasticsearch -d -p /data/es/es.pid # 之后通过 pid 文件优雅停止 kill $(cat /data/es/es.pid)-p参数指定 pid 文件路径这样 stop 的时候不用满世界ps -ef | grep elastic。直接kill -9也能停但强烈不建议因为 ES 有大量索引文件需要正常关闭刷盘强杀有极小概率导致分片需要恢复得不偿失。启动之后立刻做连通性验证# 8.x 需要带认证先带 -u 参数 curl -k -u elastic:你记下的密码 https://localhost:9200/?pretty正常返回的 JSON 里会有cluster_name、version.number、tagline这几项看到tagline: You Know, for Search就说明服务活了。如果连接被拒绝九成是network.host配成了别的地址或者启动没成功先回去看日志。如果返回 401是密码不对或者没带认证。如果返回 403多半是证书指纹没确认需要重新走一遍 enrollment 流程。日志文件的观察也有讲究。/data/es/logs/下会有几个文件重点看集群名.log里面按时间顺序记录了节点启动的每一步加载配置、初始化插件、恢复分片、加入集群。排查启动问题时永远从日志的最后 50 行往前看报错一定是最后抛出来的前面那些 INFO 大多是正常的流程记录。4. Windows 本地跑起来与 Docker 快速验证不是所有场景都需要上服务器。做开发的时候本机装一个 ES 来调试查询语句、验证索引结构效率高得多。这一节讲两种快速路径Windows 原生和 Docker 容器。这两条路的共同点是快共同的问题是别拿来跑生产。4.1 Windows 解压即用以及那几个必踩的坑Windows 上的安装简单到有点不真实去官网下载 zip 包解压到任意目录路径别带中文和空格然后双击bin\elasticsearch.bat。第一次运行会弹防火墙提示允许就行。之后浏览器打开https://localhost:9200会要求输入用户名密码用户名elastic密码在第一次启动时那个 cmd 窗口里打印出来了翻上去找。网上的搜索结果里windows启动elasticsearch这个关键词热度很高说明卡在 Windows 上的人不少。我把常见坑列一下第一个坑是路径带空格或中文。比如解压到C:\Program Files\或者D:\我的软件\启动脚本会因为路径解析问题直接失败。解压到D:\es\这种纯英文短路径最保险。第二个坑是内存不够。Windows 版默认在config\jvm.options里配了-Xms1g -Xmx1g如果你机器内存吃紧可以在同目录下建jvm.options.d\heap.options把它改小到512m但注意别小于 256m否则启动会失败。第三个坑是杀毒软件。ES 在启动时会创建大量小文件、开启大量网络监听某些安全软件会误判为异常行为并拦截表现为启动卡住不动。遇到这种先把实时防护关掉试试。第四个坑是 JDK 环境变量。前面说过 ES 自带 JDK但 Windows 上如果你系统里配了JAVA_HOME指向一个低版本 JDK启动脚本有时会优先用它导致版本不兼容报错。可以在启动前临时set JAVA_HOME清掉确认是不是这个原因。Windows 上还容易遇到端口占用。9200 被别的程序占了怎么办netstat -ano | findstr 9200找到 PID再到任务管理器里结束对应的进程。如果实在腾不出来改config\elasticsearch.yml里的http.port换成 9201 也行但记得同步改客户端的连接地址。4.2 Docker 一条命令拉起单节点Docker 路线的核心优势是环境隔离装坏了删容器重来不会污染宿主机。适合 CI 环境、临时验证、教学演示。docker run -d \ --name es-single \ -p 9200:9200 \ -p 9300:9300 \ -e discovery.typesingle-node \ -e ES_JAVA_OPTS-Xms1g -Xmx1g \ -e xpack.security.enabledfalse \ -v es-data:/usr/share/elasticsearch/data \ docker.elastic.co/elasticsearch/elasticsearch:8.13.4几个参数说明一下。discovery.typesingle-node是告诉它这是单节点跳过引导检查里关于集群发现的要求否则容器起不来。ES_JAVA_OPTS覆盖堆内存容器环境建议显式指定不然它会用默认值在内存小的机器上出事。xpack.security.enabledfalse是关掉认证方便本地调试——这一条在能连公网的机器上千万别开等于把服务裸奔在互联网上。数据卷es-data挂出来是为了容器删除后数据还在命名卷比绑定挂载省事Docker 自己管路径。这里有个必须强调的点Docker 里的 ES 依然受宿主机内核参数约束。vm.max_map_count是宿主机级别的容器内改不了。所以即使你用了 Docker第 2.1 节那个内核参数照样要在宿主机上配。很多人第一次用 Docker 跑 ES 就卡在这一步容器反复重启日志里还是那句max virtual memory areas vm.max_map_count [65530] is too low。另外docker desktop在 Windows 和 Mac 上是通过虚拟机跑的实际的内核参数要在 Docker Desktop 的设置里或者它背后的虚拟机里调。Mac 上比较麻烦一般用 Docker Desktop 自带的配置界面调资源限制内核参数得进它的虚拟机里改。这也是为什么我前面说练手可以、生产别用容器。4.3 从单机到三节点小集群练手单节点够用但只要你想验证副本分配、故障转移、跨节点查询这些行为单节点是看不出问题的——因为单节点上的副本分片永远分配不出去集群状态会一直是 yellow。这不是配置错了是物理上没有第二台机器放副本。想看到 green至少三节点。三节点的最小配置每个节点的elasticsearch.yml大致这样以 node-1 为例cluster.name: dev-cluster node.name: node-1 node.roles: [master, data, ingest] path.data: /data/es/data path.logs: /data/es/logs network.host: 192.168.1.11 http.port: 9200 transport.port: 9300 discovery.seed_hosts: [192.168.1.11:9300, 192.168.1.12:9300, 192.168.1.13:9300] cluster.initial_master_nodes: [node-1, node-2, node-3] bootstrap.memory_lock: truenode.roles这个参数值得展开说。ES 7.9 之后引入了节点的角色分离master角色负责集群状态管理data负责存数据ingest负责预处理管道。小集群里一般三个角色都留但如果集群规模上去了强烈建议把 master 角色单独拆出来做专属 master 节点因为数据节点压力大的时候会影响集群状态更新的响应速度进而让整个集群不稳定。节点启动顺序上我的经验是先把所有 master-eligible 节点同时启动等集群形成后再启>curl -k -u elastic:密码 https://192.168.1.11:9200/_cluster/health?pretty返回里的number_of_nodes应该是 3status应该是green。如果还是yellow用_cluster/allocation/explain接口查一下分片为什么没分配通常会给出很具体的原因比如磁盘水位超限、节点角色不匹配等。5. 装完不等于能用安全配置与生产必做项服务起来了不等于可以交付了。我见过太多案例ES 装完丢在内网没有任何认证半年后被人拿走数据。8.x 虽然默认开了安全但很多人图省事在配置里给它关掉了这个习惯非常危险。这一节讲两块安全配置怎么配、系统层面的稳定性开关怎么开。5.1 开启账号密码与传输加密如果你装的是 8.x 且没关安全那么默认就是开着的证书和密码在首次启动时已经生成了。要做的事情是把这套证书和凭据管理起来而不是每次启动重新生成。关于证书简单说清楚它的组成ES 用一套 CA 签发的证书链config/certs/下会生成ca.crt、ca.key、节点的http.crt/http.key、transport.crt/transport.key。ca.key是私钥权限要收紧绝对不能外传ca.crt是公钥证书客户端连接时需要它来做校验。生产环境里建议用公司统一的 CA 重新签发一套方便证书轮换和集中管理。密码这块有几个内置用户要记住elastic是超级用户权限最大也最危险日常操作不要直接用它而是建一个业务专用账号授予最小必要权限。创建用户的接口是_security/user/可以用 Kibana 的界面点也可以直接调 APIcurl -k -u elastic:密码 -X POST https://localhost:9200/_security/user/app_user \ -H Content-Type: application/json -d { password: 换个强密码, roles: [app_read_write], full_name: 业务写入账号 }角色也要按需建不要图省事给superuser。最小权限原则在 ES 里尤其重要因为一个索引的写权限就足够覆盖掉全部数据了。如果你是 7.x或者手动把 8.x 的安全关了那就要手动开启xpack.security.enabled: true xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12 xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: certs/http.p12然后用bin/elasticsearch-certutil生成证书用bin/elasticsearch-setup-passwords interactive交互式设置所有内置用户的密码。整个过程稍微繁琐但比裸奔强一万倍。注意transport.ssl.verification_mode如果设成none会跳过证书校验虽然能连通但等于放弃了加密的意义生产环境必须用certificate或full。这个参数是很多连不上集群问题的元凶——排查时临时改成none能通、改回来不通就说明证书配错了。5.2 内存锁定、交换分区与熔断器这一节讲的是稳定性开关配了之后 ES 在高负载下不容易雪崩。交换分区这块最彻底的做法是让 ES 完全不用 swap。前面配的bootstrap.memory_lock: true锁住了 JVM 堆但堆外内存还是可能被换出去。更激进的做法是把宿主机的 swap 关掉或者把vm.swappiness调到 1echo vm.swappiness1 | sudo tee -a /etc/sysctl.conf sudo sysctl -pswappiness是 0~100 的值越大越倾向于换出内存。设成 1 的意思是除非万不得已否则别换。不要设成 0因为在内存真正见底的时候完全不换出可能导致 OOM Killer 直接杀掉进程比慢一点更糟。熔断器是 ES 的自我保护机制。它监控 JVM 堆内存的使用量当某个操作比如一个巨大的聚合查询占用的内存超过阈值时主动抛异常拒绝避免整个节点 OOM。默认阈值是 95%通常不用改但如果你想更保守可以在elasticsearch.yml里调indices.breaker.total.limit: 70% indices.breaker.fielddata.limit: 40% indices.breaker.request.limit: 40%磁盘水位也要配。ES 默认在磁盘使用超过 85% 时不再往该节点分配新分片超过 90% 时尝试把分片挪走超过 95% 时索引变成只读。对小容量磁盘来说这套默认值偏激进可以调cluster.routing.allocation.disk.watermark.low: 80% cluster.routing.allocation.disk.watermark.high: 90% cluster.routing.allocation.disk.watermark.flood_stage: 95%但调阈值只是缓解不是解决。真正的解法是加盘或者清理旧索引用 ILM索引生命周期管理策略自动滚动删除。见过有人把flood_stage调到 98%结果磁盘还剩 2% 的时候 ES 疯狂报错系统盘也满了最后只能强制删数据救场。6. 上线前的验证清单与故障速查装完、配完最后一步是验收。验收不是打开浏览器看到页面就完事而是要有几个明确的检查项确认这个实例真的能扛事。我整理了一份自检清单和一张报错速查表你照着走一遍基本能覆盖 90% 的初期问题。6.1 五步健康自检第一步查集群健康。用_cluster/health接口重点看status是不是 green、number_of_nodes对不对、unassigned_shards是不是 0。yellow 在单节点上是正常的多节点上出现 yellow 就要查原因。第二步查节点信息。用_nodes/stats看几个关键指标jvm.mem.heap_used_percent是否长期高于 75%高于说明堆偏小、indices.fielddata.memory_size_in_bytes是不是很大大说明有聚合在滥用 fielddata、fs.total.available_in_bytes磁盘剩余。这些指标看一眼心里就有数了。第三步写入读取闭环测试。别只看健康状态实际建个索引写几条数据再查出来curl -k -u elastic:密码 -X PUT https://localhost:9200/test_idx -H Content-Type: application/json -d { settings: { number_of_shards: 1, number_of_replicas: 0 } } curl -k -u elastic:密码 -X POST https://localhost:9200/test_idx/_doc/1 -H Content-Type: application/json -d { title: hello es, ts: 2024-01-01 } curl -k -u elastic:密码 https://localhost:9200/test_idx/_search?qhellopretty走通这套说明写链路和读链路都正常。测完记得把test_idx删掉别留在生产环境里。第四步压一下。不用专业压测工具用curl循环发几百个请求看响应时间也行。重点观察有没有明显抖动——如果响应时间忽快忽慢大概率是 swap 没关干净回去查_nodes/stats里的jvm.mem.pools和系统的free -h。第五步重启一次。这一条最容易被跳过但价值最高。很多配置错误只有在重启后才会暴露比如前面提到的cluster.initial_master_nodes没删、limits.conf没生效、挂载点没配好自动挂载。重启一遍全部走通才算真的验收通过。6.2 常见报错速查表下面这张表是我这些年遇到频率最高的报错按出现概率从高到低排。报错信息关键词根本原因处理方式can not run elasticsearch as root用 root 启动了切换到专用用户或用--user方式启动max virtual memory areas vm.max_map_count [65530] is too low内核参数没配或没生效sysctl -w vm.max_map_count262144并写入/etc/sysctl.confmax file descriptors [4096] for elasticsearch process is too low句柄限制没生效配limits.conf重新登录用户使配置生效the default discovery settings are unsuitable for production use改了network.host但没配 discovery单节点加discovery.type: single-node集群配seed_hosts和initial_master_nodesmemory locking requested for elasticsearch process but memory is not locked开了bootstrap.memory_lock但 memlock 限制没放开limits.conf加memlock unlimited或 systemd 加LimitMEMLOCKinfinitynode is not in the initial master nodes list集群已成型后还留着initial_master_nodes注释掉该参数再启动java.lang.OutOfMemoryError: Java heap space堆内存给小了调jvm.options.d里的-Xms/-XmxAccessDeniedException: /data/es/data/nodes数据目录属主不对chown -R esuser:esuser /data/esPort 9200 already in use端口被占用ss -lntpcluster status is RED有主分片未分配_cluster/allocation/explain查具体原因常见是磁盘水位或节点掉线index is read-only, disk watermark exceeded磁盘超过flood_stage清理磁盘后调_settings解除只读长期靠 ILM 策略控制这张表建议存下来遇到报错先搜关键词对上能省下大量搜索时间。提示遇到不认识的报错最快的路径不是搜索引擎而是先看日志里紧挨着报错的那几行 WARN。ES 的日志设计得很好最终的 ERROR 往往只是结果真正的原因藏在它前面几行的 WARN 里。比如分片分配失败ERROR 只说失败但前面会有一条 WARN 写清楚因为磁盘水位超过阈值所以拒绝分配。7. 我在实际安装中踩过的那些坑前面讲的都是应该怎么做这一节讲我实际遇到的那些计划外的事算是给这份安装教程打个补丁。第一个坑跟时间有关。有次在三台机器上装集群配置文件一模一样但 node-3 死活加不进去日志显示它不断重试加入但每次都被拒绝。排查了一个多小时才发现是那台机器的时间比另外两台慢了四分钟导致集群选主时的任期判断出问题。集群对时间同步的要求比想象中高现在我做任何集群部署第一件事就是chronyc sources确认时间源正常比什么都管用。第二个坑跟磁盘有关。有个环境用的是云主机数据盘是网络存储我给path.data指过去之后发现写入性能极差索引速度只有本地盘的十分之一。原因是网络存储的 IOPS 和延迟跟本地 SSD 完全不是一个量级而 ES 对磁盘延迟极其敏感。结论就是ES 的数据盘必须用本地 SSD网络盘只能用来放备份。这个教训我后来写进了所有部署文档的首页。第三个坑跟内存锁定有关。配了bootstrap.memory_lock: truelimits.conf也改了ulimit -a看max locked memory确实是 unlimited但启动还是报内存锁定失败。最后发现是用的 systemd 启动服务而 systemd 服务有自己独立的一套LimitXXX配置它不走limits.conf需要在 service 文件里单独加LimitMEMLOCKinfinity。这个坑很隐蔽因为手动su启动是好的用 systemd 就失败容易让人以为是配置写错了。第四个坑跟升级有关。用软链方式部署之后升级新版本二进制替换了但配置文件没注意对比新版增加了一些新的必填项启动时报unknown setting。教训是升级前一定要把新旧版本的elasticsearch.yml拿 diff 工具过一遍尤其是大版本升级很多参数被废弃或者改名了照搬旧配置会出问题。第五个坑跟 JVM 参数有关。有一次为了省内存把堆调到 512m 跑一个日志场景前面几个月都正常数据量涨上去之后开始频繁 Full GC服务每隔几小时就卡顿几十秒。查jvm.mem.heap_used_percent发现长期在 80% 以上。堆内存的配置要留出余量按当前数据量的两到三倍估别按刚好够用来算。后来把堆提到 4G问题立刻消失。最后分享一个小习惯。每次装完 ES我都会在config/目录下放一个README.md写上这次部署的关键信息版本号、部署日期、数据目录路径、证书位置、管理员密码的存放位置不写密码本身、以及这份配置对应的是哪套环境。几个月后回头看这份随手写的记录能帮你省下大量翻文档的时间。装 ES 这件事命令本身不难难的是把一堆看起来无关的参数串成一套能长期稳定运行的配置。
返回列表