应用日志的收集、分析和监控是日常运维工作重要的部分,妥善地处理应用日志收集往往是应用容器化重要的一个课题。
Docker处理日志的方法是通过docker engine捕捉每一个容器进程的STDOUT和STDERR,通过为contrainer制定不同log driver 来实现容器日志的收集,缺省json-file log driver是将容器的STDOUT/STDERR 输出保存在磁盘上,然后用户就能使用docker logs <container>来进行查询。
在部署一个传统的应用的时候,应用程序记录日志的方式通常记录到文件里, 一般(但不一定)会记录到/var/log目录下。应用容器化后,不同于以往将所有日志放在主机系统的统一位置,日志分散在很多不同容器的相互隔离的环境中。
如何收集应用写在容器内日志记录,有以下挑战:
1) 资源消耗
如果在每个容器运行一个日志收集进程, 比如logstatsh/fluentd 这类的日志工具,在主机容器密度高的时候,logstatsh/fluentd这类日志采集工具会消耗大量的系统资源。上面这种方法是最简单直观的,也是最消耗资源的。
2) 应用侵入
一些传统应用,特别是legacy 系统,写日志机制往往是没法配置和更改的,包括应用日志的格式,存放地址等等。日志采集机制,要尽量避免要求修改应用。
3) 日志来源识别
采用统一应用日志收集方案,日志分散在很多不同容器的相互隔离的环境中,需要解决日志的来源识别问题。
日志来源识别的功能借助了rancher平台为container_name的命名的规则特性,可以做到即使一个容器在运行过程中被调度到另外一台主机,也可以识别日志来源。
容器化应用日志收集方案
下面是我们设计的一个低资源资源消耗、无应用侵入、可以清楚识别日志来源的统一日志收集方案,该方案已经在睿云智合的客户有成功实施案例。
在该方案中,会在每个host 部署一个wise2c-logger,wise2C会listen docker engine的event,当有新容器创建和销毁时,会去判断是否有和日志相关的local volume 被创建或者销毁了,根据lables,wise2c-logger 会动态配置logstatsh的input、filter 和output,实现应用日志的收集和分发。
1) 应用如何配置
应用容器化时候,需要在为应用容器挂载一个专门写有日志的volume,为了区别该volume 和容器其它数据volume,我们把该volume 定义在容器中,通过volume_from 指令share 给应用容器,下面是一个例子:demo应用的docker-compose file
web-data 容器使用一个local volume,mount到/var/log目录(也可以是其它目录),在web-data中定义了几个标签, io.wise2c.logtype说明这个容器中包含了日志目录,标签里面的值elasticsearch、kafka可以用于指明log的output或者过滤条件等。
那么我们现在来看下wiselogger大致的工作流程:
监听新的日志容器->获取日志容器的type和本地目录->生成新的logstash配置:
1)wise2c-looger 侦听docker events 事件, 检查是否有一个日志容器创建或者被销毁;
2)当日志容器被创建后(通过container label 判断), inspect 容器的volume 在主机的path;
3)重新配置wise2c-logger 内置的logstatsh 的配置文件,设置新的input, filter 和output 规则。
这里是把wise2c-logger在rancher平台上做成catalog需要的docker-compose.yml的截图,大家可以配合上面的流程描述一起看一下。
优化
目前我们还在对Wise2C-logger 作进一步的优化:
1)收集容器的STDOUT/STDERR日志
特别是对default 使用json-file driver的容器,通过扫描容器主机的json-file 目录,实现容器STDIN/STDERR日志的收集。
2)更多的内置日志收集方案
目前内置缺省使用logstatsh 作日志的收集,和过滤和一些简单的转码逻辑。未来wise2C-logger 可以支持一些更轻量级的日志收集方案,比如fluentd、filebeat等。
Q & A
Q:有没有做过性能测试?我这边模块的日志吞吐量比较大。比如在多少量级的日志输出量基础上,主要为logger模块预留多少系统资源,保证其正常稳定工作?