docker-compose部署ELK

God-slayer發表於2024-05-03

參考地址:https://www.cnblogs.com/zys2019/p/14816634.html

1. 概述

筆者在學習docker的相關知識,本著talk is cheap show me the code 原則,實際操作下,正好上面的博主分享了文件,我照著做成功了,只是有些細節上面的問題,需要解決下

2. ELK架構

  1. Elasticsearch是個開源分散式搜尋引擎,提供蒐集、分析、儲存資料三大功能。
  2. Logstash 主要是用來日誌的蒐集、分析、過濾日誌的工具,支援大量的資料獲取方式。
  3. Kibana 也是一個開源和免費的工具,Kibana可以為 Logstash 和 ElasticSearch 提供的日誌分析友好的 Web 介面,可以幫助彙總、分析和搜尋重要資料日誌。

img

2.1. 部署ELK

建立docker-elk目錄,在此目錄建立檔案和其他目錄

mkdir /opt/docker_elk

建立logstash配置檔案

mkdir /opt/docker_elk/logstash
touch  /opt/docker_elk/logstash/logstash.conf

配置logstash.conf

input {
  tcp {
    mode => "server"
    host => "0.0.0.0"
    port => 4560
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "logstash-%{+YYYY.MM.dd}"
  }
  stdout { codec => rubydebug }
}

建立docker-compose.yml檔案 , touch /opt/docker_elk/docker-compose.yml

version: '3.7'
services:
  elasticsearch:
    image: elasticsearch:7.6.2
    container_name: elasticsearch
    privileged: true
    user: root
    environment:
      #設定叢集名稱為elasticsearch
      - cluster.name=elasticsearch 
      #以單一節點模式啟動
      - discovery.type=single-node 
      #設定使用jvm記憶體大小
      - ES_JAVA_OPTS=-Xms512m -Xmx512m 
    volumes:
      - /opt/docker_elk/elasticsearch/plugins:/usr/share/elasticsearch/plugins
      - /opt/docker_elk/elasticsearch/data:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
      - 9300:9300
    networks:
      - elk-network

  logstash:
    image: logstash:7.6.2
    container_name: logstash
    ports:
       - 4560:4560
    privileged: true
    environment:
      - TZ=Asia/Shanghai
    volumes:
      #掛載logstash的配置檔案
      - /opt/docker_elk/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf 
    depends_on:
      - elasticsearch 
    links:
      #可以用es這個域名訪問elasticsearch服務
      - elasticsearch:es 
    networks:
      - elk-network

  kibana:
    image: kibana:7.6.2
    container_name: kibana
    ports:
        - 5601:5601
    privileged: true
    links:
      #可以用es這個域名訪問elasticsearch服務
      - elasticsearch:es 
    depends_on:
      - elasticsearch 
    environment:
      #設定訪問elasticsearch的地址
      - elasticsearch.hosts=http://es:9200
    networks:
      - elk-network

networks:
  elk-network:
    driver: bridge

進入docker_elk目錄 啟動docker-compose

#啟動
docker-compose up -d

#關閉
docker-compose down

#重啟某個容器
docker-compose restart logstash

2.2. kibana

輸入http://192.168.56.188:5601/,訪問Kibana web介面。點選左側設定,進入Management介面

img

點選index pattern,船艦logstash-*索引

img

2.3. log4j記錄日誌

要使用log4j2,則必須排除SpringBoot自帶的日誌。

  1. 排除logback並匯入依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <!-- 引入log4j日誌時需去掉預設的logback -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- 日誌管理log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>
  1. 在資源目錄下新建log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--日誌級別以及優先順序排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--
    status="warn" Configuration後面日誌框架本身的輸出日誌級別,可以不加入
    monitorInterval="5" 自動載入配置檔案的間隔時間, 不低於 5 秒
    注: 我們的配置檔案修改後在生產環境下無需重啟應用, 可以實現熱更新的效果
-->
<Configuration monitorInterval="5">

    <!--全域性屬性-->
    <Properties>
        <Property name="APP_NAME">coding</Property>
        <Property name="LOG_FILE_PATH">/Users/A-Study/logs/${APP_NAME}</Property>
        <Property name="PATTERN_FORMAT">%date{yyyy-MM-dd HH:mm:ss.SSS}$$%mdc{logId}$$%mdc{hostName}$$%mdc{ip}$$%level$$%mdc{module}$$%class$$%method$$%msg%n</Property>
    </Properties>

    <!--輸出源-->
    <Appenders>

        <!--輸出到控制檯-->
        <Console name="Console" target="SYSTEM_OUT"><!--輸出的型別SYSTEM_ERR-->
            <PatternLayout pattern="${PATTERN_FORMAT}"/>
        </Console>

        <!--輸出到logstash的appender-->
        <Socket name="Socket" host="192.168.56.188" port="4560" protocol="TCP">
            <!--輸出到logstash的日誌格式-->
            <PatternLayout pattern="${PATTERN_FORMAT}"/>
        </Socket>

        <!--輸出info資訊日誌到檔案 用來定義超過指定大小自動刪除舊的建立新的的Appender.-->
        <RollingFile name="RollingInfoFile" fileName="${LOG_FILE_PATH}/info.log"
                filePattern="${LOG_FILE_PATH}/$${date:yyyyMM}/info-%d{yyyyMMdd}-%i.log.gz">
            <!--控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch)-->
            <Filters>
                <ThresholdFilter level="warn" onMatch="DENY"
                        onMismatch="NEUTRAL"/>  <!--高於warn級別就放行,低於這個級別就攔截-->
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>

            <PatternLayout>
                <pattern>${PATTERN_FORMAT}</pattern> <!--檔案路徑-->
            </PatternLayout>

            <!--設定檔案具體拆分規則-->
            <Policies>
                <!--在系統啟動時, 觸發拆分規則,生產一個新的日誌檔案-->
                <OnStartupTriggeringPolicy/>
                <!--按照檔案大小拆分, 30 MB -->
                <SizeBasedTriggeringPolicy size="30 MB"/>
                <!--按照時間節點拆分, 規則根據filePattern定義的-->
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <!--在同一個目錄下,檔案的個數限定為 30 個, 超過進行覆蓋-->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>

        <!--輸出錯誤日誌到檔案-->
        <RollingFile name="RollingErrorFile" fileName="${LOG_FILE_PATH}/error.log"
                filePattern="${LOG_FILE_PATH}/$${date:yyyyMM}/error-%d{yyyyMMdd}-%i.log.gz">
            <!--控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>

            <PatternLayout>
                <pattern>${PATTERN_FORMAT}</pattern>
            </PatternLayout>

            <Policies>
                <!--在系統啟動時, 觸發拆分規則,生產一個新的日誌檔案-->
                <OnStartupTriggeringPolicy/>
                <!--按照檔案大小拆分, 30 MB -->
                <SizeBasedTriggeringPolicy size="30 MB"/>
                <!--按照時間節點拆分, 規則根據filePattern定義的-->
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <!--在同一個目錄下,檔案的個數限定為 30 個, 超過進行覆蓋-->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>
    </Appenders>


    <!--定義logger,日誌記錄器配置-->
    <Loggers>
        <!--過濾掉spring和mybatis的一些無用的DEBUG資訊-->
        <Logger name="org.springframework" level="INFO"/>
        <Logger name="org.mybatis" level="INFO"/>

        <!-- LOG "com.luis*" at TRACE level -->
        <Logger name="com.luis" level="INFO"/>
        <!--使用 rootLogger 配置 日誌級別 level="trace"-->
        <Root level="INFO">
            <!--指定日誌使用的處理器-->
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingInfoFile"/>
            <AppenderRef ref="RollingErrorFile"/>
            <AppenderRef ref="Async"/>
            <AppenderRef ref="Socket"/>
        </Root>
    </Loggers>
</Configuration>

主要是Socket 那部分配置,筆者的mdc裡面的欄位有自定義,在專案日誌切面部分做了MDC輸入值的處理,非原始配置

img

日誌能夠上傳到es中,kibana裡面可以檢視到

2.4. logstash檔案資訊切割

對應logstash,預設是格式是使用的logback的預設格式,一旦使用log4j2或其他日誌框架來指定日誌的輸出格式時,那麼logstash便無法解析,需要進行自定義過濾。

2.4.1. 自定義過濾

筆者使用的是

<Property name="PATTERN_FORMAT">%date{yyyy-MM-dd HH:mm:ss.SSS}$$%mdc{logId}$$%mdc{hostName}$$%mdc{ip}$$%level$$%mdc{module}$$%class$$%method$$%msg%n</Property>

在logstash.conf中新增的filter過濾規則如下

filter {
  grok {
    match => {
    "message" => "^%{TIMESTAMP_ISO8601:timestamp}\$\$(?<logId>[a-fA-F0-9]{32})?\$\$(?<hostName>[^\$]+)\$\$(?<ip>%{IP})\$\$%{WORD:level}\$\$(?<module>[^\$]*)?\$\$(?<class>.*?)\$\$(?<method>[^\\$]+)\$\$(?<msg>.*)"
    } 
  }
  date {
        match => ["timestamp", "yyyy-MM-dd HH:mm:ss.SSS"]
        target => "@timestamp"
  }
  mutate {
    remove_field => ["message","port"]
  }
}

顯示結果如下:

img

2.4.2. 多行問題

有時輸出的是異常日誌,存在多行問題,並不是按照這個格式列印,需要修改input配置,支援多行的日誌

input {
  tcp {
    mode => "server"
    host => "0.0.0.0"
    port => 4560
    codec => multiline {
      pattern => "^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{3}" # 確保這與您的日誌格式匹配
      negate => true
      what => "previous"
      auto_flush_interval => 1
    }
  }
}

這樣列印出來的支援多行合併

img

2.4.3. 遺留問題

目前只是部署了ELK,而且還是單機模式,當前的日誌蒐集使用的是tcp,由於多行的日誌,蒐集不知道下一次什麼時候結束,所以當前的部署方式存在當前請求的介面日誌只列印了部分,下一次請求來了時,上一次的日誌才會完全列印出

解決這個問題,一個是自己部署虛擬機器的配置儘量高一點

再一個可以部署filebeat,來進行最佳化日誌收集過濾

相關文章