转载

对容器中应用程序的配置和日志的认知

近日在迁移应用到docker的过程中,纠结于配置和日志处理,查阅了网友关于此的讨论,有所认知,请批评指正。 以下认知,均是基于测试/生产环境,不涉及开发环境。

关于配置

通过几个开源项目(wordpress,MySQL)的官方镜像处理方式,来窥探一下关于配置参数的处理手法。

  • 通过“环境”传递配置参数到容器。
  • 容器内通过ENTRYPOINT指令配置的脚本接收环境变量,并按格式写入配置文件。
  • ENTRYPOINT脚本通过exec指令启动CMD指令。

观点

$

  • “环境”是传递数据到容器内应用程序的常规手法,但数据项太多时,会给维护造成困扰。
  • 通过“ENTRYPOINT”指令配置的脚本,完成配置的初始化是一个合理的选择。
  • 配置初始化。实践中,配置项往往规模较大,被集中管理(zookeeper/etcd),需要区分部署的环境(测试/生产)。在此场景下,将“部署环境标识”通过“环境变量”传递到容器,在容器启动时,通过entrypoint脚本根据“环境标识”和“应用程序配置项需求”(应用程序一般会有关于配置的schema文件,描述了需要哪些配置项),从配置管理设施中获取配置数据,完成配置的初始化后,启动应用程序。
  • 配置项变更。配置项的变更一般涉及两项:如何捕获这些更新(watch配置管理设施,由谁来watch?),以及如何让新配置生效(一般意味着进程轮换,如nginx;或者php项目中清理apc缓存)。 在docker场景下,应当使用能与编排工具通信的设施负责捕获变更,并将变更转换为与镜像相关,提交给编排工具,由编排工具启动新容器轮换掉老容器,完成配置生效。 那些企图在容器内部捕获配置变更,然后使配置生效的处理手法,不符合docker的设计精神,而且往往复杂度高

关于日志

《 使用 Fluentd 管理 Docker 日志 》一文对docker日志的讨论,受益匪浅。

观点:

$

  • 从当前实际来看,通过挂载volume到容器,应用程序将日志写入volume,然后通过宿主机上的agent实现收集,更具可操作性,与主机模型的日志处理几乎一致。当然,正如作者所言,这需要应用程序将日志写入volume。 如果我们将日志视作业务数据,将volume作为存储的话,那这也合乎情理

    对于web服务器来说,访问日志是其生产的内容,对于日志分析系统来说,访问日志就是业务数据。

  • docker收集容器内应用程序的stdout、stderr,并存储为日志,只是一种实现。但它并不是(至少现在不是)为大规模日志(如web服务器)而设计,如果这种机制不满足需求,我们就需要辩证的使用它。
  • 如果仍坚持使用docker的日志机制(通过stdout,stderr收集应用程序日志),在制定rotate机制时,可考虑容器的生命周期,或许以日志的轮转周期,启动新容器替换旧容器更符合docker场景。但这对于会产生大量日志的应用来说,也会带来问题:以什么样的频率轮换?
  • 如果使用docker的日志机制,在收集时可考虑动态的方案。以flume机制为例:主机上监听docker事件,以容器label区分业务类型,当监听到start事件时,动态生成配置文件,并启动agent。日志数据通过
    docker logs -f 容器ID
    获取。当监听到stop事件,在日志采集完后,清理掉agent及相关配置。这里有几个问题:由于日志采集是异步的,如何认定日志已经采集完?另外编排系统在何时删除掉被停止的容器,当容器停止被删除后,该容器的所有数据会被清理,如何协调它们?这引入了复杂度。

小结

容器的启用和销毁的成本低,在生命周期管理上,往往通过容器的轮换来处理一些原来需要精细化控制的细节,如果照搬主机的处理模式,会很难受,且格格不入。

参阅

- 一种Docker化应用程序的简单方法

- 使用 Fluentd 管理 Docker 日志

- 容器里Nginx、MySQL的配置文件、日志是否应该挂载到宿主机上

- 请教下代码放在Docker里面还是外面呢

正文到此结束
Loading...