Docker进程log和应用log采集调研
Docker容器化已是一个相对成熟的理念,但是在实际使用中还是有很多挑战,目前我们遇到的一个问题是Docker中的log如何采集。
这些log包括Docker容器进程本身的log和容器内运行应用的业务log,两份log都比较重要,尤其业务log,因为一些埋点数据和统计指标都在业务log中也包括一些程序异常log。
针对这些log采集,我们面对的一些问题有:
- 容器标准输出日志采集
- 容器内业务log采集 (是否要支持同时采集多个文件或多个业务log)
- 断点续传
- 异常日志合并与拼接 (要想合并异常日志,则日志必须标准化)
- 日志采集的完整性
- 日志乱序
- 从日志中区分来源
- 支持热插拔
- 对业务的侵入性
- 故障重传
目前主流两种方案,一种是log在容器内通过采集工具直接传输给log聚合服务,另一种是将容器内的log传输到宿主机,然后再通过日志采集工具进行采集。
方案1
在容器内直接将log传输给log聚合服务,可以通过业务方调整业务逻辑将日志直接打入kafka或者redis等缓存组件中,这种方式对业务侵入性较大,无法做到对业务无感知,也无法解决docker容器本身的log传输。
在容器内直接将log传输给log聚合服务也可以做到对业务无感知,那就是在容器中部署一个日志采集服务,如flume,通过flume将log采集到kafka,这样貌似结果了问题,对业务无感知,而且flume在日志采集领域也比较成熟。
这种方案看似合理,但是这种方案依然不符合上生产的条件。因为容器的启动和停止是一个常态,容器在停止之后,容器内的log也将随之消失,那就存在flume采集日志不完整,或者由于kafka等受网络或者其它原因导致数据没有写入成功,这就造成log丢失,而且这种丢失还是永久性的丢失,无法追回的丢失,这对一些指标的统计是不允许的。
方案2
针对方案1中的痛点采集不完整数据永久丢失和依赖kafka等服务的稳定性,提出是否可以将容器中的log落地到宿主磁盘,容器与宿主之间的网络延迟可以忽略也不会受外界网络的影响,这样后续流程就跟传统的日志采集服务一样了。
有了方向查阅资料就方便很多,阿里开源了一款日志采集工具log-pilot,此工具支持容器标准输出和业务log文件采集,还可以表识log来源,方便后续对日志进行归档。
docker容器日志输出的工具很多,而且docker本身也有一些功能可以实现,如log driver,但是这些只能将docker容器的标准输出与错误输出采集到宿主机上,而无法将业务log文件中的内容也采集到宿主机,如果非要用log driver之类的工具就得让业务方更改log的规则,这样就对业务有侵入了,所以感觉log-pilot还是比较符合预期的,虽然不是太完美,需要对其进行定制开发。
log-pilot最主要的一个定制功能就是可以支持断点续传和HA,具体的功能还需进一步的测试使用。
对于异常日志合并与拼接的功能可以通过更改flume的source代码实现,因为log-pilot是顺序的读取业务log并且顺序的写入宿主磁盘的某个文件中,不会出现乱序,所以我们把日志合并放在flume端进行处理。
存在的隐患
- flume对配置文件的更新在大数据量的情况下会更新异常,要对其进行调优
- log-pilot断点续传与迟延
- log-pilot部署方式,docker容器内还是宿主机