EFK应用日志收集最佳实践(一)

1,162 阅读7分钟

我正在参加「掘金·启航计划」

前言

随着微服务的普及,不知道小伙伴会不会有这种困扰,当现场发生问题时,应用服务器又非常多,排查现场问题将变成一件非常耗时又麻烦的事情;首先,需要和实施小伙伴进行沟通,进入 各个服务器查看应用日志信息,同时从日志文件中检索出重要的日志内容进行问题的排查。这里面的沟通成本,日志文件分布各地,文本类型文件的检索等问题,导致排查问题过程非常耗时,不知道 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 字段中,需要进行分割等操作。

  1. 定义日志的索引生命周期策略 ilm policy

创建索引生命周期策略,对于日志相关内容,一般我们只需保留最近几天的日志,更关注的是实时日志排查,或者现场某个时间的日志信息。 日志生命周期策略为 当达到 30 G ,或者 1天 时,索引进行自动滚动,当索引创建 2 周后,自动删除索引。

  • Kibana ==>stack Management => 索引生命周期 进行 生命周期策略配置

  1. 定义日志内容处理管道 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
      }
    }
  ]
}
  1. 定义 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 进行服务链路的全面追踪,让现场问题排查更加快速。

好了,本篇内容就到这里了,我们下期见。