网上关于这一块的介绍已经有不少了,但发现基本介绍的都是在一台机器上的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
docker-compose up -d
查看启动情况
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES95e7f5808aef kibana "/docker-entrypoint.…" 6 days ago Up 6 days 0.0.0.0:5601->5601/tcp data_kibana_1d72ec5d2e09b 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 配置kibana访问:http://xxx:5601/
没问题的话会弹出下面的页面,让你建匹配索引的表达式。我的是按照日期存储的,格式类似fluentd-20191230,fluentd-20191229,…
所以填fluentd-*就可以了
fluentd-server目前装了3台机器,docker镜像是自己制作的,特别简单,就是暴露24225端口用于接收日志,然后转发给es,具体参数看fluentd官网文档。
Dockerfile
docker build -t registry.uecent.com:5000/fluentd-server:1.0.0 .
上传私服docker push registry.uecent.com:5000/fluentd-server:1.0.0
启动镜像fluentd-server(这三台机器172.19.115.18、172.19.115.29、172.19.115.20)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-clientfluentd-client在每个应用服务器上都装了一个,通过24224端口接收日志。
Dockerfile
docker build -t registry.uecent.com:5000/fluentd-client:1.0.0 .
上传私服docker push registry.uecent.com:5000/fluentd-client:1.0.0
启动fluentd-client(需要的服务器上启动,比如运行java服务的服务器)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
–log-driver=fluentd #日志驱动为fluentd–log-opt fluentd-address=localhost:24224 #fluentd的地址,为本地地址,也可以写远程地址–log-opt tag=“service.${PROJECT}” #这个很重要,跟我前面的配置有关,我这边统一是service作为前缀,后面跟服务的名称。–log-opt env=“fluentd-folder,fluentd-project,fluentd-ip” # 自定义三个环境变量,后面再讲–env fluentd-folder=“dev-live” # 第一个自定义环境变量,表示哪个环境–env fluentd-project="${PROJECT}" # 第二个自定义环境变量,表示哪个项目–env fluentd-ip="${IP}" #第三个环境变量,表示当前机器IP这样全部配置就完成了,现在看下kibana效果。
可以看到有fluentd-project下面有不同的项目,fluentd-ip有不同的地址,可以点击筛选以下。比如选了fluentd-project其中一个项目provider-climb,则fluentd-ip只剩下两个,说明provider-climb部署了两台机器。
右侧可以看到不同机器上,不同的日志内容。也可以筛选只看其中一台,剩下的都是kibana的使用了,操作比较简单,不介绍了。
2021年2月后面实测发现单台ES还是有些看不住,还是把ES做了集群,目前ES上了4个节点。
现在每天大概会产生40多个G的日志,每个服务的日志会保存7天,一共存了307G的日志。
新版kibana页面