ELK部署以及使用

ELK实际上是三个工具的集合,Elasticsearch + Logstash + Kibana,这三个工具组合形成了一套实用、易用的监控架构,很多公司利用它来搭建可视化的海量日志分析平台。

ELK部署
Docker

docker是目前非常流行的容器化技术,可以非常方便快捷的部署服务,解决项目部署时的环境问题,实现“一次封装,到处运行”,我们采用docker可以快速的部署ELK。

Docker-compose

Docker Compose是一个用于定义和运行多个docker容器应用的工具,可以很方便的管理和编排容器。

ELK部署
  • 下载Docker-compose

    curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    
  • 修改文件权限

    chmod +x /usr/local/bin/docker-compose
    
  • 检查docker-compose是否安装成功

    docker-compose --version
    
  • 编写docker-compose.yml脚本

    version: '3'
    services:
      elasticsearch:
        image: elasticsearch:6.4.0
        container_name: elasticsearch
        environment:
          - "cluster.name=elasticsearch" #设置集群名称为elasticsearch
          - "discovery.type=single-node" #以单一节点模式启动
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m" #设置使用jvm内存大小
          - TZ=Asia/Shanghai
        volumes:
          - /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins #插件文件挂载
          - /mydata/elasticsearch/data:/usr/share/elasticsearch/data #数据文件挂载
        ports:
          - 9200:9200
          - 9300:9300
      kibana:
        image: kibana:6.4.0
        container_name: kibana
        links:
          - elasticsearch:es #可以用es这个域名访问elasticsearch服务
        depends_on:
          - elasticsearch #kibana在elasticsearch启动之后再启动
        environment:
          - "elasticsearch.hosts=http://es:9200" #设置访问elasticsearch的地址
          - TZ=Asia/Shanghai
        ports:
          - 5601:5601
      logstash:
        image: logstash:6.4.0
        container_name: logstash
        environment:
          - TZ=Asia/Shanghai
        volumes:
          - /mydata/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #挂载logstash的配置文件
        depends_on:
          - elasticsearch #kibana在elasticsearch启动之后再启动
        links:
          - elasticsearch:es #可以用es这个域名访问elasticsearch服务
        ports:
          - 4560:4560
          - 4561:4561
          - 4562:4562
          - 4563:4563
    
  • 创建容器挂载路径

    mkdir /mydata/elasticsearch/plugins
    mkdir /mydata/elasticsearch/data
    mkdir /mydata/logstash
    
    # 修改路径权限
    chmod 777 -R /mydata
    
  • 编写/mydata/logstash/logstash.conf文件

    input {
      tcp {
        mode => "server"
        host => "0.0.0.0"
        port => 4560
        codec => json_lines
        type => "debug"
      }
      tcp {
        mode => "server"
        host => "0.0.0.0"
        port => 4561
        codec => json_lines
        type => "error"
      }
      tcp {
        mode => "server"
        host => "0.0.0.0"
        port => 4562
        codec => json_lines
        type => "business"
      }
      tcp {
        mode => "server"
        host => "0.0.0.0"
        port => 4563
        codec => json_lines
        type => "record"
      }
    }
    filter{
      if [type] == "record" {
        mutate {
          remove_field => "port"
          remove_field => "host"
          remove_field => "@version"
        }
        json {
          source => "message"
          remove_field => ["message"]
        }
      }
    }
    output {
      elasticsearch {
        hosts => ["es:9200"]
        action => "index"
        codec => json
        index => "mall-tiny-%{type}-%{+YYYY.MM.dd}"
        template_name => "mall-tiny"
      }
    }
    
  • 创建容器

    在docker-compose.yml脚本所在目录下执行命令:

    docker-compose -f docker-compose.yml up -d
    

    检查容器是否启动成功

    # 显示所有已启动的容器
    docker ps
    
  • 安装Logstash的json_lines插件

    # 进入logstash容器内部
    docker exec -it logstash bash
    # 安装json_lines插件
    logstash-plugin install logstash-codec-json_lines
    
  • 访问kibana

    访问网址http://192.168.56.102:5601,改成服务器的IP,如果能访问到kibana界面,表示环境已部署成功。

Spring Boot整合ELK
  • 创建SpringBoot项目

  • pom.xml文件中加入logstash依赖

    <!--集成logstash-->
    <dependency>
      <groupId>net.logstash.logback</groupId>
      <artifactId>logstash-logback-encoder</artifactId>
      <version>5.3</version>
    </dependency>
    
  • 在resource目录下添加logback-spring.xml日志配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration>
    <configuration>
        <!--引用默认日志配置-->
        <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
        <!--使用默认的控制台日志输出实现-->
        <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
        <!--应用名称-->
        <springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="springBoot"/>
        <!--日志文件保存路径-->
        <property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/>
        <!--LogStash访问host-->
        <springProperty name="LOG_STASH_HOST" scope="context" source="logstash.host" defaultValue="localhost"/>
    
        <!--DEBUG日志输出到LogStash-->
        <appender name="LOG_STASH_DEBUG" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>DEBUG</level>
            </filter>
            <destination>${LOG_STASH_HOST}:4560</destination>
            <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp>
                        <timeZone>Asia/Shanghai</timeZone>
                    </timestamp>
                    <!--自定义日志输出格式-->
                    <pattern>
                        <pattern>
                            {
                            "project": "mall-tiny",
                            "level": "%level",
                            "service": "${APP_NAME:-}",
                            "pid": "${PID:-}",
                            "thread": "%thread",
                            "class": "%logger",
                            "message": "%message",
                            "stack_trace": "%exception{20}"
                            }
                        </pattern>
                    </pattern>
                </providers>
            </encoder>
            <!--当有多个LogStash服务时,设置访问策略为轮询-->
            <connectionStrategy>
                <roundRobin>
                    <connectionTTL>5 minutes</connectionTTL>
                </roundRobin>
            </connectionStrategy>
        </appender>
    
        <!--ERROR日志输出到LogStash-->
        <appender name="LOG_STASH_ERROR" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
            <destination>${LOG_STASH_HOST}:4561</destination>
            <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp>
                        <timeZone>Asia/Shanghai</timeZone>
                    </timestamp>
                    <!--自定义日志输出格式-->
                    <pattern>
                        <pattern>
                            {
                            "project": "mall-tiny",
                            "level": "%level",
                            "service": "${APP_NAME:-}",
                            "pid": "${PID:-}",
                            "thread": "%thread",
                            "class": "%logger",
                            "message": "%message",
                            "stack_trace": "%exception{20}"
                            }
                        </pattern>
                    </pattern>
                </providers>
            </encoder>
            <!--当有多个LogStash服务时,设置访问策略为轮询-->
            <connectionStrategy>
                <roundRobin>
                    <connectionTTL>5 minutes</connectionTTL>
                </roundRobin>
            </connectionStrategy>
        </appender>
    
        <!--业务日志输出到LogStash-->
        <appender name="LOG_STASH_BUSINESS" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
            <destination>${LOG_STASH_HOST}:4562</destination>
            <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp>
                        <timeZone>Asia/Shanghai</timeZone>
                    </timestamp>
                    <!--自定义日志输出格式-->
                    <pattern>
                        <pattern>
                            {
                            "project": "mall-tiny",
                            "level": "%level",
                            "service": "${APP_NAME:-}",
                            "pid": "${PID:-}",
                            "thread": "%thread",
                            "class": "%logger",
                            "message": "%message",
                            "stack_trace": "%exception{20}"
                            }
                        </pattern>
                    </pattern>
                </providers>
            </encoder>
            <!--当有多个LogStash服务时,设置访问策略为轮询-->
            <connectionStrategy>
                <roundRobin>
                    <connectionTTL>5 minutes</connectionTTL>
                </roundRobin>
            </connectionStrategy>
        </appender>
    
        <!--接口访问记录日志输出到LogStash-->
        <appender name="LOG_STASH_RECORD" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
            <destination>${LOG_STASH_HOST}:4563</destination>
            <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp>
                        <timeZone>Asia/Shanghai</timeZone>
                    </timestamp>
                    <!--自定义日志输出格式-->
                    <pattern>
                        <pattern>
                            {
                            "project": "mall-tiny",
                            "level": "%level",
                            "service": "${APP_NAME:-}",
                            "class": "%logger",
                            "message": "%message"
                            }
                        </pattern>
                    </pattern>
                </providers>
            </encoder>
            <!--当有多个LogStash服务时,设置访问策略为轮询-->
            <connectionStrategy>
                <roundRobin>
                    <connectionTTL>5 minutes</connectionTTL>
                </roundRobin>
            </connectionStrategy>
        </appender>
    
        <!--控制框架输出日志-->
        <logger name="org.slf4j" level="INFO"/>
        <logger name="springfox" level="INFO"/>
        <logger name="io.swagger" level="INFO"/>
        <logger name="org.springframework" level="INFO"/>
        <logger name="org.hibernate.validator" level="INFO"/>
    
        <root level="DEBUG">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="LOG_STASH_DEBUG"/>
            <appender-ref ref="LOG_STASH_ERROR"/>
        </root>
    
        <logger name="com.shuguangtj.efk.component" level="DEBUG">
            <appender-ref ref="LOG_STASH_RECORD"/>
        </logger>
    
        <logger name="com.shuguangtj.efk" level="DEBUG">
            <appender-ref ref="LOG_STASH_BUSINESS"/>
        </logger>
    </configuration>
    

    pattern中定义的字段会对应ES中日志index的字段

  • application.yml配置

    logstash:
      host: 192.168.56.102 # ELK所在服务的IP
    logging:
      level:
        root: debug
    
  • 启动项目,并在项目中输出日志

    @GetMapping(value = "/sayHello")
    public String sayHello() {
      LOG.debug("debug hello");
      LOG.info("info hello");
      LOG.warn("warning hello");
      LOG.error("error hello");
    
      throw new RuntimeException("system error");
    }
    
使用ELK
  • 进入kibana界面

    访问http://192.168.56.102:5601
    在这里插入图片描述

  • 创建index Pattern

    如果ELK环境搭建成功了,可以看到logstash已经将项目日志传输到ES了

    在这里插入图片描述

    创建index pattern,index pattern就是ES的索引(index),ES中的每个索引对应一个日志文件
    在这里插入图片描述

  • 查看日志

    可以根据上面创建的index pattern进行过滤
    在这里插入图片描述

    可以看到,在logback-spring.xml文件中的pattern中定义的字段,都映射到ES的index中了

    <pattern>
      {
        "project": "mall-tiny",
        "level": "%level",
        "service": "${APP_NAME:-}",
        "class": "%logger",
        "message": "%message"
      }
    </pattern>
    

    也可以指定过滤条件,注意AND要大写

    在这里插入图片描述

    还可以设置搜索提示
    在这里插入图片描述

    再输入检索条件时会出现提示
    在这里插入图片描述

    还可以指定显示的字段
    在这里插入图片描述

    还可以对日志进行管理
    在这里插入图片描述
    在这里插入图片描述

    暂时还没找到怎么下载日志文件,可以在kibana中对日志进行检索,找到对应的index(日志文件名)之后到部署项目的服务器上下载日志文件(前提是日志有输出到日志文件中)

    如果不想使用kibana提供的日志检索工具,也可以直接写ES查询语句对日志进行检索

    在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐