1万字长文!手把手带你搭建ElasticSearch(ES)!

作者:域名 来源:应用开发 浏览: 【】 发布时间:2025-11-05 09:09:25 评论数:

  没有日志分析工具前,长文运维工作存在以下痛点

  生产出现故障后,手把手带运维工程师需要不停查看各种不同的搭建日志进行分析?是不是毫无头绪?

  项目上线出现错误,如何快速定位问题?长文如果后端节点过多、日志分散怎么办?手把手带

  开发人员需要实时查看日志但又不想给服务器的登陆权限,怎么办?搭建难道每天帮开发取日志?

  频繁出现被盗链的情况,导致异常流量突增2G有余,长文给公司带来了损失,手把手带该如何分析异常流量呢?搭建

  使用elastic stack日志分析系统之后

  如上所有的痛点都可以使用日志分析系统ELK解决;

  通过ELK,将运维所有的长文服务器日志,业务系统日志都收集到一个平台下;

  然后提取想要的手把手带内容,比如错误信息,搭建警告信息等,长文当过滤到这种信息,手把手带就马上告警;

  告警后,搭建运维人员就能马上定位是哪台机器、哪个业务系统出现了问题,出现了什么问题;

  ElasticStack是什么?

  ElasticStack简称为ES, 是一个开源的高扩展的分布式全文搜索引擎,是整个ELK架构的b2b供应网核心。

  它可以近乎实时的存储、检索数据;本身扩展性好,可以扩展到上百台服务器,处理PB级别的数据。

  Elastic Stack的主要优点有如下几个:

  处理方式灵活:elasticsearch是实时全文索引,具有强大的搜索功能;

  配置相对简单:elasticsearch全部使用JSON接口,logstash使用模块配置,kibana的配置文件部分更简单;

  检索性能高效:基于优秀的设计,虽然每次查询都是实时,但是也可以达到百亿级数据的查询秒级响应;

  集群线性扩展:elasticsearch和logstash都可以灵活线性扩展。

  文档的底层操作原理解析

  文档的写流程

  新建,删除,更新操作我们都可以归纳为写(write)操作,它们必须在主分片上成功完成才能复制到相关的复制分片上。

  如下所示,下面是我们罗列的主分片和副本分片上成功新建,删除,服务器托管更新一个文档必要的顺序步骤:

  客户端可以请求任意集群节点(比如"es01"),此时我们称该节点为"协调节点(coordinating)";

  协调节点计算数据的存储路由,默认会根据文档的"_id"来计算,假设计算结果确定文档属于分片0,它转发请求到"es03",分片0位于这个节点上;

  "es03"节点在主分片上执行写请求将数据进行保存;

  主分片数据保存成功后,它会转发请求到相应副本分片节点,如下图所示,副本分片位于"es01"节点上;

  当所有的副本分片节点保存数据成功后,会告知"es03"节点写请求执行成功;

  "es03"节点(主分片节点)在反馈给客户端写请求操作的执行结果;

  客户端接收到成功响应的时候,文档的修改已经应用于主分片和所有的副本分片,你的修改生效了。

  综上所述,文档的写操作,主分片和副本分片拥有强一致性,即主分片和副本分片的数据是一致的。

  温馨提示:

  我们可以通过修改consistency参数的值来改变上述写入的流程,其值为one,all和quorum(默认值)。云南idc服务商

  只要主分片状态写入成功,就认为数据写入成功,直接返回给客户端,并不等待任意的副本分片同步数据。

  必须要主分片和所有的副本分片数据写入成功后才允许执行写操作。

  只要主分片和大部分副本分片写入成功就返回给客户端,并不需要等待所有的副本节点同步数据。这是默认的策略。生产环境中我建议大家就是用默认的策略即可。

  如果没有足够的副本分片写入,ES会等待,希望更多的分片出现。默认情况下等待的超时时间为1分钟,如果你需要,可以使用timeout参数使它更早终止,比如修改为: 5s, 10s, 30s等。

  文档的读流程-单个文档搜索

  文档能够从主分片或者任意一个副本分片被检索。

  如下所示,我们罗列在主分片或者复制分片上检索一个文档必要的顺序步骤:

  客户端给协调节点("es03")发送get请求;

  协调节点默认使用文档的"_id"确定文档属于分片"0",分片"0"对应的副本分片在"es01"和"es03"节点上都有,此时,它转发请求到"es01";

  "es01"返回文档(document)给"es03",然后由"es03"返回给客户端;

  对于读请求,为了平衡负载均衡,请求节点会为每个请求选择不同的分片,它会循环所有的分片副本。

  可能的情况是,一个被索引的文档已经存在于主分片上却还没来得及同步到副本分片上。

  这时副本分片会报告文档未找到,主分片会成功返回文档。一旦索引请求成功返回给用户,文档则在主分片和副本分片都是可用的。

  文档的读流程-全文搜索

  对于全文搜索而言,文档可能分散在各个节点上,那么在分布式的情况下,分为两个阶段,即搜索(query)和取回(fetch)这两个阶段。

  搜索(query)阶段包含以下三步:

  客户端发送一个search(搜索)请求给"es03","es03"创建了一个长度为"from + size"(这两个参数大家并不陌生,在分页查询中我们有使用到)的空优先级队列;

  "es03"转发这个搜索请求中每个分片的主分片或者副本分片,每个分片在本地执行这个查询并将结果存储到一个大小为"from + size"的有序本地优先级队列里去;

  每个分片返回文档(document)的ID和它优先级队列里的所有document的排序值给协调节点"es03","es03"把这些值合并到自己的优先队列里产生全局排序结果;

  取回(fetch)阶段包含以下三步:

  协调节点辨别出哪个文档(document)需要取回,并且向相关分片发出GET请求;

  每个分片加载document并且根据需要丰富(enrich)它们(因为query阶段拿到的是排序后的"_id",并没有真正拿到数据),然后再将document返回协调节点;

  一旦所有的document都被取回,协调节点会将结果返回给客户端;

  文档的更新流程

  部分更新一个文档结合了先前说明的读取和写入流程。

  部分更新一个文档的步骤如下:

  客户单向协调节点("es03")发送更新请求;

  协调节点通过计算,发现更新请求的主分片在"es02"上,因此将请求转发到主分片所在的"es02";

  "es02"从主分片检索文档,修改"_source"字段中的JSON,并且尝试重新索引主分片的文档。如果文档已经被另一个进程修改(该文档底层对应的文件就会被上"锁"),它会重试步骤3,超过retry_on_conflict次后放弃;

  如果"es02"成功更新文档,它将新版本的文档并行转发到其它的副本分片,重新建立索引;

  一旦所有副本分片都返回成功,"es02"向协调节点也返回成功,协调节点向客户端返回成功;

  温馨提示:

  当主分片把更改转发到副本分片时,它不会转发更新请求。相反,它转发完整文档的新版本。

  请记住,这些更改将会异步转发到副本分片,并且不能保证他们以发送他们相同的顺序到达。如果elasticsearch仅转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

  多文档的批量操作流程

  mget和bulk API的模式类似于单文档模式。

  区别在于协调节点知道每个文档存在于哪个分片中。它将整个文档请求分解成每个分片的多文档请求,并且将这些请求并行转发到每个参与节点。

  协调节点一旦收到来自节点的应答,就将每个节点的响应收集整理成单个响应,返回给客户端。

  使用elastic stack能收集哪些日志?

  容器管理工具:docker;

  负载均衡服务器:lvs、haproxy、Nginx;

  Web服务器:httpd、Nginx、Tomcat;

  数据库:mysql、redis、MongoDB、PgSQL;

  存储:nfs、gluterfs、fastdfs、Ceph;

  系统:message、security;

  业务:包括且不限于C/C++、Java、Python、Shell等编程语言研发的App

  ElasticStack基础环境准备

  部署规划与架构图

  修改国内的软件源

[root@oldboy-elk01 ~]# curl -s -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo [root@oldboy-elk01 ~]# curl -s -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [root@oldboy-elk01 ~]# yum makecache

  关闭防火墙

[root@oldboy-elk01 ~]# systemctl stop firewalld [root@oldboy-elk01 ~]# systemctl disable firewalld

  禁用Selinux

[root@oldboy-elk01 ~]# getenforce Enforcing [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# setenforce 0 [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# getenforce Permissive [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# sed -ri s#(SELINUX=)enforcing#\1disabled# /etc/selinux/config [root@oldboy-elk01 ~]#

  安装常用的工具

[root@oldboy-elk01 ~]# yum install tree nmap dos2unix lrzsz nc lsof wget tcpdump htop iftop iotop sysstat nethogs -y [root@oldboy-elk01 ~]# yum install psmisc net-tools bash-completion vim-enhanced -y

  时间同步

[root@oldboy-elk01 ~]# yum install ntp -y [root@oldboy-elk01 ~]# ntpdate ntp1.aliyun.com

  JDK部署

[root@oldboy-elk01 ~]# wget https://javadl.oracle.com/webapps/download/GetFile/1.8.0_301-b09/d3c52aa6bfa54d3ca74e617f18309292/linux-i586/jdk-8u301-linux-x64.tar.gz [root@oldboy-elk01 ~]# ls -l total 149480 -rw-r--r-- 1 root root 145520298 Jun 9 2021 jdk-8u301-linux-x64.tar.gz [root@oldboy-elk01 ~]# tar zxf jdk-8u301-linux-x64.tar.gz -C /oldboyedu/softwares/ [root@oldboy-elk01 ~]# [root@oldboy-elk01 softwares]# cd /oldboyedu/softwares/ [root@oldboy-elk01 softwares]# ls -l total 4 drwxr-xr-x 8 10143 10143 4096 Jun 9 2021 jdk1.8.0_301 [root@oldboy-elk01 softwares]# ln -s jdk1.8.0_301/ jdk [root@oldboy-elk01 softwares]# ll total 4 lrwxrwxrwx 1 root root 13 Apr 11 15:53 jdk -> jdk1.8.0_301/ drwxr-xr-x 8 10143 10143 4096 Jun 9 2021 jdk1.8.0_301 [root@oldboy-elk01 softwares]# cat >/etc/profile.d/jdk.sh<<EOF #!/bin/bash export JAVA_HOME=/oldboyedu/softwares/jdk export PATH=\$PATH:\$JAVA_HOME/bin EOF [root@oldboy-elk01 softwares]# source /etc/profile.d/jdk.sh [root@oldboy-elk01 softwares]# java -version java version "1.8.0_301" Java(TM) SE Runtime Environment (build 1.8.0_301-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode) [root@oldboy-elk01 softwares]#

  ES分布式架构搭建

  配置免密登录

[root@oldboy-elk01 ~]# ssh-keygen -t rsa -P -f ~/.ssh/id_rsa [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# ssh-copy-id 192.168.56.130 [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# ssh-copy-id 192.168.56.131 [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# ssh-copy-id 192.168.56.132 [root@oldboy-elk01 ~]#

  编写rsync集群同步脚本

[root@oldboy-elk01 ~]# vim data_rsync.sh [root@oldboy-elk01 ~]# [root@oldboy-elk01 ~]# cat data_rsync.sh #!/bin/bash if [ $# -ne 1 ];then echo "仅支持一个路径参数." exit fi # 判断文件是否存在 if [ ! -e $1 ];then echo "[ $1 ] dir or file not find!" exit fi # 获取父路径 fullpath=`dirname $1` # 获取子路径 basename=`basename $1` # 进入到父路径 cd $fullpath for ((host_id=131;host_id<=132;host_id++)) do # 使得终端输出变为绿色 tput setaf 2 echo ===== 192.168.56.${host_id}: $basename ===== # 使得终端恢复原来的颜色 tput setaf 7 # 将数据同步到其他两个节点 rsync -az $basename `whoami`@192.168.56.${host_id}:$fullpath if [ $? -eq 0 ];then echo "命令执行成功!" fi done [root@oldboy-elk01 ~]#

  安装Elasticsearch软件

[root@oldboy-elk01 ~]# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.12.1-linux-x86_64.tar.gz [root@oldboy-elk01 ~]# tar zxf elasticsearch-7.12.1-linux-x86_64.tar.gz -C /oldboyedu/softwares/ [root@oldboy-elk01 softwares]# cd /oldboyedu/softwares/ [root@oldboy-elk01 softwares]# ls -l total 4 drwxr-xr-x. 9 root root 155 4月 21 05:00 elasticsearch-7.12.1 lrwxrwxrwx 1 root root 13 Apr 11 15:53 jdk -> jdk1.8.0_301/ drwxr-xr-x 8 10143 10143 4096 Jun 9 2021 jdk1.8.0_301 [root@oldboy-elk01 softwares]# ln -s elasticsearch-7.12.1 elasticsearch [root@oldboy-elk01 softwares]# ls -l total 4 lrwxrwxrwx 1 root root 13 Apr 11 15:53 elasticsearch -> elasticsearch-7.12.1/ drwxr-xr-x. 9 root root 155 4月 21 05:00 elasticsearch-7.12.1 lrwxrwxrwx 1 root root 13 Apr 11 15:53 jdk -> jdk1.8.0_301/ drwxr-xr-x 8 10143 10143 4096 Jun 9 2021 jdk1.8.0_301 [root@oldboy-elk01 softwares]# cat >/etc/profile.d/es.sh<<EOF #!/bin/bash export ES_HOME=/oldboyedu/softwares/elasticsearch export PATH=\$PATH:\$ES_HOME/bin EOF [root@oldboy-elk01 softwares]# source /etc/profile.d/es.sh

  创建普通用户并修改文件属主权限

[root@oldboy-elk01 ~]# useradd oldboy [root@oldboy-elk01 ~]# chown -R oldboy.oldboy -R /oldboyedu/softwares/elasticsearch-7.12.1 [root@oldboy-elk01 ~]# mkdir -p /oldboyedu/data/elasticsearch [root@oldboy-elk01 ~]# chown oldboy.oldboy /oldboyedu/data/elasticsearch [root@oldboy-elk01 ~]# ls -ld /oldboyedu/data/elasticsearch/ drwxr-xr-x. 2 oldboy oldboy 6 5月 16 14:52 /oldboyedu/data/elsticsearch/ [root@oldboy-elk01 ~]# mkdir -p /oldboyedu/logs/elasticsearch [root@oldboy-elk01 ~]# chown -R oldboy.oldboy /oldboyedu/logs/elasticsearch [root@oldboy-elk01 ~]# ls -ld /oldboyedu/logs/elasticsearch/ drwxr-xr-x. 2 oldboy oldboy 4096 5月 16 14:43 /oldboyedu/logs/elsticsearch [root@oldboy-elk01 ~]#

  修改ES配置文件,配置文件解释

  单机版配置文件

[root@oldboy-elk01 ~]# cd /oldboyedu/softwares/elasticsearch/config [root@oldboy-elk01 config]# vim elasticsearch.yml [root@oldboy-elk01 config]# egrep ^[a-z] elasticsearch.yml cluster.name: oldboy-linux node.name: 192.168.56.130 path.data: /oldboyedu/data/elasticsearch path.logs: /oldboyedu/logs/elasticsearch network.host: 0.0.0.0 discovery.seed_hosts: ["192.168.56.130"] cluster.initial_master_nodes: ["192.168.56.130"]

  集群版配置文件

[root@oldboy-elk01 ~]# cd /oldboyedu/softwares/elasticsearch/config [root@oldboy-elk01 config]# vim elasticsearch.yml [root@oldboy-elk01 config]# egrep ^[a-z] elasticsearch.yml cluster.name: oldboy-linux node.name: 192.168.56.130 path.data: /oldboyedu/data/elasticsearch path.logs: /oldboyedu/logs/elasticsearch network.host: 0.0.0.0 discovery.seed_hosts: ["192.168.56.130","192.168.56.131","192.168.56.132"] cluster.initial_master_nodes: ["192.168.56.130","192.168.56.131","192.168.56.132"]

  调优集群的初始化参数

  修改文件描述符的最大打开数量

[root@oldboy-elk01 ~]# vim /etc/security/limits.d/es.conf [root@oldboy-elk01 ~]# cat /etc/security/limits.d/es.conf # Add by oldboy for Elasticsearch * soft nofile 65535 * hard nofile 65535

  修改虚拟内存区域映射大小

[root@oldboy-elk01 ~]# vim /etc/sysctl.conf [root@oldboy-elk01 ~]# cat /etc/sysctl.conf vm.max_map_count=262144 [root@oldboy-elk01 ~]# sysctl -p vm.max_map_count = 262144

  启动ElasticSearch服务

[root@oldboy-elk01 ~]# su - oldboy Last login: Mon Apr 11 17:03:24 CST 2022 on pts/0 [oldboy@oldboy-elk01 ~]$ [oldboy@oldboy-elk01 ~]$ elasticsearch -d [oldboy@oldboy-elk01 ~]$ ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *:22 *:* LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 [::]:9200 [::]:* LISTEN 0 128 [::]:9300 [::]:* LISTEN 0 100 [::1]:25 [::]:* [root@oldboy-elk01 ~]# curl 192.168.56.130:9200 { "name" : "192.168.56.130", "cluster_name" : "my-application", "cluster_uuid" : "dB4nRg7MTGGzzzPblMjksw", "version" : { "number" : "7.12.1", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "3186837139b9c6b6d23c3200870651f10d3343b7", "build_date" : "2021-04-20T20:56:39.040728659Z", "build_snapshot" : false, "lucene_version" : "8.8.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }

  停止ElasticSearch服务

[root@oldboy-elk01 ~]# jps 31991 Jps 31739 Elasticsearch [root@oldboy-elk01 ~]# kill 31739

  node节点搭建

[root@oldboy-elk01 ~]# sh data_rsync.sh /oldboyedu [root@oldboy-elk01 ~]# sh data_rsync.sh /etc/profile.d/jdk.sh [root@oldboy-elk01 ~]# sh data_rsync.sh /etc/profile.d/es.sh [root@oldboy-elk01 ~]# [root@oldboy-elk02 ~]# cd /oldboyedu/softwares/elasticsearch/config [root@oldboy-elk02 config]# vim elasticsearch.yml [root@oldboy-elk02 config]# egrep ^[a-z] elasticsearch.yml cluster.name: oldboy-linux node.name: 192.168.56.131 path.data: /oldboyedu/data/elasticsearch path.logs: /oldboyedu/logs/elasticsearch network.host: 0.0.0.0 discovery.seed_hosts: ["192.168.56.130","192.168.56.131","192.168.56.132"] cluster.initial_master_nodes: ["192.168.56.130","192.168.56.131","192.168.56.132"] [root@oldboy-elk02 config]# source /etc/profile.d/jdk.sh [root@oldboy-elk02 config]# source /etc/profile.d/es.sh [root@oldboy-elk02 config]# [root@oldboy-elk03 ~]# cd /oldboyedu/softwares/elasticsearch/config [root@oldboy-elk03 config]# vim elasticsearch.yml [root@oldboy-elk03 config]# egrep ^[a-z] elasticsearch.yml cluster.name: oldboy-linux node.name: 192.168.56.132 path.data: /oldboyedu/data/elasticsearch path.logs: /oldboyedu/logs/elasticsearch network.host: 0.0.0.0 discovery.seed_hosts: ["192.168.56.130","192.168.56.131","192.168.56.132"] cluster.initial_master_nodes: ["192.168.56.130","192.168.56.131","192.168.56.132"] [root@oldboy-elk03 config]# source /etc/profile.d/jdk.sh [root@oldboy-elk03 config]# source /etc/profile.d/es.sh [root@oldboy-elk03 config]#