业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理, Docker 提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。
2013 年以来 Docker 迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控、日志、网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验。
日志收集是大数据的基础,业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行分析处理;高可用性,高可靠性以及可扩展性是日志收集系统的必备要素。
ELK 是目前较流行的日志一体化解决方案,提供日志收集、处理、存储、搜索、展示等功能。容器标准输出日志常用的查询方式是通过 Docker 命令 docker logs containerid 来查看,容器内日志受容器隔离性影响不便于收集,因此当面对大型系统,用单一命令管理日志是不可行的,需要一个对于容器日志统一检索管理的方案。基于 ELK 实践了一套容器日志管理系统,架构如下:
传统的日志采集有较成熟的解决方案,如 Flume 、 Logstash 等,但传统的采集方案不适用于容器日志。 Docker 本身提供了 LogDriver 功能,可以利用不同的 driver 把日志输出到不同地方, LogDriver 具体有以下几种:
对于这些 LogDriver 就不一一详细介绍了,大家有兴趣可以去 Docker 官网查看。可见 Docker 对日志提供了较为丰富的处理方式,供选择的还有优秀的开源项目 Logspout 等,然而这并不能满足所有的使用场景。
容器的标准输出日志可从以上驱动中选择,由于大多数用户选择标准化输出日志,故 Docker 没有提供采集功能,如果将日志内的文件挂载出来进行采集,多个实例同名日志则会无法区分,容器内文件日志处理、错误日志多行处理等问题时有发生,若想标准输出日志和容器内文件日志兼得,则需自己动手丰衣足食,以下为数人云日志采集系统实践。
针对 Marathon + Mesos 环境开发了一套日志采集工具, Docker 的标准输出日志 json-file 默认持久化在本地上, Mesos 对于标准输出日志也存了一份在 Sandbox 下:
因此标准输出日志也可以通过 Mesos 文件的方式进行采集。
平台支持的文件存储是 Overlay ,避免了许多复杂环境的处理。关于 Overlay 盗用一张图:
容器的存储驱动运用写时复制( Copy On Write ), Overlay 主要分为 lower 和 upper, 当需要修改一个文件时,使用 CoW 将文件从只读的 Lower 层复制到可写层 Upper 层进行修改,在 Docker 中,底部的只读层是 image ,可写层是 Container ,因此容器内日志在宿主机上通过 Upper 的文件系统可找到,例如在容器内的 /var/log/test.log 中写一个 test 字符,如图:
同理,无论是标注输出的日志还是容器内文件日志,都可以通过文件的方式进行处理,也可以同时把 json-file 关闭,以减轻 Docker 本身的压力。
基于上述方式开发了一款日志采集工具,对日志进行统一收集管理,日志通过 TCP 把 JSON 格式化的日志输出到 Logstash ,包括应用 ID ,容器 Name ,容器 ID , TaskID 等,当然开发的过程中也遇到许多问题,如断点续传和错误日志多行处理等功能,这其中参考了 Filebeat ( Go 语言开发)对于日志处理的方式,个人认为如果是对于传统文件日志处理, Filebeat 是不错的选择,日志采集功能第一步支持:
日志处理需要提供快速的数据处理能力,在开发过程中遇到了性能问题, CPU 占用非常高,针对该问题对程序作调优,使用 Golang 内置的包 net/http/pprof ,对 Golang 程序调优很好用,可将程序中每个函数占用 CPU 内存的比例通过生成 SVG 的方式直观的反映出来,如图:
Golang 内置包 encoding/json json 的序列化、正则、反射、字节转字符串对于资源的消耗也比较高,可针对以上几方面以及程序本身进行调整。
日志存储功能有 Logstash 、 Heka 、 Fluentd 等方案, Logstash 基于 R uby ,支持功能丰富,但性能方面诟病较多; Heka 基于 Go ,性能方面比 Logstash 好很多,不过 Heka 好像已经不维护了。综合考虑社区活跃度、迭代速度以及稳定性方面最终选择了 Logstash ,实际应用过程中比较重要的参数如下:
以上参数仅供参考,可根据实际环境进行调试。如果日志量较大,为了确保架构的稳定性,可以在中间加一层消息队列,比较常用的有 Kafka 、 Redis 等,相信大家对这方面应用比较多,不再赘述。
ES 应该是索引存储的不二选择,整个架构的缓解包括 ES 通过 Docker 的方式部署,压测时用 Marvel 对 ES 的索引方式监控等,网上有很多调优资料,可自行实验。日志的展示是通过自己定制的, Kibana 本身的功能比较强大的同时也略微有些学习成本,最终客户想要的是很简单的东西。
压测工具选择的是分布式压测工具 Tsung ,通过压测一个应用产生日志然后通过 Log-Agent 对日志进行采集,模拟真实环境日志采集。
日志处理中,关键字报警是一个重要功能,对于监控报警主要用 Prometheus + Alertmanager 实现。应用运行过程中,根据日志关键字告警部的应用场景,从 Logstash 部分对日志做分流(具体方案可以看上面图的报警部分),自研 grok_export 对日志进行过滤分析生成 Prometheus 格式的数据,然后从 Prometheus 配置报警策略通过 alertmanager 报警。 Log-Agent 本身也支持 Prometheus 数据, Prometheus 通过特定的规则查看日志的统计信息。
Prometheus : Prometheus 是开源的监控告警系统,通过 pull 的方式采集时间序列,以及用 http 传输,数据存储在本地,支持丰富的查询语法和简单的 Dashboard 展示。
Alertmanager : Alertmanager 作为 Prometheus 的组件,所有达到阀值的时间都通过 Alertmanager 报警, Alertmanager 支持非常强大的告警功能,包括 http 、 email 通知,以及静默重复报警屏蔽等功能。
以上是数人云在实践容器日志系统过程中遇到的问题,更高层次的应用包括容器日志分析等,还有待继续挖掘和填坑,欢迎大家提出建议,一起交流。
Q : Overlay 是没有实现 inotify 接口的,是咋获取文件日志增量数据的?
A :通过循环读取文件的方式,记录文件 offset 。
Q :既然主要框架是 ELK ,采集端不直接用 Filebeat 是因为 Filebeat 有局限性吗?
A : Filebeat 没有满足我们产品基于 Docker 的需求,等于上面加了 Docker 的逻辑。
Q :自研的日志系统,打出来的每条日志格式都是规定好的吗?开发中每个人都要按这个规范来做吗?不管是什么级别的日志?
A :其实并没有,但是如果是内部使用,能规约好当然更好,可以更方便的处理,而且可以做更细粒度的分析。
Q :日志收集有做分析展示处理吗?用什么处理的。
A :对于日志内容的分析还没做,例如 Nginx 请求日志还是有分析意义的。
Q :采集方面有考虑直接使用系统的 Syslog 和 Logrotate 吗?
A :用过 Syslog 后来因为容器内的文件日志需求重新开发的。