V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dataman
V2EX  ›  Docker

数人云工程师手记 | 容器日志管理实践

  •  
  •   dataman · 2017-01-12 10:55:20 +08:00 · 3838 次点击
    这是一个创建于 2864 天前的主题,其中的信息可能已经有所发展或是发生改变。

    业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理, Docker 提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集、存储以及告警等方面的实践经验。

    2013 年以来 Docker 迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控、日志、网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验。

    基于 ELK 的日志管理系统架构

    日志收集是大数据的基础,业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行分析处理;高可用性,高可靠性以及可扩展性是日志收集系统的必备要素。

    ELK 是目前较流行的日志一体化解决方案,提供日志收集、处理、存储、搜索、展示等功能。容器标准输出日志常用的查询方式是通过 Docker 命令 docker logs containerid 来查看,容器内日志受容器隔离性影响不便于收集,因此当面对大型系统,用单一命令管理日志是不可行的,需要一个对于容器日志统一检索管理的方案。基于 ELK 实践了一套容器日志管理系统,架构如下:

    日志采集

    传统的日志采集有较成熟的解决方案,如 Flume 、 Logstash 等,但传统的采集方案不适用于容器日志。 Docker 本身提供了 LogDriver 功能,可以利用不同的 driver 把日志输出到不同地方, LogDriver 具体有以下几种:

    • None (将日志设置成不再输出)
    • json-file ( Docker 默认的 LogDriver ,将日志以 JSON 文件的方式存储在本地)
    • Syslog (标准输出日志可通过该方式传输)
    • Journal
    • SELF
    • Fluent
    • awslogs
    • Splunk
    • etwLogs
    • gcplogs

    对于这些 LogDriver 就不一一详细介绍了,大家有兴趣可以去 Docker 官网查看。可见 Docker 对日志提供了较为丰富的处理方式,供选择的还有优秀的开源项目 Logspout 等,然而这并不能满足所有的使用场景。

    容器的标准输出日志可从以上驱动中选择,由于大多数用户选择标准化输出日志,故 Docker 没有提供采集功能,如果将日志内的文件挂载出来进行采集,多个实例同名日志则会无法区分,容器内文件日志处理、错误日志多行处理等问题时有发生,若想标准输出日志和容器内文件日志兼得,则需自己动手丰衣足食,以下为数人云日志采集系统实践。

    1. 标准输出日志

    针对 Marathon + Mesos 环境开发了一套日志采集工具, Docker 的标准输出日志 json-file 默认持久化在本地上, Mesos 对于标准输出日志也存了一份在 Sandbox 下:

    因此标准输出日志也可以通过 Mesos 文件的方式进行采集。

    2. 容器内文件日志

    平台支持的文件存储是 Overlay ,避免了许多复杂环境的处理。关于 Overlay 盗用一张图:

    容器的存储驱动运用写时复制( Copy On Write ), Overlay 主要分为 lower 和 upper, 当需要修改一个文件时,使用 CoW 将文件从只读的 Lower 层复制到可写层 Upper 层进行修改,在 Docker 中,底部的只读层是 image ,可写层是 Container ,因此容器内日志在宿主机上通过 Upper 的文件系统可找到,例如在容器内的 /var/log/test.log 中写一个 test 字符,如图:

    同理,无论是标注输出的日志还是容器内文件日志,都可以通过文件的方式进行处理,也可以同时把 json-file 关闭,以减轻 Docker 本身的压力。

    3. 自研日志采集工具

    基于上述方式开发了一款日志采集工具,对日志进行统一收集管理,日志通过 TCP 把 JSON 格式化的日志输出到 Logstash ,包括应用 ID ,容器 Name ,容器 ID , TaskID 等,当然开发的过程中也遇到许多问题,如断点续传和错误日志多行处理等功能,这其中参考了 Filebeat ( Go 语言开发)对于日志处理的方式,个人认为如果是对于传统文件日志处理, Filebeat 是不错的选择,日志采集功能第一步支持:

    • 容器标准输出日志采集
    • 容器内文件日志采集,支持同时采集多个文件
    • 断点续传 (如果 Agent 崩溃,从上次 offset 采集)
    • 多行日志合并 (如:多行错误日志合并)
    • 日志文件异常处理 (如:日志被 rotate 可以重新采集)
    • TCP 传输
    • --add-env --add-label 标签,可以通过指定命令把 container 的 env 或者 label 加到日志数据里,如(--add-env hostname=HOST --add-env test=ENV_NAME1 --add-label tlabel=label_name)
    • Prometheus 指标数据

    日志处理需要提供快速的数据处理能力,在开发过程中遇到了性能问题, CPU 占用非常高,针对该问题对程序作调优,使用 Golang 内置的包 net/http/pprof ,对 Golang 程序调优很好用,可将程序中每个函数占用 CPU 内存的比例通过生成 SVG 的方式直观的反映出来,如图:

    Golang 内置包 encoding/json json 的序列化、正则、反射、字节转字符串对于资源的消耗也比较高,可针对以上几方面以及程序本身进行调整。

    日志存储后端架构

    日志存储功能有 Logstash 、 Heka 、 Fluentd 等方案, Logstash 基于 R uby ,支持功能丰富,但性能方面诟病较多; Heka 基于 Go ,性能方面比 Logstash 好很多,不过 Heka 好像已经不维护了。综合考虑社区活跃度、迭代速度以及稳定性方面最终选择了 Logstash ,实际应用过程中比较重要的参数如下:

    • --pipeline-workers (命令行参数)
    • --pipeline-batch-size (命令行参数)
    • LS_HEAP_SIZE=${LS_HEAP_SIZE} (根据自己的实际情况填写,可以写到环境变量活着命令行参数里面)
    • workers => 8 (根据自己实际情况,一般等于 CPU 数,配置文件参数)
    • flush_size => 3000 (根据自己的实际情况测试)

    以上参数仅供参考,可根据实际环境进行调试。如果日志量较大,为了确保架构的稳定性,可以在中间加一层消息队列,比较常用的有 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&A

    Q : Overlay 是没有实现 inotify 接口的,是咋获取文件日志增量数据的?

    A :通过循环读取文件的方式,记录文件 offset 。

    Q :既然主要框架是 ELK ,采集端不直接用 Filebeat 是因为 Filebeat 有局限性吗?

    A : Filebeat 没有满足我们产品基于 Docker 的需求,等于上面加了 Docker 的逻辑。

    Q :自研的日志系统,打出来的每条日志格式都是规定好的吗?开发中每个人都要按这个规范来做吗?不管是什么级别的日志?

    A :其实并没有,但是如果是内部使用,能规约好当然更好,可以更方便的处理,而且可以做更细粒度的分析。

    Q :日志收集有做分析展示处理吗?用什么处理的。

    A :对于日志内容的分析还没做,例如 Nginx 请求日志还是有分析意义的。

    Q :采集方面有考虑直接使用系统的 Syslog 和 Logrotate 吗?

    A :用过 Syslog 后来因为容器内的文件日志需求重新开发的。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5365 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 07:43 · PVG 15:43 · LAX 23:43 · JFK 02:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.