【SRE工程师培训】ElasticSearch分布式架构搭建详解!
老男孩IT教育
技术博客
2022年9月30日 10:31
ElasticStack简称为ES, 是一个开源的高扩展的分布式全文搜索引擎,是整个ELK架构的核心。
ElasticStack简称为ES, 是一个开源的高扩展的分布式全文搜索引擎,是整个ELK架构的核心。
它可以实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
Elastic Stack的主要优点有如下几个:
elasticsearch和logstash都可以灵活线性扩展
于优秀的设计,虽每次查询都是实时,但是也可以达到百亿级数据的查询秒级响应
elasticsearch全部使用JSON接口,logstash使用模块配置,kibana的配置文件更简单
elasticsearch是实时全文索引,具有强大的搜索功能
| 没有ES服务前,运维工作有哪些痛点
1、生产出现故障后,运维需要不停的查看各种不同的日志进行分析?是不是毫无头绪
2、项目上线出现错误,如何快速定位问题?如果后端节点过多、日志分散怎么办
3、开发人员需要实时查看日志但又不想给服务器的登陆权限,怎么办?难道每天帮开发取日志
4、分析的日志数据量大,势必会导致查询速度慢、难度大,会导致我们无法快速的获取到想要的指标
5、频繁出现被盗链的情况,导致异常流量突增2G有余,给公司带来了损失,又该如何分析异常流量
| 使用elastic stack日志分析系统之后
- 如上所有的痛点都可以使用日志分析系统ELK解决
- 通过ELK,将运维所有的服务器日志,业务系统日志都收集到一个平台下
- 然后提取想要的内容,比如错误信息,警告信息等,当过滤到这种信息,就马上告警
- 告警后,运维人员就能马上定位是哪台机器、哪个业务系统出现了问题,出现了什么问题
ElasticStack原理解析
| 文档的写流程
新建,删除,更新操作我们都可以归纳为写(write)操作,它们必须在主分片上成功完成才能复制到相关的复制分片上
如下图所示,下面是我们罗列的主分片和副本分片上成功新建,删除,更新一个文档必要的顺序步骤:
1、客户端可以请求任意集群节点(比如"es01"),此时我们称该节点为"协调节点(coordinating)";
2、协调节点计算数据的存储路由,默认会根据文档的"_id"来计算,假设计算结果确定文档属于分片0,它转发请求到"es03",分片0位于这个节点上;
3、"es03"节点在主分片上执行写请求将数据进行保存;
4、主分片数据保存成功后,它会转发请求到相应副本分片节点,如下图所示,副本分片位于"es01"节点上;
5、当所有的副本分片节点保存数据成功后,会告知"es03"节点写请求执行成功;
6、"es03"节点(主分片节点)在反馈给客户端写请求操作的执行结果;
7、客户端接收到成功响应的时候,文档的修改已经应用于主分片和所有的副本分片,你的修改生效了
综上所述,文档的写操作,主分片和副本分片拥有强一致性,即主分片和副本分片的数据是一致的
温馨提示:
我们可以通过修改consistency参数的值来改变上述写入的流程,其值为one,all和quorum(默认值)
1、one:只要主分片状态写入成功,就认为数据写入成功,直接返回给客户端,并不等待任意的副本分片同步数据
2、all:必须要主分片和所有的副本分片数据写入成功后才允许执行写操作。
3、quorum:只要主分片和大部分副本分片写入成功就返回给客户端,并不需要等待所有的副本节点同步数据
(计算公式为: "int((primary + number_of_replicas)/2) + 1")
| 文档的读流程-单个文档搜索
文档能够从主分片或者任意一个副本分片被检索
如下图所示,我们罗列在主分片或者复制分片上检索一个文档必要的顺序步骤:
1、客户端给协调节点("es03")发送get请求;
2、协调节点默认使用文档的"_id"确定文档属于分片"0",分片"0"对应的副本分片在"es01"和"es03"节点上都有,此时,它转发请求到"es01";
3、"es01"返回文档给"es03",然后由"es03"返回给客户端;
对于读请求,为了平衡负载均衡,请求节点会为每个请求选择不同的分片,它会循环所有的分片副本
可能的情况是,一个被索引的文档已经存在于主分片上却还没来得及同步到副本分片上
这时副本分片会报告文档未找到,主分片会成功返回文档。一旦索引请求成功返回给用户,文档则在主分片和副本分片都是可用的
我猜测有可能你会问:
1、为啥"es03"节点不直接返回文档给客户端呢?
2、当"es01"节点查询到数据后为啥不直接返回给客户端而是要将数据交给"es03"节点呢?
参考答案:
1、当"es03"节点负载比较高时,如果把文档的搜索工作还交给当前节点,无疑是雪上加霜,因为他消耗的不仅仅是CPU,内存,套接字等资源,而将任务交给"es01"节点后,就无需为本次搜索承担额外的资源了,换句话说,就会减少本次查询对系统资源负载的消耗;
2、当"es01"节点查询到数据后,并不会直接将数据返回给客户端,我猜想原因之一是不知道客户端的IP地址,原因之二就是如果知道了IP地址也得需要建立TCP连接才能完成传输,与其这样,还不如直接交由已经建立TCP连接的"es03"节点进行数据的返回;
| 文档的读流程-全文搜索
对于全文搜索而言,文档可能分散在各个节点上,那么在分布式的情况下,分为两个阶段,即搜索(query)和取回(fetch)这两个阶段:
搜索(query)阶段包含以下三步:
1、客户端发送一个search(搜索)请求给"es03","es03"创建了一个长度为"from + size"(这两个参数大家并不陌生,在分页查询中我们有使用到)的空优先级队列;
2、"es03"转发这个搜索请求中每个分片的主分片或者副本分片,每个分片在本地执行这个查询并将结果存储到一个大小为"from + size"的有序本地优先级队列里去;
3、每个分片返回文档的ID和它优先级队列里的所有文档的排序值给协调节点"es03","es03"把这些值合并到自己的优先队列里产生全局排序结果;
取回(fetch)阶段包含以下三步:
1、协调节点辨别出哪个文档需要取回,并且向相关分片发出GET请求;
2、每个分片加载文档并且根据需要丰富(enrich)它们(因为query阶段拿到的是排序后的"_id",并没有真正拿到数据),然后再将文档返回协调节点;
3、一旦所有的文档都被取回,协调节点会将结果返回给客户端;
ElasticStack基础环境准备
| 部署规划与架构图
| 修改国内的软件源
curl -s -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -s -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum makecache
| 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
| 禁用Selinux
setenforce 0
sed -ri 's#(SELINUX=)enforcing#\1disabled#' /etc/selinux/config
| 安装常用的工具
yum install tree nmap dos2unix lrzsz nc lsof wget tcpdump htop iftop iotop sysstat nethogs -y
yum install psmisc net-tools bash-completion vim-enhanced -y
| 时间同步
yum install ntp -y
ntpdate ntp1.aliyun.com
| JDK部署
# 下载源码包
wget https://javadl.oracle.com/webapps/download/GetFile/1.8.0_301-b09/d3c52aa6bfa54d3ca74e617f18309292/linux-i586/jdk-8u301-linux-x64.tar.gz
# 部署JDK
tar zxf jdk-8u301-linux-x64.tar.gz -C /oldboyedu/softwares/
cd /oldboyedu/softwares/
ln -s jdk1.8.0_301/ jdk
# 设置环境变量
cat >/etc/profile.d/jdk.sh<<'EOF'
#!/bin/bash
export JAVA_HOME=/oldboyedu/softwares/jdk
export PATH=\$PATH:\$JAVA_HOME/bin
EOF
# 环境变量生效
source /etc/profile.d/jdk.sh
ES分布式架构搭建
| 配置免密登录
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
ssh-copy-id 192.168.56.130
ssh-copy-id 192.168.56.131
ssh-copy-id 192.168.56.132
| 编写rsync集群同步脚本
cat >data_rsync.sh<<'EOF'
#!/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
EOF
| 安装Elasticsearch软件
# 下载ES软件
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.12.1-linux-x86_64.tar.gz
# 部署ES
tar zxf elasticsearch-7.12.1-linux-x86_64.tar.gz -C /oldboyedu/softwares/
cd /oldboyedu/softwares/
ln -s elasticsearch-7.12.1 elasticsearch
# 配置环境变量
cat >/etc/profile.d/es.sh<<EOF
#!/bin/bash
export ES_HOME=/oldboyedu/softwares/elasticsearch
export PATH=\$PATH:\$ES_HOME/bin
EOF
# 使环境变量生效
source /etc/profile.d/es.sh
| 创建普通用户并修改文件属主权限
# 创建用户
useradd oldboy
# 目录创建与授权
chown -R oldboy.oldboy -R /oldboyedu/softwares/elasticsearch-7.12.1
mkdir -p /oldboyedu/data/elasticsearch
chown oldboy.oldboy /oldboyedu/data/elasticsearch
mkdir -p /oldboyedu/logs/elasticsearch
chown -R oldboy.oldboy /oldboyedu/logs/elasticsearch
| 修改ES配置文件,配置文件解释
单机版配置文件:
# cd /oldboyedu/softwares/elasticsearch/config
# vim elasticsearch.yml
# 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"]
集群版配置文件:
# cd /oldboyedu/softwares/elasticsearch/config
# vim elasticsearch.yml
# 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"]
| 调优集群的初始化参数
修改文件描述符的最大打开数量
cat >/etc/security/limits.d/es.conf<<EOF
# Add by oldboy for Elasticsearch
* soft nofile 65535
* hard nofile 65535
EOF
修改虚拟内存区域映射大小
cat >/etc/sysctl.conf<EOF
vm.max_map_count=262144
EOF
sysctl -p
| 启动ElasticSearch服务
# 切换到 oldboy 用户
su - oldboy
# 启动ES服务
elasticsearch -d
| 测试ElasticSearch服务
$ 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 [::]:*
# 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服务
# jps
31991 Jps
31739 Elasticsearch
# kill 31739
| node节点搭建
将配置文件从master节点复制到其它节点上
# scp -rp /oldboyedu root@192.168.56.131:/
# scp -rp /oldboyedu root@192.168.56.132:/
# scp -rp /etc/profile.d/jdk.sh root@192.168.56.131:/etc/proflie.d/
# scp -rp /etc/profile.d/jdk.sh root@192.168.56.132:/etc/proflie.d/
# scp -rp /etc/profile.d/es.sh root@192.168.56.131:/etc/proflie.d/
# scp -rp /etc/profile.d/es.sh root@192.168.56.132:/etc/proflie.d/
node节点修改配置文件并使环境变量生效
# cd /oldboyedu/softwares/elasticsearch/config
# vim elasticsearch.yml
# 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"]
# source /etc/profile.d/jdk.sh
# source /etc/profile.d/es.sh
# cd /oldboyedu/softwares/elasticsearch/config
# vim elasticsearch.yml
# 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"]
# source /etc/profile.d/jdk.sh
# source /etc/profile.d/es.sh
老男孩教育Linux运维云计算课程汇集了虚拟化、云计算、安全攻防、Python开发、SRE等技术,课堂效率高、内容丰富全面,由浅入深,循序渐进,帮助学员稳扎稳打,夯实基础,在有限的时间内帮助学员高效提升,成为符合企业需求的技术型人才。