网上关于这一块的介绍已经有不少了,但发现基本介绍的都是在一台机器上的demo,实用性不强。事实上如果应用很简单,根本没必要搭建专门的日志系统来收集日志,直接看日志文件就好了。出现这种需求反而是大型系统或者微服务架构,有几十上百甚至上千台服务的时候,如果还是传统的到服务器上看日志,那就看不过来了。特别是集群环境,同一种类型的服务部署在多台机器上,要找某个机器上某个日志中的内容,特别不方便,所以才需要通过日志系统直接定位问题。
因为我们目前采用的微服务架构,大概部署了有十几台机器,虽然通过传统的方式还能应付,但为了应对将来越来越多的机器,我还是搭建了一套EFK环境。
开始也是跟着网上的教程进行部署,我的架构类似下面这样。
即每个服务器上部署两个docker容器,一个跑应用,一个跑fluentd,跑应用的那个docker容器的日志以fluentd形式输出,跑fluentd的容器用来收集日志并上传到elasticsearch(后面简称es)。本身这样没毛病,跑得也好好的,但后面随着服务越来越多,es竟然报java内存溢出,开始以为是内存小的原因(4G),就把内存升级到8G,结果一样报内存溢出,而真正使用的内存都没有到8G。再仔细查看es的日志,发现有大量的GC,后面猜测是GC不过来,内存报了。一直GC的原因猜测是因为有好多fluentd在上送日志,一直不停请求(es接收数据那块具体怎么实现不太清楚),es不停的存数据,释放对象。后面把服务器上的fluentd全部停止了,只开启少数几个,es就好的。没有停fluentd前,es每次重启之后,过不了几分钟就挂了。
于是发现上面这种架构不行,查看fluentd文档,又想到另一个方案。既然是es来不及接收日志,那就少用几个fluentd连接es,可以部署几个fluentd作为server来接收fluentd的client端发来的日志。
改为上面这种架构之后,运行就都正常了,不得不说fluentd确实很强大,能接收,能转发,支持各种插件。
下面是部署过程,因为都是基于docker部署,所以特别简单。
我把es和kibana装在一台服务器上,es也没有做集群,因为是开发环境,没搞这么复杂。
docker-compose.yml
version: '2'
services:
elasticsearch:
image: elasticsearch
expose:
- 9200
- 9300
ports:
- "9200:9200"
- "9300:9300"
volumes:
- /data/jvm.options:/etc/elasticsearch/jvm.options
restart: always
kibana:
image: kibana
links:
- "elasticsearch"
ports:
- "5601:5601"
restart: always
docker-compose up -d
查看启动情况
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95e7f5808aef kibana "/docker-entrypoint.…" 6 days ago Up 6 days 0.0.0.0:5601->5601/tcp data_kibana_1
d72ec5d2e09b elasticsearch "/docker-entrypoint.…" 6 days ago Up 6 days 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp data_elasticsearch_1
访问:http://xxx:5601/
没问题的话会弹出下面的页面,让你建匹配索引的表达式。我的是按照日期存储的,格式类似fluentd-20191230,fluentd-20191229,…
所以填fluentd-*就可以了
fluentd-server目前装了3台机器,docker镜像是自己制作的,特别简单,就是暴露24225端口用于接收日志,然后转发给es,具体参数看fluentd官网文档。
Dockerfile
# fluentd/etc/fluent.conf
>
>
@type parser
format json
reserve_data true
key_name log
>
>
@type forest
subtype copy
remove_prefix service
>
>
@type elasticsearch
host 172.19.115.18
port 9200
logstash_format true
logstash_prefix fluentd
logstash_dateformat %Y%m%d
include_tag_key true
type_name java_log
tag_key @log_name
buffer_type memory
flush_interval 5s
max_retry_wait 30
disable_retry_limit
buffer_chunk_limit 256M
buffer_queue_limit 128
num_threads 8
reconnect_on_error true
resurrect_after 5s
>
>
>
docker build -t registry.uecent.com:5000/fluentd-server:1.0.0 .
docker push registry.uecent.com:5000/fluentd-server:1.0.0
docker run -d --name=fluentd-server --restart=always -p 24225:24225 -p 24225:24225/udp registry.uecent.com:5000/fluentd-server:1.0.0
fluentd-client在每个应用服务器上都装了一个,通过24224端口接收日志。
Dockerfile
# fluentd/etc/fluent.conf
>
>
@type parser
format json
reserve_data true
key_name log
>
>
@type forward
send_timeout 60s
recover_wait 10s
hard_timeout 60s
buffer_type memory
flush_interval 1s
buffer_chunk_limit 256M
buffer_queue_limit 128
num_threads 8
>
name server-1
host 172.19.115.18
port 24225
weight 60
>
>
name server-2
host 172.19.115.29
port 24225
weight 60
>
>
name server-3
host 172.19.115.20
port 24225
weight 60
>
>
@type file
path /var/log/fluent/forward-failed
>
>
docker build -t registry.uecent.com:5000/fluentd-client:1.0.0 .
docker push registry.uecent.com:5000/fluentd-client:1.0.0
docker run -d --name=fluentd-client --restart=always -p 24224:24224 -p 24224:24224/udp registry.uecent.com:5000/fluentd-client:1.0.0
注意:
1)fluentd本身没有客户端和服务端之分,是因为我这边的用途,做了人为的分配。
2)Docker私服是为了方便装了一个,没有私服,就把Dockerfile拷贝到每台服务器上制作镜像再运行也可以。
以Java服务为例,将含有java服务的docker容器日志输出到fluentd-client(注意这两个docker容器必须在一台机器上)
sudo docker run -d --name provider-auth --net=host -p 80:80 -v /data/provider-auth:/tmp -e APP_OPTS="-Dspring.profiles.active=dev" --restart=always --log-driver=fluentd --log-opt fluentd-address=localhost:24224 --log-opt fluentd-async-connect=true --log-opt fluentd-retry-wait=5s --log-opt fluentd-max-retries=3000 --log-opt tag=“service.provider-auth” --log-opt env=“fluentd-folder,fluentd-project,fluentd-ip” --env fluentd-folder=“dev-live” --env fluentd-project=“provider-auth” --env fluentd-ip=“172.19.115.14” registry.uecent.com:5000/provider-auth:1.0.0
可以看到有fluentd-project下面有不同的项目,fluentd-ip有不同的地址,可以点击筛选以下。比如选了fluentd-project其中一个项目provider-climb,则fluentd-ip只剩下两个,说明provider-climb部署了两台机器。
右侧可以看到不同机器上,不同的日志内容。也可以筛选只看其中一台,剩下的都是kibana的使用了,操作比较简单,不介绍了。
后面实测发现单台ES还是有些看不住,还是把ES做了集群,目前ES上了4个节点。
现在每天大概会产生40多个G的日志,每个服务的日志会保存7天,一共存了307G的日志。
新版kibana页面