ELK日志收集系统

ELK组成

参考链接:https://zhuanlan.zhihu.com/p/26399963

ELK架构

  1. Shipper:负责收集各种来源的日志数据,可以是系统日志、文件、redis、mq等等;
  2. Broker:作为Shipper与中心Indexer之间的缓冲区(redis,kafka,RabbitMQ),主要是为了可以提高系统的性能和可靠性,当Indexer提取数据失败时,数据保存在redis中,而不至于丢失;
  3. Indexer:负责从Broker中取出数据,对数据进行格式化和相关处理后,输出到Elasticsearch中存储;
  4. Elasticsearch:一个分布式搜索引擎和分析引擎,用于数据存储,可提供实时的数据查询。
  5. Kibana:一个数据可视化服务,根据用户的操作从Elasticsearch中查询数据,形成相应的分析结果,以图表的形式展现给用户。

部署ELK方案

  1. 在每台生成日志文件的机器上,部署Logstash,作为Shipper的角色,负责从日志文件中提取数据,但是不做任何处理,直接将数据输出到Redis队列(list)中;
  2. 需要一台机器部署Logstash,作为Indexer的角色,负责从Redis中取出数据,对数据进行格式化和相关处理后,输出到Elasticsearch中存储;
  3. 部署Elasticsearch集群,当然取决于你的数据量了,数据量小的话可以使用单台服务,如果做集群的话,最好是有3个以上节点,同时还需要部署相关的监控插件;
  4. 部署Kibana服务,提供Web服务。

在上面的部署方案中,我们将Logstash分为Shipper和Indexer两种角色来完成不同的工作,中间通过Redis做数据管道。

为什么要这样做?为什么不是直接在每台机器上使用Logstash提取数据、处理、存入Elasticsearch?采用这样的架构部署,有三点优势:

  1. 降低对日志所在机器的影响,这些机器上一般都部署着反向代理或应用服务,本身负载就很重了,所以尽可能的在这些机器上少做事;
  2. 如果有很多台机器需要做日志收集,那么让每台机器都向Elasticsearch持续写入数据,必然会对Elasticsearch造成压力,因此需要对数据进行缓冲,同时这样的缓冲也可以一定程度的保护数据不丢失;
  3. 将日志数据的格式化与处理放到Indexer中统一做,可以在一处修改代码、部署,避免需要到多台机器上去修改配置。

docker部署ELK

参考链接:https://logz.io/blog/docker-logging/

推荐docker:https://github.com/deviantony/docker-elk

端口占用情况:

  • 5000: Logstash TCP input.
  • 9200: Elasticsearch HTTP
  • 9300: Elasticsearch TCP transport
  • 5601: Kibana

Logspout

Logspout是Docker流行和轻量级的(15.2MB)日志路由器,它将附加到主机中的所有容器,并将Docker日志流输出到syslog服务器(除非定义了不同的输出目标)。

Filebeat

Filebeat属于Elastic的Beats系列日志收集组件, Filebeat是用Go语言开发的,支持追踪特定文件和日志加密的中间组件,它可以配置将日志导出到Logstash或者直接导出到Elasticsearch。

如果没有额外指定,容器的stdout和stderr输出(也称为“docker logs”)输出到JSON文件。所以,如果是一个小型Docker环境,使用Filebeat来收集日志将是不错的选择。但如果使用其他日志记录驱动程序,则可能需要考虑其他方法。

Logging Driver

Docker从1.12开始支持Logging Driver,允许将Docker日志路由到指定的第三方日志转发层,可将日志转发到AWS CloudWatch,Fluentd,GELF或NAT服务器。


docker应用服务器配置

Nginx

日志格式化,日志输出重定向

http {} 节点添加如下配置信息:

1
2
3
4
5
6
log_format main '[$remote_addr, $request, $status, $body_bytes_sent, ' 
'$http_user_agent, $http_referer, $http_x_forwarded_for, $request_time, '
'$upstream_response_time, $http_cookie, $http_Authorization, $http_token]';

access_log /dev/stdout main;
error_log /dev/stdout;

注意,在Docker中
/var/log/nginx/access.log -> /dev/stdout
/var/log/nginx/error.log -> /dev/stderr

为了方便logstash进行分割,建议使用如下格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
log_format main '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"url":"$uri",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"agent":"$http_user_agent",'
'"status":"$status"}';

Logstash 配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
input {
udp {
port => 5000
type => "nginx"
}
}

## Add your filters / logstash plugins configuration here
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "logstash-%{type}-%{+YYYY.MM.dd}"
document_type => "%{type}"
flush_size => 20000
idle_flush_time => 10
sniffing => true
template_overwrite => true
}
}

注意:这里input默认是使用TCP,现在修改为UDP,则docker-compse.yml需要修改ports为 “port:5000/udp”

input参数说明

type

  • 对应_type

output参数说明

flush_size idle_flush_time

  • Logstash 会努力攒到 20000 条数据一次性发送出去,但是如果 10 秒钟内也没攒够 20000 条,Logstash 还是会以当前攒到的数据量发一次。

index

  • 写入的 ES 索引的名称,这里可以使用变量。为了更贴合日志场景,Logstash 提供了 %{+YYYY.MM.dd} 这种写法。在语法解析的时候,看到以 + 号开头的,就会自动认为后面是时间格式,尝试用时间格式来解析后续字符串。此外,注意索引名中不能有大写字母,否则 ES 在日志中会报 InvalidIndexNameException,但是 Logstash 不会报错,这个错误比较隐晦,也容易掉进这个坑中。

hosts

  • host 可以设置数组,它会从节点列表中选取不同的节点发送数据,达到 Round-Robin 负载均衡的效果。

Logstas 过滤日志

Logspout

查看收集Logspout收集nginx日志

1
curl http://ip:port/logs


docker日志处理

在部署一个传统的Linux时,应用程序或者架构记录日志的方式通常记录到文件里,一般会记录到/var/log目录下。

Docker有什么不同呢?不同于以往将所有日志放在主机系统的统一位置,如今日志分散在很多不同容器的相互隔离的环境中。

典型ELK日志收集流程如下所示:

Logstash负责从各种Docker容器和主机中提取日志,这个流程的主要优点是可以更好地用过滤器来解析日志,Logstash将日志转发到Elasticsearch进行索引,Kibana分析和可视化数据。

这个流程可以有多种不同的实现方式, 例如可以使用不同的日志收集和转发组件, 如Fluentd或Filebeat 将日志发送到Elasticsearch。或者添加一个由Kafka或Redis容器组成的中间层,作为Logstash和Elasticsearch之间的缓冲区。


docker-compose

1
2
git clone https://github.com/deviantony/docker-elk.git
docker-compose up

正常情况下, ELK套件的三个服务(Elasticsearch, Logstash, Kibana)会启动成功,默认持久化数据目录 /var/lib/elasticsearch (Elasticsearch 的数据存储目录)

测试Elasticsearch

1
curl localhost:9200

返回结果

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name" : "6cU6dcx",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "PGZdqdKdQiKwh67to_2H7g",
"version" : {
"number" : "5.6.3",
"build_hash" : "1a2f265",
"build_date" : "2017-10-06T20:33:39.012Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}

打开Kibaba web页面 localhost:5601

Logspout 收集日志

如果docker服务使用docker-compose管理,则添加如下配置信息

1
2
3
4
5
6
7
8
logspout:
image: gliderlabs/logspout:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "10000:80"
command:
syslog://Logstash_IP:Logstash_port

查看logsout收集的日志

1
curl http://localhost:10000/logs