Docker容器化已是一个相对成熟的理念,但是在实际使用中还是有很多挑战,目前我们遇到的一个问题是Docker中的log如何采集
这些log包括Docker容器进程本身的log和容器内运行应用的业务log,两份log都比较重要,尤其业务log,因为一些埋点数据和统计指标都在业务log中也包括一些程序异常log。

针对这些log采集,我们面对的一些问题有:

  1. 容器标准输出日志采集
  2. 容器内业务log采集 (是否要支持同时采集多个文件或多个业务log)
  3. 断点续传
  4. 异常日志合并与拼接 (要想合并异常日志,则日志必须标准化)
  5. 日志采集的完整性
  6. 日志乱序
  7. 从日志中区分来源
  8. 支持热插拔
  9. 对业务的侵入性
  10. 故障重传

目前主流两种方案,一种是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端进行处理。

存在的隐患

  1. flume对配置文件的更新在大数据量的情况下会更新异常,要对其进行调优
  2. log-pilot断点续传与迟延
  3. log-pilot部署方式,docker容器内还是宿主机