ELK部署以及使用

本文详细介绍了如何使用Docker和Docker Compose快速部署ELK(Elasticsearch、Logstash和Kibana)集群,包括配置文件编写、容器挂载和SpringBoot集成。通过实例展示,从安装到日志管理的全过程。

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查询语句对日志进行检索

    在这里插入图片描述

### ELK Stack 部署最佳实践 #### 准备工作环境 为了确保能够顺利连接至目标虚拟机,在AWS上运行的Ubuntu 16.04实例被选作部署平台。这一步骤对于后续操作至关重要,因为所有配置都将在此环境中执行[^1]。 #### 安装必要的组件 考虑到Kibana是由Node.js编写的这一事实,当涉及到SSL/TLS加密通信时需要注意特定细节。如果遇到`.p12`格式证书不兼容的情况,则需将其转换成PEM格式以便于使用。此过程可通过命令行工具OpenSSL完成: ```bash openssl pkcs12 -in elastic-stack-ca.p12 -out elastic-stack-ca.pem ``` 上述指令实现了从PKCS#12到PEM格式的安全证书文件转换,从而解决了可能存在的认证问题[^2]。 #### 使用Ansible自动化部署流程 采用Ansible作为配置管理工具来进行ELK堆栈的自动部署是一种高效的方法。通过编写Playbook脚本来定义服务器状态以及所需软件包版本等参数,可极大简化复杂系统的初始化设置并提高一致性。 #### 数据收集与传输优化 针对日志和其他类型的数据采集任务,推荐利用Beats系列中的Filebeat实现轻量化且高效的源端处理机制;而对于应用性能监测需求而言,Elastic APM提供了全面的支持方案。这些工具不仅有助于减轻中央节点负担,还能增强整体架构灵活性和响应速度[^5]。 #### 日志存储及检索效率提升 为了让用户获得更好的体验效果,在设计索引模式时应充分考虑查询频率较高的字段组合情况,并适当调整分片数量以平衡读写负载分布。此外,合理规划冷热数据分离策略同样重要——即将较旧的历史记录迁移至成本更低廉但访问延迟稍高的介质中保存。 #### 可视化展示与告警设定 一旦整个系统搭建完毕之后,就可以借助Kibana的强大可视化能力来构建个性化的仪表板页面了。除了直观呈现各类统计图表外,还允许定制复杂的过滤条件表达式用于实时跟踪异常事件的发生趋势。更重要的是,及时建立有效的预警通知渠道可以帮助运维人员迅速察觉潜在风险所在,进而采取相应措施加以防范[^3]。 #### 处理UDP协议下的日志输入挑战 面对某些特殊场景下无法改变现有网络通讯方式的问题,可以探索基于异步I/O框架(例如libev)开发自定义解决方案的可能性。这种方式能够在保持原有协议不变的前提下有效解决高并发条件下消息丢失的风险,同时保证较低延迟能力满足实际业务要求[^4]。 ```python import socket from threading import Thread def udp_listener(host='localhost', port=9600): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = (host, port) try: sock.bind(server_address) while True: data, address = sock.recvfrom(4096) # Process received message here finally: sock.close() if __name__ == '__main__': listener_thread = Thread(target=udp_listener) listener_thread.start() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值