我正在参加「掘金·启航计划」
前言
随着微服务的普及,不知道小伙伴会不会有这种困扰,当现场发生问题时,应用服务器又非常多,排查现场问题将变成一件非常耗时又麻烦的事情;首先,需要和实施小伙伴进行沟通,进入 各个服务器查看应用日志信息,同时从日志文件中检索出重要的日志内容进行问题的排查。这里面的沟通成本,日志文件分布各地,文本类型文件的检索等问题,导致排查问题过程非常耗时,不知道 xdm 的公司会不会有这种情况,你没有,没关系,我有。
那么如何能提高排查问题的效率?有没有一种可视化的工具,可以汇总所有的日志信息。只需在界面上进行相应的搜索,就能找到 自己 想要的日志内容呢? 看标题,你也知道是有的,2333。。。 接下来,我们来看下如何通过业界上比较流行的 ELK 进行业务日志的收集。
本篇内容主要包含以下几个部分:
- EFK介绍
- 业务应用收集的主要设计思路
- EFK 实践
- Kibana 展示日志列表
简单粗暴的认识一下 EFK
对于点进来看的朋友们,我相信你们一定听过ES 家族在日志中的产品 ELK ,或者 ELKB ,那 EFK 是什么鬼东西, 我还 KFC 呢!
- ELK : Elasticsearch ,Logstash , Kibana
- ELKB: Elasticsearch ,Logstash , Kibana,Fileabeat
- EFK: Elasticsearch,Fileabeat,Kibana (相对于以上方案,去掉了 Logstash)
看下这几位大哥在日志系统中占据着什么样的地位?他们又是啥东东呢
-
Filebeat
- 轻量型日志采集器 ,可以采集服务器上的各种日志文件,并转发,汇总文件信息。
- 收集数据并将数据发送到 Logstash 或 Elasticsearch 时,Filebeat 使用背压敏感协议,以应对更多的数据量。如果 Logstash 正在忙于处理数据,则会告诉 Filebeat 减慢读取速度。一旦拥堵得到解决,Filebeat 就会恢复到原来的步伐并继续传输数据。
-
Elasticsearch
- 存储日志内容
- Kibana
展示日志列表,提供搜索等可视化界面操作
-
Logstash
-
Logstash 是免费且开放的服务器端数据处理管道,能够从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中。
-
为啥本次搭建舍弃了 Logstash?
- 目前日志数据量使用 EFK 即可满足需求
- Logstash 相对于 Filebeat 更加笨重,没有 beat 来得轻盈
- 对于数据处理的需求,使用 ES 中的 pipeline 管道处理即可满足需求
当随着后续日志数据量比较大时,对 es 产生较大压力,处理不及时,会考虑加入 logstash,kafka 进行缓冲如下图所示:
-
当前阶段,暂不考虑 Logstash ,Kafka。本次收集的日志主要包含 业务应用日志 和 nginx 日志。架构流程如下图所示:
- 从上图,可看出,本次主要收集日志有 业务应用日志 + Nginx 日志
- 收集流程为 Filebeat 收集 应用日志和 nginx 日志 ,发送到 ES,最终通过 Kibana 进行展示
- 业务应用日志还会结合 Skywalking 进行全链路监控[EFK+Skywalking]
- Nginx 日志收集实践 (第三篇)
业务应用的日志收集
目前,我们的业务应用主要是 spring boot 应用, 业务应用日志 主要以收集 spring boot 应用日志为主。业务系统日志等级主要有 3类 INFO,ERROR,WARN
1、业务系统中的日志格式
2022-09-05 07:09:43.407 INFO 10526 --- [ main] [ ] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2022-09-05 07:09:43.411 INFO 10526 --- [ main] [ ] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2022-09-05 07:09:43.529 INFO 10526 --- [ main] [ ] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 92 ms. Found 0 Redis repository interfaces.
2022-09-05 07:09:44.052 INFO 10526 --- [ main] [ ] o.s.c.c.s.GenericScope : BeanFactory id=3a93ecf4-15e8-39b8-97b7-c859c6e17bf2
从日志内容,可以看出日志中主要 有 时间,日志等级,进程id,线程名称,上下文内容,类名,message
2、日志内容结构化
分析日志信息,梳理日志内容的有效信息,定义 ES 的索引结构,如下图所示
- 其中 appid 和 moduleid 主要通过 file path 获取,用来业务应用标识
- Traceid 链路追踪ID ,下节讲
- mdc 扩展日志内容,可以在 日志中注入应用相关信息,如 用户ID 等
3、ES 索引,数据处理,生命周期设置
在第二步中,我们已经把 ES 中所要存储的日志结构定义下来,但是随着日志内容的不断增量,需要定义索引的生命周期策略,进行自动创建新索引,删除旧的索引等,同时 通过filebeat直接收集到的日志信息是柔和 在 message 字段中,需要进行分割等操作。
- 定义日志的索引生命周期策略 ilm policy
创建索引生命周期策略,对于日志相关内容,一般我们只需保留最近几天的日志,更关注的是实时日志排查,或者现场某个时间的日志信息。 日志生命周期策略为 当达到 30 G ,或者 1天 时,索引进行自动滚动,当索引创建 2 周后,自动删除索引。
- Kibana ==>stack Management => 索引生命周期 进行 生命周期策略配置
- 定义日志内容处理管道 pipeline
- Message 日志内容实用 grok 语法进行分割
- 时间日志重新定义,不然会存在 时区问题 ,设置为 东八区
PUT _ingest/pipeline/log-pipeline
{
"processors": [
{
"grok": {
"field": "message",
"patterns": [
"%{TIMESTAMP_ISO8601:time}%{SPACE}*%{LOGLEVEL:level} %{DATA:pid}%{SPACE}--- \[%{DATA:thread}\] \[%{DATA:mdc}\] %{DATA:class}:(?m)%{GREEDYDATA:message}"
],
"ignore_failure": true
}
},
{
"rename": {
"field": "log.file.path",
"target_field": "logpath",
"ignore_failure": true
}
},
{
"remove": {
"field": "log"
}
},
{
"date": {
"field": "time",
"formats": [
"yyyy-MM-dd HH:mm:ss.SSS"
],
"timezone": "Asia/Shanghai",
"ignore_failure": true
}
}
]
}
- 定义 ES 的索引模版
- 以 test-log- 开头的索引,自动使用 log_template 创建模版
- 索引创建时间使用 log-policy 策略,一天创建一个,达到 30 G 也会创建,使用别名 test-log 进行写入
PUT _index_template/log_template
{
"index_patterns": [
"test-log-*"
],
"template": {
"settings": {
"default_pipeline": "log-pipeline",
"number_of_shards": 2,
"number_of_replicas": 1,
"index.lifecycle.name": "log-policy",
"index.lifecycle.rollover_alias": "test-log",
"index.refresh_interval": "30s"
},
"aliases": {
"test-log-alias": {}
},
"mappings": {
"properties": {
"level": {
"type": "keyword"
},
"logpath": {
"type": "keyword"
},
"ip": {
"type": "keyword"
},
"class": {
"type": "text",
"norms":false
},
"pid": {
"type": "long"
},
"message": {
"type": "text"
},
"thread": {
"type": "keyword"
},
"mdc":{
"type": "text"
},
"appid": {
"type": "keyword"
},
"moduleid": {
"type": "keyword"
},
"traceid": {
"type": "keyword"
},
"time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"locale": "zh_CN"
}
}
}
},
"priority": 500,
"version": 1,
"_meta": {
"description": "应用日志index模版"
}
}
4、filebeat 搭建配置
-
Filebeat 配置
- filebeat.yml 配置
#限制一个 CPU 核心,避免过多抢占业务资源
max_procs: 1
# 存储于内存队列的事件数,排队发送(4096)
queue.mem.events: 2048
#默认2048,增大可提高吞吐量
queue.mem.flush.min_events: 1536
filebeat.inputs:
- type: log
enabled: true
paths:
# 日志实际路径地址
- /home/logs/test-basic.log
- /home/logs/test-applog.log
fields:
# 日志标签,区别不同日志,下面建立索引会用到
ip: "192.168.0.121"
fields_under_root: true
# 指定被监控的文件的编码类型,使用plain和utf-8都是可以处理中文日志的
encoding: utf-8
# 多行日志开始的那一行匹配的pattern
multiline.pattern: '^(((?:19|20)\d\d)-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01]))\s(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?.[0-9]{3}\s+'
# 是否需要对pattern条件转置使用,不翻转设为true,反转设置为false。 【建议设置为true】
multiline.negate: true
multiline.match: after
setup.ilm.enabled: true
setup.ilm.rollover_alias: "yqfk-log"
setup.ilm.pattern: "{now/d}-000001"
setup.template.overwrite: true
#-------------------------- Elasticsearch output ------------------------------
output.elasticsearch:
enabled: true
hosts: ["192.168.0.95:9200","192.168.0.93:9200"]
username: "filebeat"
password: "****"
processors:
- drop_fields:
# 去除多余字段
fields: ["agent","input","ecs","host"]
- 启动 filebeat 开启日志收集
[root@localhost data]# cd filebeat-7.13.4-linux-x86_64/
#测试配置是否正确
./filebeat test config
Config OK
# 启动 filebeat ,-c 指定某个配置文件
./filebeat -e -c filebeat2222.yml
当上面配置完成,整个 EFK 中的 EF 就算搭建完全。接下来,我们就可以通过 kibana 配置个 列表
5、kibana
- 创建索引模式,在 Discover 中配置 列表
后续 大家就可以愉快的在 kibana 中进行日志内容的查询啦
总结
本篇内容简单的介绍EFK,同时详情介绍了 业务应用日志使用 EFK 收集搭建的全部实践过程,包含 ES的配置,Filebeat 配置,Kibana 的配置等。下一篇主要介绍业务应用日志在 EFK 中如何结合 Skywalking 进行服务链路的全面追踪,让现场问题排查更加快速。
好了,本篇内容就到这里了,我们下期见。