ELK介绍与部署

日志系统

在系统发生故障时,工程师需要登录到服务器上,使用 grep / sed / awk 等 Linux 工具通过关键字去日志里查找我们想要的信息。在一个较大的分布式系统中,至少需要查找几个甚至几十个服务的日志,且这些服务很有可能还是分布在不同的服务器上,另外每个服务还会设置日志滚动策略(如:每天生成一个文件),还有日志压缩归档策略等。一整个排错的流程下来,不仅效率低下,而且容易错过关键的日志信息。所以,如果我们能把这些日志集中管理,并提供集中检索功能,不仅能提高排错的效率,同时还能实时获取整个业务系统的健康状态。

一个日志系统,一般需要具备以下几个特点:

  • 数据收集-能够采集多种来源的日志数据
  • 数据传输-能够稳定的把日志数据传输到中央系统
  • 数据存储-如何存储日志数据
  • 数据分析-提供UI界面,检索日志信息,定位相应的 bug
  • 服务诊断:通过对日志信息进行统计、分析,了解服务运行状态
  • 异常警告-能够提供错误报告,监控机制

ELK

ELK简介

ELK是Elasticsearch、Logstash、Kibana的简称(现在一般还会加上一个Filebeat),它是一套开源的集中日志管理解决方案,是目前主流的一种日志系统。

  • Elasticsearch:开源分布式搜索引擎,它具有分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等特点;Elasticsearch 基于 Lucene 开发,现在使用最广的开源搜索引擎之一,Wikipedia 、StackOverflow、Github 等都基于它来构建自己的搜索引擎。
  • Logstash:数据收集处理引擎。支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储以供后续使用。由于其占用资源较大,目前收集功能已被Filebeat替代;
  • Kibana:可视化化平台。它能够搜索、展示存储在 Elasticsearch 中索引数据。使用它可以很方便的用图表、表格、地图展示和分析数据。
  • Filebeat:轻量级数据收集引擎。基于原先 Logstash-fowarder 的源码改造出来。换句话说:Filebeat就是新版的 Logstash-fowarder,也会是 ELK Stack 在 Agent 的第一选择。在需要采集日志数据的server 上安装 Filebeat,并指定日志目录或日志文件后,Filebeat 就能读取数据,迅速发送到 Logstash 进行解析,亦或直接发送到Elasticsearch 进行集中式存储和分析。

消息队列

在ELK系统中,一般还会引入消息队列,解耦数据收集和分析入库的过程,同时提高了可扩展性。引入消息队列能使日志系统具有峰值处理能力,不会因为突发的访问压力而造成整个日志系统或部分组件的崩溃。

目前ELK常用的消息队列有Redis和Kafka,两者有各自的优缺点,根据业务实际情况选择。

Kafka:在大数据领域的实时计算、日志采集等场景, Kafka 是业内标准,具有高可靠,高扩展性,持久高、高吞吐等特点。

Redis:一个Key-Value的NoSQL数据库,消息都存放在内存中,写入读取速度快,本身支持MQ功能。但是受内存容量的限制,容易造成内存充爆,如果超过设置的Max memory,数据会被丢弃。在对日志数据完整性要求不是非常严格的业务场景下,完全可以当做一个轻量级的日志队列服务来使用。

ELK部署

环境

服务器名称 系统 IP 备注
elk1 CentOS7.6 192.168.10.1 8C16G
elk2 CentOS7.6 192.168.10.2 8C16G
elk3 CentOS7.6 192.168.10.3 8C16G

Elasticsearch

参考:https://www.elastic.co/guide/en/elasticsearch/reference/7.3/rpm.html#rpm-repo

先安java

1
yum install java

下载并安装ES的yum公钥

1
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

配置Elasticsearch的yum源

1
2
3
4
5
6
7
8
9
[root@elk1 ~]# vi /etc/yum.repos.d/elasticsearch.repo
[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

三台服务器执行

1
yum install elasticsearch

检查elasticsearch时候正常运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@elk1 ~]# curl 127.0.0.1:9200
{
"name" : "elk1",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "Nm1SGy7GRQOCIDBmj31jhw",
"version" : {
"number" : "7.3.1",
"build_flavor" : "default",
"build_type" : "rpm",
"build_hash" : "4749ba6",
"build_date" : "2019-08-19T20:19:25.651794Z",
"build_snapshot" : false,
"lucene_version" : "8.1.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}

配置

cat /etc/elasticsearch/elasticsearch.yml

elk1

1
2
3
4
5
6
7
8
cluster.name: es-cluster
node.name: es-1
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 192.168.10.1
discovery.seed_hosts: ["192.168.10.1:9300","192.168.10.2:9300","192.168.10.3:9300"]
cluster.initial_master_nodes: ["192.168.10.1:9300","192.168.10.2:9300","192.168.10.3:9300"]
gateway.recover_after_nodes: 3

elk2

1
2
3
4
5
6
7
8
9
cluster.name: es
node.name: es2
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
path.repo: ["/data/elasticsearch/repo"]
network.host: 192.168.10.2
discovery.seed_hosts: ["192.168.10.1:9300","192.168.10.2:9300","192.168.10.3:9300"]
cluster.initial_master_nodes: ["192.168.10.1:9300","192.168.10.2:9300","192.168.10.3:9300"]
gateway.recover_after_nodes: 3

elk3

1
2
3
4
5
6
7
8
9
cluster.name: es
node.name: es3
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
path.repo: ["/data/elasticsearch/repo"]
network.host: 192.168.10.3
discovery.seed_hosts: ["192.168.10.1:9300","192.168.10.2:9300","192.168.10.3:9300"]
cluster.initial_master_nodes: ["192.168.10.1:9300","192.168.10.2:9300","192.168.10.3:9300"]
gateway.recover_after_nodes: 3

启动es,三台服务器执行

1
2
systemctl enable elasticsearch
systemctl start elasticsearch

查看集群健康状态

1
2
3
4
5
6
7
8
9
[root@elk1 ~]# curl http://192.168.10.1:9200/_cat/health?v
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1568017023 08:17:03 es green 3 3 5977 5781 0 0 0 0 - 100.0%

[root@elk1 ~]# curl http://192.168.10.1:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.10.1 72 99 5 0.27 0.38 0.48 dim - es1
192.168.10.3 62 97 7 0.44 0.74 0.88 dim * es3
192.168.10.2 63 99 27 1.08 0.66 0.58 dim - es2

kibana

1
yum install kibana

配置

1
2
3
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://192.168.10.1:9200","http://192.168.10.2:9200","http://192.168.10.3:9200"]

logstash

1
yum install logstah

配置

主配置文件logstash.yml

1
2
3
4
5
path.data: /var/lib/logstash
pipeline.workers: 4
pipeline.batch.size: 1500
pipeline.batch.delay: 1000
path.logs: /var/log/logstash

其他收集日志的配置文件放到目录/etc/logstash/conf.d。

例:收集系统日志配置/etc/logstash/conf.d/system.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
input {
file {
path => "/var/log/messages" #日志路径
type => "systemlog" #类型
start_position => "beginning" #logstash 从什么位置开始读取文件数据,默认是结束位置,也就是说 logstash 进程会以类似 tail -F 的形式运行。如果你是要导入原有数据,把这个设定改成"beginning",logstash 进程就从头开始读取,类似 less +F 的形式运行。
stat_interval => "2" #logstash 每隔多久检查一次被监听文件状态(是否有更新) ,默认是 1 秒。
}
}
filter {
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:logtime}" }
}
date {
match => ["logtime", "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd HH:mm:ss,SSS", "ISO8601"]
target => "@timestamp"
}
}

output {
elasticsearch {
hosts => ["192.168.10.1:9200","192.168.10.2:9200","192.168.10.3:9200"] #指定hosts
index => "logstash-systemlog-%{+YYYY.MM.dd}" #索引名称
}

}

启动logstash

1
systemctl start logstash

查看elasticsearch,已经有相应的索引
curl -s -X GET “127.0.0.1:9200/_cat/indices?v” |grep system

1
green  open   logstash-systemlog-2019.09.09                         -dnjG_bbR66b88LB80PHnw   1   1        779            0    256.8kb        125.7kb

最后在kibana上创建索引模式后,即可通过kibana查看系统日志。

elasticsearch配置说明

参数 说明
cluster.name: ES ES集群名称,同一个集群内的所有节点集群名称必须保持一致
node.name: slave2 ES集群内的节点名称,同一个集群内的节点名称要具备唯一性
node.master: true 允许节点是否可以成为一个master节点,ES是默认集群中的第一台机器成为master,如果这台机器停止就会重新选举
node.data: false 允许该节点存储索引数据(默认开启)
path.data: ES是搜索引擎,会创建文档,建立索引,此路径是索引的存放目录.可以指定多个存储位置
path.logs: elasticsearch专门的日志存储位置
bootstrap.memory_lock: true 在ES运行起来后锁定ES所能使用的堆内存大小,锁定内存大小一般为可用内存的一半左右;锁定内存后就不会使用交换分区。如果不打开此项,当系统物理内存空间不足,ES将使用交换分区,ES如果使用交换分区,那么ES的性能将会变得很差
network.host: 0.0.0.0 es的HTTP端口和集群通信端口就会监听在此地址上
network.tcp.no_delay: true 是否启用tcp无延迟,true为启用tcp不延迟,默认为false启用tcp延迟
truenetwork.tcp.keep_alive: true 是否启用TCP保持活动状态,默认为true
network.tcp.reuse_address: true 是否应该重复使用地址。默认true,在Windows机器上默认为false
network.tcp.send_buffer_size: 128mb tcp发送缓冲区大小,默认不设置
network.tcp.receive_buffer_size: 128mb tcp接收缓冲区大小,默认不设置
transport.tcp.port: 9301 设置集群节点通信的TCP端口,默认就是9300
transport.tcp.compress: true 设置是否压缩TCP传输时的数据,默认为false
http.max_content_length: 200mb 设置http请求内容的最大容量,默认是100mb
http.cors.enabled: true 是否开启跨域访问
http.cors.allow-origin: “*” 开启跨域访问后的地址限制,*表示无限制
http.port: 9201 定义ES对外调用的http端口,默认是9200
discovery.zen.ping.unicast.hosts: [“127.0.0.1:9301”,”127.0.0.1:9302”,”127.0.0.1:9303”] 在Elasticsearch7.0版本已被移除,配置错误。写入候选主节点的设备地址,来开启服务时就可以被选为主节点。默认主机列表只有127.0.0.1和IPV6的本机回环地址。上面是书写格式,discover意思为发现,zen是判定集群成员的协议,unicast是单播的意思,ES5.0版本之后只支持单播的方式来进行集群间的通信,hosts为主机
discovery.zen.minimum_master_nodes: 2 在Elasticsearch7.0版本已被移除,配置无效,为了避免脑裂,集群的最少节点数量为,集群的总节点数量除以2加一
discovery.zen.fd.ping_timeout: 120s 在Elasticsearch7.0版本已被移除,配置无效。探测超时时间,默认是3秒,我们这里填120秒是为了防止网络不好的时候ES集群发生脑裂现象
discovery.zen.fd.ping_retries: 6 在Elasticsearch7.0版本已被移除,配置无效。探测次数,如果每次探测90秒,连续探测超过六次,则认为节点该节点已脱离集群,默认为3次
discovery.zen.fd.ping_interval: 15s 在Elasticsearch7.0版本已被移除,配置无效。节点每隔15秒向master发送一次心跳,证明自己和master还存活,默认为1秒太频繁
discovery.seed_hosts: [“127.0.0.1:9301”,”127.0.0.1:9302”,”127.0.0.1:9303”] Elasticsearch7新增参数,写入候选主节点的设备地址,来开启服务时就可以被选为主节点,由discovery.zen.ping.unicast.hosts:参数改变而来
cluster.initial_master_nodes: [“127.0.0.1:9301”,”127.0.0.1:9302”] Elasticsearch7新增参数,写入候选主节点的设备地址,来开启服务时就可以被选为主节点
cluster.fault_detection.leader_check.interval: 15s Elasticsearch7新增参数,设置每个节点在选中的主节点的检查之间等待的时间。默认为1秒
discovery.cluster_formation_warning_timeout: 30s Elasticsearch7新增参数,启动后30秒内,如果集群未形成,那么将会记录一条警告信息,警告信息未master not fount开始,默认为10秒
cluster.join.timeout: 30s Elasticsearch7新增参数,节点发送请求加入集群后,在认为请求失败后,再次发送请求的等待时间,默认为60秒
cluster.publish.timeout: 90s Elasticsearch7新增参数,设置主节点等待每个集群状态完全更新后发布到所有节点的时间,默认为30秒
cluster.routing.allocation.cluster_concurrent_rebalance: 32 集群内同时启动的数据任务个数,默认是2个
cluster.routing.allocation.node_concurrent_recoveries: 32 添加或删除节点及负载均衡时并发恢复的线程个数,默认4个
cluster.routing.allocation.node_initial_primaries_recoveries: 32 初始化数据恢复时,并发恢复线程的个数,默认4个
discovery.seed_hosts #启动当前es节点时会去这个ip列表中去发现其他节点,此处不需配置自己节点的ip,这里支持ip和ip:port形式,不加端口号默认使用ip:9300去发现节点
cluster.initial_master_nodes 可作为master节点初始的节点名称,tribe-node不在此列

jvm.options

jvm.options主要是进行内存相关配置,官方建议分配给es的内存不要超出系统内存的50%,预留一半给Lucene,因为Lucene会缓存segment数据提升检索性能;内存配置不要超过32g,如果你的服务器内存没有远远超过64g,那么不建议将es的jvm内存设置为32g,因为超过32g后每个jvm对象指针的长度会翻倍,导致内存与cpu的开销增大。

1
2
-Xms8g
-Xmx8g

其他优化

1
2
3
4
sudo swapoff -a
# 禁用swapping,开启服务器虚拟内存交换功能会对es产生致命的打击
vm.max_map_count
# 在/etc/sysctl.conf文件中找到该参数,修改 655300 为 262144后 执行sysctl -p,不然启动时会报值太小