近日在迁移应用到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安装应用(CentOS 6.5_x64)
Ubuntu 14.04安装Docker