前言
近期团队内有同学为了搭建基于ELK的日志聚合系统而投入大量精力,个人觉得只是做了思路的建议以及验证和梳理工作,顺便水一篇博客。
ELK简介
es+logstask+kibana+filebeat。
基本架构
ELK如下图所示,相对于传统的ELK架构,这个图吧filebeat也加入进来,因为随着近年来微服务的发展和普及轻量级日志采集的需求在迅速提升,filebeat的应用也是越来越广,特别是sidecar的兴起。
整套系统搭建完成后,es,logstash都运行在后台,只有kibana可以看到,如下图所示。
这样你就可以在一个界面上查看全部服务的日志啦,可以用program来区分不同的服务,查询关键词是 program.keyword:XXXX。
获取日志
获取物理节点日志
物理机的日志比较简单,如下图所示。
为了与下面容器方式区分,这里直接以代码的方式说明集成方式
下面以常见的springboot程序为例,介绍一下接入方式。
pom.xml中增加logstash的依赖
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.3</version>
</dependency>
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<property name="log.path" value="logs/logback.log"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n
</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log.path}.%i.zip</fileNamePattern>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<!-- 为logstash输出的JSON格式的Appender -->
<appender name="LOGSTASH"
class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!--配置logStash 服务地址 -->
<destination>10.0.4.131:4565</destination>
<!-- 日志输出编码 -->
<encoder charset="UTF-8"
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"LogLevel": "%level",
"ServiceName": "${springAppName:-}",
"Pid": "${PID:-}",
"Thread": "%thread",
"Class": "%logger{40}",
"Date": "%d",
"ExceptionInfo": "%ex{full}",
"message": "%message"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>
对了别忘了往application.properties中写 logback的配置
logging.config=logback.xml
logstash的配置
tcp_logstash.conf
input {
tcp {
port => 4565
type => "jgdq_sim"
}
}
output {
if [type] == "jgdq_sim" {
elasticsearch {
hosts => ["10.0.4.131:9200"]
action=>"index"
#ES索引名称(自己定义的)
index => "jgdq_sim-%{+YYYY.MM.dd}"
}
}
stdout{
codec => rubydebug { }
}
}
input {
syslog {
port => "4560"
}
}
filter{
mutate{
remove_field => ["timestamp"]
}
}
output {
elasticsearch {
hosts => ["10.0.4.131:9200"]
action=>"index"
#ES索引名称(自己定义的)
index => "jgdq-%{+YYYY.MM.dd}"
}
stdout{
codec => rubydebug { }
}
}
获取容器中的日志
由于容器的隔离性,获取容器中的方式往往比较复杂,但本质上和物理机上一样,无外乎是文件或是网络。如下图所示:
关键的docker-compose.yml文件
version: '3.7'
services:
demo:
build: ./demo
image: demo:1.0.0
restart: always
logging:
driver: syslog
options:
syslog-address: ${SYSLOG_ADDRESS}
tag: demo
env_file:
- .env
需要提供.env文件
SYSLOG_ADDRESS=tcp://10.0.4.131:514
${SYSLOG_ADDRESS}这个是写在.env文件中的
logstash的配置
syslog_logstash.conf
input {
syslog {
port => "4560"
}
}
filter{
mutate{
remove_field => ["timestamp"]
}
}
output {
elasticsearch {
hosts => ["10.0.4.131:9200"]
action=>"index"
#ES索引名称(自己定义的)
index => "jgdq-%{+YYYY.MM.dd}"
}
stdout{
codec => rubydebug { }
}
}
filebeat的用法
filebeat直接对接es的配置
filebeat.inputs:
- type: log
# Change to true to enable this input configuration.
enabled: true
# Paths that should be crawled and fetched. Glob based paths.
paths:
- D:\Data\*.txt
#- c:\programdata\elasticsearch\logs\*
ignore_older: 1h
scan_frequency: 1s
tail_files: true
backoff: 1s
max_backoff: 2s
backoff_factor: 2
# ========================== Filebeat global options ===========================
filebeat.registry.flush: 0s
# ================================== General ===================================
queue:
mem:
events: 128
flush.min_events: 64
flush.timeout: 1s
filebeat.config.modules:
# Glob pattern for configuration loading
path: ${path.config}/modules.d/*.yml
# Set to true to enable config reloading
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
setup.kibana:
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["10.0.4.131:9200"]
indices:
- index: "TODAY-DEMO"
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~
filebeat与logstash对接
filebeat配置
# Filebeat 收集 /var/logs/ 目录下所有以 service_log. 开头的数据文件
filebeat.inputs:
- type: log
paths:
- /var/logs/service_log.*
# 将数据发送至地址为 10.42.32.70:5044 或
output.logstash:
hosts: ["10.0.4.131:5044"]
logstash配置
# 使用 beats 作为输入
input {
beats {
port => "5044"
}
}
output {
elasticsearch {
hosts => ["10.0.4.131:9200"]
action=>"index"
#ES索引名称(自己定义的)
index => "jgdq-%{+YYYY.MM.dd}"
}
stdout{
codec => rubydebug { }
}
}
结论
在实际使用中,logstash本身也是支持分布式部署的,但由于logstash基于JVM太过重型,基本每人这么干。
推荐实践方式:
- 如果要避免侵入式的可以考虑采用filebeat+文件+es的模式或是应用转syslog+logstash+es的模式
- 不介意侵入的话可以直接通过网络流推入logstash中
照看好你的微服务系统还是很困难的,希望日志聚合系统可以帮你点忙。