热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用filebeat采集分布式系统日志

前言程序猿和运维几乎每天都需要和日志打交道,不同维度下可以区分多类日志。如windows

前言


程序猿和运维几乎每天都需要和日志打交道,不同维度下可以区分多类日志。
如windows操作系统会将收集到的日志在

【计算机管理】→【系统工具】→【事件查看器】→【windows日志】。
Linux操作系统则通过syslog服务采集内核日志与非内核日志,一般存储在/var/log目录下。


上面都是系统层面的日志,我们自身研发后的各项服务最终投产后都会产生日志,在单体应用场景下日志查看很方便也很直接,可以存储到指定的目录下,出现问题直接到该目录打开日志通过关键字定位进行问题排查(当然关键日志也可以存储到数据库,后续通过sql方式排查)。


但是在分布式服务环境下,每个服务的日志都在各自的目录下甚至是直接在容器内,如果还是采取单体应用的方式进行日志检索的话效率太低了。这个时候就需要引入一个或N个中间件来解决这些烦恼了。


下图是我随意画的一张微服务场景下的日志管理流程图。

s1、s2、s3是日志的生产者(即我们的服务应用),logCenter是一个抽象化的持久层,可以是一个文件夹目录,也可以是Redis、ElasticSearch等任何能接收数据的中间件或数据库,它们用于存储采集后的日志,view则是日志的展示层,它负责从locCenter提取数据展示。如果需要对日志进行进一步的处理可以在logCenter采集到数据后先推送到数据处理中间件然后再推送到持久层(Logstash就是起这个作用),当然目前版本的beatfile其实已经具备了日志处理的能力,所以我下面的例子也是直接使用beatfile对日志进行处理后推送到持久层。


分布式系统日志管理方案

常见的分布式日志管理方案有下面几种
ElasticSearch + Logstash + Kibana
ElasticSearch + Fluentd + Kibana
ElasticSearch + Filebeat + Kibana
Loki + Promtail  +Grafana


上面的方案均提供开源版本,其中有三种都是依赖了ElasticSearch(ES)作为日志的持久层。其中Logstash、Fluentd、Filebeat、Promtail均用于采集日志。对于日志的采集Filebeat可以说是里面性价比最高的组件(除Promtail外,Promtail不熟悉不妄下定论),资源消耗小,完善的配置,特别适合云服务器租不起的同志们~

本篇博客主要对filebeat进行讲解,下面就步入正题!


filebeat介绍

filebeat工作流程如下(摘自官网)

fillebeat由以下几个重要组件组成

  • input

  • harvester

  • processors

  • output

我们通过filebeat.yml配置文件可以对以上组件进行配置,filebeat启动后通过读取filebeat.yml配置文件制定日志采集流程。


input

input是filebeat的输入层,input支持多种类型,如log、docker、container、mqtt、filestream ...
filebeat.yml配置文件中通过filebeat.inputs配置项进行inpu的配置, 配置方式如下:

    filebeat.inputs:
    - type: log
    paths:
    - usr/local/src/efk/*.log

    如上面配置filebeat的输入类型为log,paths接收多个需采集日志的目录。比如下面的配置,表示从多个目录进行日志采集:

      filebeat.inputs:
      - type: log
      paths:
      - usr/local/src/efk/*.log
      - usr/local/src/srv/*.log

      filebeat也支持多个输入类型,如下配置:

        filebeat.inputs:
        - type: log
        paths:
        - usr/local/src/efk/*.log
        - usr/local/src/efk/*/*.log
        - type: container
        paths:
        - '/var/lib/docker/containers/*/*.log'

         如果想对当前目录下以及子目录下所有日志进行采集需要如下配置:

          filebeat.inputs:
          - type: log
          paths:
          - usr/local/src/efk/**/*.log


          filebeat 将会把 `/**/` 翻译成 8 层的子目录,

          假如指定了 /home/data/**/my*.log 那么等同的效果如下:

            /home/data/my*.log
            /home/data/*/my*.log
            /home/data/*/*/my*.log
            /home/data/*/*/*/my*.log
            /home/data/*/*/*/*/my*.log
            /home/data/*/*/*/*/*/my*.log
            /home/data/*/*/*/*/*/*/my*.log
            /home/data/*/*/*/*/*/*/*/my*.log
            /home/data/*/*/*/*/*/*/*/*/my*.log

            so,我们最终的配置如下:

              filebeat.inputs:
              - type: log
              paths:
              - usr/local/src/efk/**/*.log
              - type: container
              paths:
              - '/var/lib/docker/containers/*/*.log'

              tips

              注意上面input的type有container、docker两个类型, 我第一次见就傻傻分不清楚,不知道使用哪一个type才可以对容器的日志进行采集。
              答案是都可以,只是两者处理方式有所不同。

              container 是需要我们显示的提供容器的日志文件目录

              docker 是通过提供容器本身的反方式给filebeat。
              docker类型的input配置如下所示,

                ## 采集指定的docker容器日志
                filebeat.inputs:
                - type: docker
                containers.ids:
                - '8b6fe7dc9e067b58476dc57d6986dd96d7100430c5de3b109a99cd56ac655347'


                ## 采集所有的docker容器日志
                filebeat.inputs:
                - type: docker
                containers.ids:
                - '*'

                containers.ids是一个非空配置项,允许提供多个容器ID,也可以通过传入 * 表示所有容器。

                docker类型下的其他可选配置(部分关键的配置):

                配置项名
                配置说明

                containers.path

                docker日志所在的基本路径。

                默认值是/var/lib/docker/containers

                containers.paths

                容器日志路径列表,如有些docker容器我们人为变更了他们的日志存储地址则需要在此处声明,该参数为一个集合,与上面的containers.path配置同时存在时containers.path配置会被忽略

                exclude_linesedit

                使用正则表达式过滤不需要采集的日志信息

                include_linesedit

                使用正则表达式约定需要采集的日志信息


                harvester

                harvester是filebeat在读取配置后对日志实施采集时启动的一个服务,该服务工作范畴就是日志采集。filebeat读取filebeat.yml配置文件后根据inputs启动harvester,harvester对日志文件进行逐行读取,读取的内容会放置缓冲区,后续通过processors执行完毕后推送给输出方。


                processors

                processors负责对采集的日志进行过滤、和加工。也是通过在filebeat.yml配置文件中预先设定processors的过滤规则,也是得益于processors的存在我才可以不需要引入Logstash。
                processors允许加入多个处理器,处理流程如下:

                  event -> processor 1 -> event1 -> processor 2 -> event2 ...

                  以下配置示例将删除所有调试消息。

                    processors:
                    - drop_event:
                    when:
                    regexp:
                    message: "^DBG:"

                    output


                    output为输出,filebeat提供多个输出方式:

                    • Console

                    • Log

                    • ElasticSearch

                    • Redis

                    • Kafka

                    • Logstash

                    • 其他不常用的组件



                    控制台输出配置:

                      # 控制台输出
                      output.console:
                      pretty: true

                      Log输出配置:


                        output.file:
                        path: "/tmp/filebeat"
                        filename: filebeat

                        ElasticSearch输出配置:

                          output.elasticsearch:
                          hosts: ["https://myEShost:9200"]

                          这里需要注意的是output不像input可以定义多个,output只能在配置文件定义一次,如果需要对同一日志输出到不同的数据源则引入kafka或redis进行分发。


                          常见问题

                          问:filebeat如何处理多行日志(将多行日志合并成一行)
                          答:使用multiline相关配置项对日志信息进行格式化。假设日志样例数据如下

                            [2015-08-24 11:49:14,389] [INFO] [MESSAGE]

                            可以使用下面的配置对日志进行格式化:

                              multiline.pattern: '^\[[0-9]{4}-[0-9]{2}-[0-9]{2}'
                              multiline.negate: true
                              multiline.match: after

                              需注意!multiline相关配置项需放置filebeat.inputs配置下

                              如:

                                filebeat.inputs:
                                - type: log
                                paths:
                                - usr/local/src/efk/**/*.log


                                multiline.pattern: '^\[[0-9]{4}-[0-9]{2}-[0-9]{2}'
                                multiline.negate: true
                                multiline.match: after

                                • multiline.pattern (指定用于匹配多行的正则表达式)

                                • multiline.negate (定义模式是否被否定。默认false)

                                • multiline.match (指定filebeat如何把多行合并成一个事件。可选的值是 after 或者 before)

                                • multiline.max_lines (可以合并成一个事件的最大行数。如果一个多行消息包含的行数超过max_lines,则超过的行被丢弃。默认是500)


                                测试

                                目标:在配置为4G内存双核CPU的CentOS7.0版本的Linux操作系统上使用docker部署ElasticSearch + Filebeat + Kibana,将下面日志输出到ElasticSearch并在Kibana上展示出来。

                                样例日志内容如下:

                                  [2021-04-22 19:26:24.585] [INFO] [http-nio-8100-exec-8-63] [serviceDemo] [1] [api.service.service.impl.CollectServiceImpl,collect] [日志信息={"remark":"这是测试数据"}

                                  过程:
                                  1、编写docker-compose.ym

                                    version: "3"
                                    services:


                                    elasticsearch:
                                    image: "docker.elastic.co/elasticsearch/elasticsearch:7.12.0"
                                    hostname: "elasticsearch"
                                    container_name: "elasticsearch"
                                    environment:
                                    - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
                                    - "discovery.type=single-node"
                                    restart: unless-stopped
                                    privileged: true
                                    ports:
                                    - "9200:9200"
                                    volumes:
                                    - elasticsearch_data:/usr/share/elasticsearch/data
                                    - /usr/local/src/efk/elasticsearch/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
                                    networks:
                                    hy-net:
                                    ipv4_address: 172.16.238.111


                                    kibana:
                                    image: "docker.elastic.co/kibana/kibana:7.12.0"
                                    hostname: "kibana"
                                    container_name: "kibana"
                                    restart: unless-stopped
                                    privileged: true
                                    ports:
                                    - "5601:5601"
                                    volumes:
                                    - /usr/local/src/efk/kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml
                                    networks:
                                    hy-net:
                                    ipv4_address: 172.16.238.112


                                    filebeat:
                                    image: "docker.elastic.co/beats/filebeat:7.12.0"
                                    hostname: "filebeat"
                                    container_name: "filebeat"
                                    restart: unless-stopped
                                    privileged: true
                                    user: root
                                    volumes:
                                    - /usr/local/src/efk/filebeat/conf/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
                                    - /usr/local/src/efk/filebeat/logs:/usr/share/filebeat/logs
                                    - /var/lib/docker:/var/lib/docker:ro
                                    - /var/run/docker.sock:/var/run/docker.sock
                                    - /usr/local/src/efk/:/usr/local/src/efk/
                                    networks:
                                    hy-net:
                                    ipv4_address: 172.16.238.114


                                    volumes:
                                    elasticsearch_data:


                                    networks:
                                    hy-net:
                                    external:
                                    name: hy-net

                                    需注意!上面的hy-net网络是本人之前已经提前创建好的docker自定义网络。

                                    2、创建filebeat.yml,路径是上面filebeat的数据卷信息 /usr/local/src/efk/filebeat/conf/filebeat.yml

                                     

                                      filebeat.inputs:
                                      - type: log
                                      paths:
                                      - /usr/local/src/efk/**/*.log


                                      multiline.pattern: '^\[[0-9]{4}-[0-9]{2}-[0-9]{2}'
                                      multiline.negate: true
                                      multiline.match: after


                                      - type: container
                                      paths:
                                      - '/var/lib/docker/containers/*/*.log'


                                      processors:
                                      - add_docker_metadata:
                                      host: "unix:///var/run/docker.sock"


                                      - decode_json_fields:
                                      fields: ["message"]
                                      target: "json"
                                      overwrite_keys: true


                                      output.elasticsearch:
                                      hosts: ["elasticsearch:9200"]
                                      index: "filebeat-%{+yyyy.MM.dd}"
                                      indices:
                                      - index: "filebeat-%{+yyyy.MM.dd}"


                                      setup.template.name: "filebeat-"
                                      setup.template.pattern: "filebeat-*"
                                      setup.dashboards.enabled: true
                                      setup.kibana:
                                      host: "kibana:5601"

                                      3、创建数据卷相关路径以及测试用的日志文件;

                                      4、在docker-compose.yml路径下执行命令

                                        docker-compose up -d

                                        打开kibana查看日志结果如下:

                                        ok,至此已经在目标服务器上使用Docker部署了一套日志平台,接下来修饰下相关字段,调整下日志格式基本上就OK了,当然线上环境还需要增加ElasticSearch的认证配置。



                                        推荐阅读
                                        author-avatar
                                        一个字-刘斌
                                        这个家伙很懒,什么也没留下!
                                        PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
                                        Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有