ARTICLE DETAIL

资讯详情

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

Elasticsearch 6.5.4三节点集群部署实战:从配置到排错全攻略

Elasticsearch 6.5.4三节点集群部署实战:从配置到排错全攻略 如果你还在为一个 6.5.4 版本的 elasticsearch 集群头疼那咱们基本是一路人新版本 8.x 的教程铺天盖地但生产环境里跑了两三年的老集群才是大多数公司真正在用的东西。这个版本用的还是 Zen Discovery 机制配置项和 7.x/8.x 差异不小很多人照着新教程配 6.x第一步就把 discovery 参数写错了。这篇把从环境准备、配置文件、三节点部署到常见报错排查的完整过程整理出来重点照顾第一次从单机转集群的读者也适合被线上集群问题折磨到半夜的同学当排查手册。按图文教程的节奏来写每到一个关键操作点终端输出和配置文件的核心差异都会贴出来能对着一步步操作。1. 先想清楚再动手6.5.4 版本的后台逻辑与集群角色规划1.1 为什么 6.x 系列至今还有大量存量部署先说个扎心的现实很多公司的核心业务系统用的还是 6.x 甚至 5.x 的 ES。不是大家不想升级而是升级成本被严重低估了——数据要迁移、客户端要适配、查询语法可能要改更别提 7.x 之后discovery.seed_hosts和 6.x 的discovery.zen.ping.unicast.hosts完全不兼容一不小心就连不上集群。所以 6.5.4 这种版本在可见的未来一段时间里还有大量存量项目要维护。这个版本本身也比较稳定6.5.4 是 6.x 中期的一个小版本修复了不少 6.0 到 6.4 阶段的坑像是分片分配慢、节点重启后未分配分片恢复不及时之类的问题都有明显改善。如果你的线上业务跑在 6.5.4 上除非有硬性需求否则确实没必要顶着风险盲升。另外多说一句现在网上能搜到不少“ES 9.4 部署”之类的新版教程但老版本项目的维护逻辑和新版是完全不同的。新版本教程默认你使用 Kubernetes、容器化部署、外加各种自动化编排这些在老集群里根本不适用。6.5.4 的集群部署核心还是在“三台独立服务器 手工配置 系统调优”这个框架下解决问题。1.2 节点角色分配master、data、ingest 到底怎么分ES 集群的最小组成单位是节点节点按角色划分在 6.5.4 里主要涉及三个角色master 候选节点、data 节点、ingest 节点。你可以在elasticsearch.yml里通过node.master和node.data控制前两类ingest 节点在 6.x 里也支持单独关掉。很多人第一次搭集群习惯把所有节点都配成node.master: true和node.data: true也就是所谓的“所有节点全能”。这种做法在小规模集群里问题不大三节点集群全部默认配置也能跑得挺稳毕竟 6.5.4 的默认行为就是每个节点都是 master 候选 data 节点。但只要集群规模起来就会发现一个尴尬问题master 节点除了要维护集群状态还要承担数据读写CPU 和内存一吃紧整个集群的稳定性都会受影响。我建议的分配方式是这样的集群规模master 候选节点data 节点ingest 节点3 节点3 个都参与选举3 个全部开启默认5 节点3 个5 个全部开启10 节点以上3 个10 个按需单独部署 2-3 个为什么 master 候选节点建议是奇数这里涉及一个选主的概念ES 集群的脑裂防护依赖discovery.zen.minimum_master_nodes这个参数它的推荐值等于可成为 master 的节点数 / 2 1。三节点集群全部参与选举公式算出来就是 2如果只有 2 个 master 候选节点公式算出来也是 2。所以奇数个 master 候选节点在发生网络分区时更容易保证“多数派”的确定性避免出现两个集群各自为政的情况。1.3 容量预估与分片规划的基础算法部署前还有个问题必须想清楚每个节点应该分配多少内存分片数怎么定6.5.4 里每个节点默认堆内存是 1GB这个值不调稍微上点流量就频繁 Full GC。关于堆内存有一条官方明确的建议不要超过物理内存的一半同时不要超过 32GB。为什么是 32GB因为 JVM 在堆内存小于 32GB 时会启用压缩指针技术对象引用占用更少空间一旦超过 32GB压缩指针失效同样大小的堆能装的对象反而变少性能不升反降。如果你的机器内存是 64GB建议堆设 31GB剩下的留给操作系统页缓存ES 查询时磁盘读的命中率会高很多。分片数则遵循一个经验值单分片容量控制在 30GB-50GB 以内。假设你有 500GB 数据副本数为 1实际存储量就是 1TB分片数建议 20-30 个左右。6.5.4 中每个节点的分片数如果过多master 节点维护集群状态的开销会直线上升这也是“节点数不多但集群很慢”的一个隐藏原因。2. 环境准备阶段最容易翻车的三个系统参数2.1 JDK 版本8u191 是硬门槛不是“装了 Java 就行”ES 6.5.4 官方要求 JDK 8这句话看着简单但坑比想象中多。生产环境遇到过几次同一个问题开发机上java -version显示的是 1.8但 ES 启动时直接报Unsupported major.minor version 52.0。这个报错的本质是“当前 Java 版本太旧无法识别新版 class 文件”但如果你确认 Java 8 已经装了大概率是 PATH 环境变量把别的 JDK 版本带进来了。还有一个隐藏条件ES 6.5.4 推荐使用 8u191 及以上版本。因为 8u191 之后JVM 对容器内存限制的识别比之前更准确某些 Linux 发行版上如果 JDK 版本太旧ES 启动时可能无法正确读取系统内存导致堆设置异常。所以环境准备第一步请确认java -version # 输出示例 # openjdk version 1.8.0_202 # OpenJDK Runtime Environment (build 1.8.0_202-b08)注意输出里的版本号必须包含1.8并且_后面的编号要大于等于 191。如果你机器上装了多个 JDK务必将JAVA_HOME指向 8u191 以上的那个并在/etc/profile或/etc/environment中固定好避免启动脚本在 PATH 里抓到错误版本。2.2 vm.max_map_count 和文件句柄两条必须提前处理的 sysctl没有调优过的 Linux 机器直接跑 ES 6.5.4启动日志里大概率会出现这样两行[1] max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536] [2] max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]先解释下这两行是什么意思。max file descriptors是进程能打开的最大文件句柄数ES 的每个分片、每个文件句柄、每个网络连接都会占用这个额度默认 4096 对数据库类应用来说完全不够早上高峰期分片一多进程直接报 “Too many open files”。vm.max_map_count则是系统允许创建的虚拟内存映射区数量ES 使用 Lucene 做底层存储会创建大量的 mmap 文件映射默认 65530 不够用。解决方式分两步。第一步修改/etc/sysctl.conf追加下面这行vm.max_map_count262144然后执行sysctl -p让它立即生效。第二步修改/etc/security/limits.conf追加elasticsearch soft nofile 65536 elasticsearch hard nofile 65536 elasticsearch soft nproc 4096 elasticsearch hard nproc 4096 elasticsearch soft memlock unlimited elasticsearch hard memlock unlimited这里把memlock也一起设置了目的是配合bootstrap.memory_lock: true使用防止 ES 堆内存在 GC 时被操作系统换出到磁盘。如果你不打算配置内存锁定memlock 这两行可以不加但加了一定没坏处。还要注意一个 CentOS 7 的特有坑/etc/security/limits.d/20-nproc.conf这个文件里的配置优先级更高如果里面有针对普通用户的nproc限制你在limits.conf里写的 nproc 可能不生效。解决办法是直接在20-nproc.conf里也配置一份或者干脆把文件里和 ES 用户相关的行注释掉。2.3 专用用户与目录规划别用 root更别把数据放系统盘ES 官方明确禁止使用 root 用户启动节点否则会直接报can not run elasticsearch as root。原因不复杂ES 进程一旦被入侵root 权限意味着攻击者能控制系统全局而专有用户能把攻击面限制在 ES 自身目录范围内。这也是为什么前面limits.conf里的用户名要写成elasticsearch。创建用户和目录的完整操作# 创建专用用户 useradd elasticsearch # 创建数据与日志目录 mkdir -p /data/es-data mkdir -p /data/es-logs # 授权给 elasticsearch 用户 chown -R elasticsearch:elasticsearch /data/es-data /data/es-logs目录规划是我特别想强调的一点。很多测试环境把 data 目录放在/根分区下面一旦磁盘写满整个操作系统都跟着遭殃。生产环境建议独立挂载一个数据盘挂在/data下与系统盘隔离。这样即使数据盘写满顶多影响 ES 可用性不会把 SSH 连接都堵死排查问题的时候你会感谢这个决定的。3. elasticsearch.yml 配置逐项拆解三节点的差异化对照3.1 节点身份和角色cluster.name/node.name/node.master 与 node.dataelasticsearch.yml是集群部署的核心文件6.5.4 的配置项和 7.x/8.x 有区别别照抄新版本教程。三个节点上唯一必须保持一致的是cluster.name只要这个值不同节点之间就算网络通了也不会互相认识。可以把cluster.name理解成集群的“姓”node.name是节点的“名”只有姓相同、名不同才能组成一个家庭。node.name在 6.5.4 里可以不写默认是主机名但生产环境建议显式指定。这直接关系到日志排查时的体验如果节点名是node-1、node-2看日志一眼就知道是哪台机器如果默认用主机名云主机那串随机字符能把人看晕。角色相关的配置组合主要有四种场景# 场景一同时作为 master 候选和数据节点中小集群常用 node.master: true node.data: true # 场景二仅作为 master 候选节点大集群专用 node.master: true node.data: false # 场景三仅作为数据节点 node.master: false node.data: true # 场景四仅作为 ingest 节点负责数据管道预处理 node.master: false node.data: false node.ingest: true三节点小集群我推荐场景一也就是三个节点都能参与选举、都能存数据。不要觉得这样“不专业”ES 官方推荐的集群最小规模就是三节点全角色这种配置在没有独立 master 节点的情况下依然能抗住单节点故障。3.2 网络绑定和 Zen Discoverynetwork.host、transport 端口、unicast.hosts 的配合6.5.4 的网络配置和 7.x 差异最大必须单独拎出来讲。这个版本默认只绑定 loopback 地址也就是说你启动后只能通过本机访问。要让其他节点和客户端能连进来需要设置network.host: 0.0.0.0这里有个连锁反应一旦network.host设置为非 loopback 地址ES 会自动进入生产模式启动时强制检查系统参数。这就是很多人第一次部署时遇到 “bootstrap checks failed” 的直接原因。如果你不想用0.0.0.0可以绑内网 IP比如network.host: 192.168.1.101 http.port: 9200 transport.tcp.port: 9300http.port是客户端 HTTP 访问端口transport.tcp.port是节点间内部通信端口。这两个端口要分清楚后面排查问题的时候至关重要客户端连的是 9200节点之间互相通信走的是 9300。然后是集群发现机制。6.5.4 用的是 Zen Discovery核心参数是discovery.zen.ping.unicast.hosts: [192.168.1.101:9300, 192.168.1.102:9300, 192.168.1.103:9300] discovery.zen.minimum_master_nodes: 2unicast.hosts列的是集群里所有 master 候选节点的 IP 和 transport 端口。新节点启动时会主动连接这些地址把自己加入集群。注意这里写的是 9300 端口不是 9200写错的话节点之间能找到彼此但永远无法完成内部握手。minimum_master_nodes是三节点集群防止脑裂的生命线值必须是(master候选节点数 / 2) 1的向下取整结果三节点就是 2。这个参数 7.x 之后已经被写进系统配置里但 6.5.4 必须手工设置。3.3 双网卡环境下的 publish_host 指定还有一种生产环境很常见的场景服务器有多块网卡比如一块内网卡、一块外网卡。如果不指定ES 可能会把 transport 通信的 publish address 绑到错误的网卡上导致集群内节点互相能 ping 通但 9300 端口握手始终失败。这种情况下建议用network.publish_host显式指定节点对外的发布地址network.host: 0.0.0.0 network.publish_host: 192.168.1.101这样 HTTP 服务可以绑定所有网卡但节点间通信只走内网 IP避免集群流量跑到外网卡上引发安全和性能双重问题。3.4 heap 内存与 jvm.options别把内存全部交给 ES堆内存不在elasticsearch.yml里配置而是在config/jvm.options文件里。6.5.4 安装包默认的两行是-Xms1g -Xmx1g生产环境必须改。我的建议是-Xms和-Xmx设置为相同的值避免 JVM 在运行过程中动态申请内存导致 Full GC。比如 32GB 内存的机器设置 16GB 或 31GB 都可以关键是不要一次性把物理内存全部塞给 ES要给操作系统留足 page cache 的空间因为 Lucene 本身非常依赖 OS 缓存来加速索引读取。4. 三节点集群部署实操记录从解压到健康检查4.1 三个节点的完整配置实例假设三台服务器的内网 IP 分别是 192.168.1.101、192.168.1.102、192.168.1.103。先在每台机器上下载并解压 6.5.4wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.4.tar.gz tar -zxf elasticsearch-6.5.4.tar.gz mv elasticsearch-6.5.4 /opt/elasticsearch chown -R elasticsearch:elasticsearch /opt/elasticsearch然后分别编辑/opt/elasticsearch/config/elasticsearch.yml。101 节点的核心配置cluster.name: es-cluster node.name: node-1 node.master: true node.data: true path.data: /data/es-data path.logs: /data/es-logs network.host: 0.0.0.0 http.port: 9200 transport.tcp.port: 9300 network.publish_host: 192.168.1.101 discovery.zen.ping.unicast.hosts: [192.168.1.101:9300, 192.168.1.102:9300, 192.168.1.103:9300] discovery.zen.minimum_master_nodes: 2102 节点和 103 节点的配置几乎一样只有两处不同node.name分别改成node-2、node-3network.publish_host改成各自的 IP。其他参数保持一致。配置完成后先用sudo -u elasticsearch切换用户再去启动记得绝对不要让 ES 跑在 root 下。4.2 启动顺序和日志观察的关键点三节点集群的启动顺序有个不成文的建议先启动配置了node.master: true的节点而且最好逐台启动不要三台同时开。第一台节点启动时由于找不到其他节点日志里会出现等待 master 的状态这很常见。关键看日志是否出现下面这段[o.e.n.Node] [node-1] initializing ... [o.e.n.Node] [node-1] starting ... [o.e.t.TransportService] [node-1] publish_address {192.168.1.101:9300}, bound_addresses {192.168.1.101:9300} [o.e.h.HttpServer] [node-1] publish_address {192.168.1.101:9200}, bound_addresses {192.168.1.101:9200} [o.e.n.Node] [node-1] started看到publish_address和started说明第一个节点已经正常起起来了。接着启动第二台、第三台观察第二台节点的日志应该出现这样的变化[o.e.c.s.ClusterApplierService] [node-2] master node changed {previous [], current [{node-1}{hash}{192.168.1.101}...]}这行日志的意思是 node-2 已经发现了集群中的 master 节点就是 node-1并成功加入了集群。如果你一直看不到这样的日志而是反复出现master not discovered yet说明节点之间的通信链路有问题需要按第 5 章的思路排查。4.3 集群健康状态与分片分配的验证命令部署完成的标志不是“三个进程都在”而是集群状态变成green。验证集群健康的命令curl -s http://192.168.1.101:9200/_cluster/health?pretty期望输出{ cluster_name : es-cluster, status : green, number_of_nodes : 3, number_of_data_nodes : 3, active_primary_shards : 0, active_shards : 0, relocating_shards : 0, initializing_shards : 0, unassigned_shards : 0 }如果刚部署完还没有建索引active_shards是 0 是正常的只要status是green就说明集群本身没有故障。此时再看节点视图curl -s http://192.168.1.101:9200/_cat/nodes?v输出应该有三行分别对应三个节点IP 和节点名一一对应。如果只显示了一个节点说明另外两个节点没有加进来果断去看 9300 端口的连通性。5. 集群部署中的高频报错排查链路5.1 “bootstrap checks failed”三条命令定位这个报错是 ES 新手村第一道坎启动日志里提示你 “bootstrap checks failed”意思是一个或多个系统参数不满足部署要求。解决方式不是去关检查而是把检查项一条条处理好。用curl调一次节点的_nodes接口能看到详细的检查结果curl -s http://192.168.1.101:9200/_nodes/process?pretty但大多数情况下直接看启动日志里[x]开头的行就够了。常见的三项及解决方法# 1. 文件描述符不足 ulimit -Hn # 期望输出 65536 或更大如果不够重新登录或检查 limits.conf # 2. 虚拟内存映射区数量不足 sysctl vm.max_map_count # 期望输出 262144 # 3. 线程数不足 ulimit -Hu # 期望输出至少 4096这三项都调好后重启 ES 进程正常情况下就不再报 bootstrap checks failed 了。遇到这个错误时最忌讳的是在elasticsearch.yml里设置bootstrap.system_call_filter: false一类参数来绕过检查那是把问题往后拖量一大还是会崩。5.2 节点迟迟无法加入从日志到端口连通性排查三台节点都启动了但_cat/nodes始终只显示一个节点这是部署阶段第二高频的问题。排查链路我从实际经验里总结了一个顺序。第一步看日志确认是在哪个阶段失败的。如果报错是connect_transport_exception说明目标节点的 9300 端口根本连不上。用telnet测一下端口telnet 192.168.1.102 9300如果通输出会显示Connected to 192.168.1.102如果不通要么是防火墙拦了要么是 ES 进程没在监听。防火墙放行参考firewall-cmd --permanent --add-port9200/tcp firewall-cmd --permanent --add-port9300/tcp firewall-cmd --reload第二步确认 9300 端口监听的网卡是不是publish_host那个 IP。执行netstat -anp | grep 9300如果监听地址是0.0.0.0:9300没问题如果监听的是 127.0.0.1说明network.host没配置对回到第 3 章检查。第三步看unicast.hosts里填的 IP 是不是光纤互联的那个网段。云环境经常出现内网 IP 和公网 IP 混填的情况节点之间互相能ping通但 9300 端口就是连不上最终查出是安全组规则只放行了 9200没放行 9300。5.3 分片卡在 UNASSIGNED红黄绿状态背后的原因集群状态yellow甚至red是最容易造成焦虑的报错。执行curl -s http://192.168.1.101:9200/_cat/shards?v | grep UNASSIGNED大概率能发现问题分片。分片未分配的原因在小集群里最常见的就是“副本数大于数据节点数”。比如只有一个数据节点时副本数为 1意味着系统需要一个和数据节点不同的节点去存放副本但节点不够副本就永远无法分配集群状态停在yellow。解决方案有两个角度一是增加数据节点这是根治方案二是临时降低副本数curl -XPUT http://192.168.1.101:9200/data_index/_settings -H Content-Type: application/json -d { number_of_replicas: 0 }如果grep UNASSIGNED看到的原因是disk watermark exceeded表示某个节点的磁盘占用超过了高水位线默认是 90%。6.5.4 的磁盘水位参数如下cluster.routing.allocation.disk.watermark.low: 85% cluster.routing.allocation.disk.watermark.high: 90%当磁盘占用超过 85%新分片不再分配到该节点超过 90%系统会尝试把分片搬到其他节点。如果其他节点空间也不足就会看到分片卡在 UNASSIGNED。这属于“磁盘明明有空间但集群就是报错”的经典场景——不是没空间是没达到 ES 预设的水位线。解决方式是清理磁盘数据或者在确认安全的前提下临时调高水位线但不要把高水位调到 99%否则磁盘写满后 ES 会完全卡死。5.4 脑裂现象的识别与恢复脑裂是分布式系统里最麻烦的问题之一ES 6.5.4 的脑裂表现为同一套cluster.name下出现了两个 master 节点各自维护一部分节点数据写入集中在不同节点上互相感知不到对方。脑裂的根因绝大多数是discovery.zen.minimum_master_nodes配置不当。比如三节点集群里这个值设成了 1当网络抖动把集群分成两个分区每个分区各有一个节点能独立选主于是两个 master 就诞生了。ES 判断 master 是否存活靠的是选举机制只要分区内的节点数满足“至少 minimum_master_nodes 个”它就会认为当前分区是合法的。脑裂恢复的方法是把minimum_master_nodes改成 2然后重启所有节点让它们重新选举出一个 master另一个孤立分区的节点会在日志里出现master node changed并自动回归。注意改配置的时候要三台都改只改一台不生效。5.5 Windows 环境启动失败的特殊坑后台搜索热度里 “windows 启动 elasticsearch” 一直居高不下这里单列一节。Windows 下部署 6.5.4最常见的问题集中在三块。第一双击elasticsearch.bat窗口一闪而过根本看不到报错信息。正确做法是在 cmd 命令行里执行让错误输出停留在屏幕上cd D:\elk\elasticsearch-6.5.4\bin elasticsearch.bat第二JAVA_HOME配置不对。Windows 的JAVA_HOME变量值不能带引号路径中尽量不要有空格。如果你装在C:\Program Files\Java这种带空格的路径下虽然现代 JVM 能处理但 ES 启动脚本在拼接路径时偶尔会出幺蛾子建议把 JDK 放到D:\jdk8这种无空格路径。第三Windows 没有vm.max_map_count这个概念也不需要设置文件句柄但需要重新审视防火墙。Windows 防火墙默认会拦截入站请求部署集群时记得在“高级安全 Windows 防火墙”里添加入站规则放行 9200 和 9300 端口。很多人在 Windows 上单机启动一切正常一到集群环境节点之间就互相连不上十有八九就是防火墙入站规则没加。第四Windows 下的服务注册方式elasticsearch-service.bat install elasticsearch-service.bat start服务方式启动后目录会多出logs文件夹下的记录排查问题优先看那里。6. 部署完成后的必做加固项6.1 安全与多团队共用的注意事项6.5.4 内置了 X-Pack 安全模块但默认是关闭状态。如果你的集群只在可信内网运行暂时不开启也可以但一旦有多个团队共用建议至少设置基础认证。开启方式是在每个节点的elasticsearch.yml里加xpack.security.enabled: true然后重启所有节点执行bin/elasticsearch-setup-passwords interactive注意安全认证一旦开启所有客户端、Kibana 的elasticsearch.hosts配置里都要补上账号密码否则连接全部报 401。这个操作请安排在业务低峰期因为重启期间集群不可用。6.2 索引快照备份的最小方案部署完成不等于万事大吉快照备份一定要做。在elasticsearch.yml里配置仓库路径path.repo: [/data/backup/es-repo]然后创建一个文件系统仓库并执行快照curl -XPUT http://192.168.1.101:9200/_snapshot/es_backup -H Content-Type: application/json -d { type: fs, settings: { location: /data/backup/es-repo } } curl -XPUT http://192.168.1.101:9200/_snapshot/es_backup/snapshot_1 -H Content-Type: application/json -d { indices: * }需要注意快照恢复时索引必须是可读状态如果索引处于close状态需要先打开。6.3 在线扩容节点的正确姿势最后补充一个后续几乎必然要用到的操作集群扩容。新节点加入时只需要把elasticsearch.yml里的cluster.name配置成和现有集群一致unicast.hosts指向原集群的任意两个节点然后启动节点就会自动加入。加入后观察分片分配情况curl -s http://192.168.1.101:9200/_cat/allocation?v如果新节点一直显示unassigned或者分片迟迟不迁移过来检查磁盘水位和cluster.routing.allocation.enable是否被设置成了none。6.5.4 默认会自动做分片再平衡唯一要做的是等它完成不要手动去reroute所有分片操作不当容易把集群搞成 red。我个人在实际部署中的体会是ES 6.5.4 的集群部署其实不复杂网上大量报错都源于环境准备阶段没做扎实比如系统参数、JDK 版本、权限设置这些“看不见的细节”。尤其是从单机到集群这一步最大的障碍不是配置本身而是对 Zen Discovery 这套老机制的陌生感。这篇文章里的命令和配置都是我在多个项目上验证过的按顺序走下来三节点集群基本一次能通。如果你在部署时遇到其他报错记住先看日志再检查系统参数不要被表面现象带偏。
返回列表