ELK 日志采集系统搭建

日志分析 ELK elk日志系统搭建_Elastic

一般我们需要进行日志分析场景:直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询。需要集中化的日志管理,所有服务器上的日志收集汇总。
常见解决思路是建立集中式日志收集系统,将所有节点上的日志统一收集,管理,访问。一般大型系统是一个分布式部署的架构,不同的服务模块部署在不同的服务器上,问题出现时,大部分情况需要根据问题暴露的关键信息,定位到具体的服务器和服务模块,构建一套集中式日志系统,可以提高定位问题的效率。
ELK提供了一整套解决方案,并且都是开源软件,之间互相配合使用,完美衔接,高效的满足了很多场合的应用。目前主流的一种日志系统。

1. 架构

ELK是Elasticsearch+Logstash+Kibana简称.

  • Elasticsearch 是一个分布式的搜索和分析引擎,可以用于全文检索、结构化检索和分析,并能将这三者结合起来。Elasticsearch 基于 Lucene 开发,现在是使用最广的开源搜索引擎之一。
  • Logstash 简单来说就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端,与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供了很多功能强大的滤网以满足你的各种应用场景。
  • Kibana 是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看、交互存放在Elasticsearch索引里的数据,使用各种不同的图标、表格、地图等,kibana能够很轻易的展示高级数据分析与可视化。

一个简单的 ELK 架构图如下:

日志分析 ELK elk日志系统搭建_日志分析 ELK_02

在这种架构中,Logstash 通过输入插件从多种数据源(比如日志文件、标准输入 Stdin 等)获取数据,再经过滤插件加工数据,然后经 Elasticsearch 输出插件输出到 Elasticsearch,通过 Kibana 进行可视化展示。

这种架构非常简单,使用场景也有限。初学者可以搭建这个架构,了解 ELK 工作模式, 但是生产环境中并不推荐. 如要有以下问题:

  • Logstash 依赖 java、在数据量大的时候,Logstash 进程会消耗过多的系统资源,这将严重影响业务系统的性能。因此官网现已经推荐通过 filebeat 代替 Logstash Agent。
  • Logstash 将资源耗尽系统或者其自身出故障的问题时,日志数据将会出现丢失等问题,因此引入 Kafka 集群作为消息缓冲队列以提高数据传输的可靠性和稳定性。

如此一来, 此架构特别适合大型集群、海量数据的业务场景,它通过将前端 Logstash Agent 替换成 filebeat,有效降低了收集日志对业务系统资源的消耗。同时,消息队列使用kafka集群架构,有效保障了收集数据的安全性和稳定性,而后端Logstash和Elasticsearch均采用集群模式搭建,从整体上提高了ELK系统的高效性、扩展性和吞吐量。
推荐的架构图如下:

日志分析 ELK elk日志系统搭建_elk_03

2. 环境搭建

本文首先采用最简单的架构方式进行搭建, 后续博文将一步一步完善到生产环境集成消息队列的架构方式.
本次环境采用 Docker 或者 DockerCompose 搭建, 如果还不能熟练使用麻溜去看帅帅之前发布的 Docker 全家桶系列视频教程:

版本如下:

  • Elasticsearch: 6.8.16
  • Logstash: 6.8.16
  • Kibana: 6.8.16

2.1 拉取镜像创建网络

docker pull elasticsearch:6.8.16
docker pull kibana:6.8.16
docker pull docker.elastic.co/logstash/logstash:6.8.16
# 创建 ELK 运行的网络
docker network create elastic

2.2 ElasticSearch

  • 配置 elasticsearch.yml
cluster.name: "es-docker-cluster"
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"
  • 安装与启动

通过如下 Docker 命令:

docker run -d --name elasticsearch --network elastic \
-p 9200:9200 -p 9300:9300 \
-e node.name=esNode -e cluster.name=es-docker-cluster -e discovery.type=single-node \
-e bootstrap.memory_lock=true -e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" \
-v ${CONF_DIR}/es:/usr/share/elasticsearch/config \
-v ${VOLUME_DATA_DIR}/es:/usr/share/elasticsearch/data \
-v ${LOGS_DIR}/es:/usr/share/elasticsearch/logs \
elasticsearch:6.8.16

其中, CONF_DIR, VOLUME_DATA_DIR, LOGS_DIR 是我本地配置的环境变量, 指向一个固定的文件夹用于挂载 Docker 容器的配置文件, 数据卷和日志文件.

  • 测试

访问 http://localhost:9200/ 看到如下界面就表示 Elasticsearch 启动成功.

日志分析 ELK elk日志系统搭建_Elastic_04

2.3 Kibana

  • 配置 kibana.yml
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://elasticsearch:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
  • 安装
docker run -d --name kibana --network elastic \
-p 5601:5601 \
--link elasticsearch:elasticsearch \
-e ELASTICSEARCH_URL=http://elasticsearch:9200 \
-e ELASTICSEARCH_HOSTS='["http://elasticsearch:9200"]' \
-v ${CONF_DIR}/kibana:/usr/share/kibana/config \
kibana:6.8.16
  • 测试

访问 http://localhost:5601/ 看到如下界面就表示 Kibana 启动成功.

日志分析 ELK elk日志系统搭建_日志分析 ELK_05

2.4 Logstash

  • 配置 logstash.yml
http.host: "0.0.0.0"
xpack.monitoring.elasticsearch.hosts: [ "http://elasticsearch:9200" ]
xpack.monitoring.enabled: true
  • 配置 pipeline/logstash.conf 指定 logstash 输入输出
# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.

input {
  tcp {
    id => "toEs"
    mode => "server"
    host => "0.0.0.0"
    port => 9600
    codec => json_lines
  }
}

filter {
}

output {
  stdout {
    codec => rubydebug
  }

  elasticsearch {
    hosts => ["elasticsearch:9200"]
    action => "index"
    index => "applog"
  }
}

从 9600 端口获取数据并做两个输出, 一个输出到标准输出, 一个是通过 Elasticsearch 插件写入 Elasticsearch, 且写入 Elasticsearch 时索引名为 <applog>

  • 启动
docker run -d --name logstash --network elastic \
-p 5044:5044 -p 9600:9600 \
--link elasticsearch:elasticsearch \
-v ${CONF_DIR}/logstash/config/:/usr/share/logstash/config/ \
-v ${CONF_DIR}/logstash/pipeline/:/usr/share/logstash/pipeline/ \
docker.elastic.co/logstash/logstash:6.8.16
  • 检查是否启动成功
  • 通过 logstash 启动日志查看

日志分析 ELK elk日志系统搭建_elk_06

  • 通过 KIbana: 进入 Kibana 的 monitoring 视图

日志分析 ELK elk日志系统搭建_elk_07


日志分析 ELK elk日志系统搭建_elasticsearch_08

当在 Kibana 中看到 Elasticsearch, Kibana, Logstash 都启动成功就表明我们 ELK 环境搭建就完成了.

3. 集成 SpringBoot, 并将日志写入 ELK

准备一个 SpringBoot 测试环境:

  • SpringBoot 版本: 2.4.1
  • logback 版本: 1.2.4

3.1 引入依赖

<dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>6.6</version>
</dependency>

需要特别注意的是 Spring boot web 环境中携带了 spring-boot-starter-logging, logback-core, logback-classic, logback-access 这几个必要包, 但是版本可能和 Logstash 不匹配, 因此最好是在 dependencyManagement 中对版本进行管理控制.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>${logback.version}</version>
        </dependency>

    </dependencies>
</dependencyManagement>

3.2 配置 logback

在 类路径 resources 下新建 logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
   <include resource="org/springframework/boot/logging/logback/base.xml" />
   <contextName>logback</contextName>
  <!-- 指定日志写入本机 9600 端口 -->
   <appender name="stash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
      <destination>127.0.0.1:9600</destination>
      <!-- encoder必须配置,有多种可选 -->
      <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
   </appender>

   <root level="info">
      <appender-ref ref="stash" />
      <appender-ref ref="CONSOLE" />
   </root>
</configuration>

3.3 编写测试方法

@RestController
public class TestLoggingController {

   @GetMapping("/logging")
   public void testLogging() {
      LOGGER.info("Come in test logging...");

      LOGGER.debug("这是一个 Debug 级别的日志");
      LOGGER.info("这是一个 INFO 级别的日志");
      LOGGER.warn("这是一个 WARN 级别的日志");
      LOGGER.error("这是一个 ERROR 级别的日志");
      LOGGER.error("这是一个 ERROR 级别的日志, 并携带了一个 Exception.",
         new UnsupportedOperationException("暂不支持操作的异常!"));
   }

3.4 测试

访问 http://localhost/logging (端口改为了 80)

  • Logstash 后台可以看到如下输出(因为logstash.conf引入了标准输出组件)
  • 日志分析 ELK elk日志系统搭建_elasticsearch_09

  • Kibana/Management 可以看到索引 applog 已经被创建, 加入 Index Pattern

日志分析 ELK elk日志系统搭建_elk_10

日志分析 ELK elk日志系统搭建_日志分析 ELK_11

日志分析 ELK elk日志系统搭建_Elastic_12

进入 Discover 即可看到日志已经在 Kibana 中可以可视化

日志分析 ELK elk日志系统搭建_Elastic_13

至此, ELK 日志采集系统便已经成功搭建完成.

4. 下一步

后面我们会对这个架构所存在的问题逐一进行验证和解决, 最终达到一个生产环境高可用的架构模式. 大家持续关注!

既然大侠已经看到这里了, 那小弟也不藏着掖着了, 公众号后台回复**ELK** 即可拿到帅帅整理好的 ELK docker compose 配置文件, 一个 up 命令启动 ELK, 一个 down 命令停止 ELK, 它 不香吗?

日志分析 ELK elk日志系统搭建_日志分析 ELK_14