站在开发者的角度上,Docker是未来软件开发部署运维的标准方式,而Kubernetes则是事实上的下一代“操作系统”。但站在运维和DBA的立场上,将生产环境数据库放入Docker中目前还不是一个好的解决方案。一、容器技术背景
最初是针对无状态的应用而设计的,在逻辑上,容器内应用产生的临时数据也属于该容器的一部分。用容器创建起一个服务,用完之后销毁它。这些应用本身没有状态,状态通常保存在容器外部的数据库里,这是经典的架构与用法,也是容器的设计哲学。
二、无状态
对于无状态的应用服务而言,容器是一个相当完美的开发运维解决方案。然而对于带持久状态的服务---数据库来说,事情就没有那么简单了。生产环境的数据库是否应当放入容器中,仍然是一个充满争议的问题。大家都知道数据库种类众多,并不是每一种都需要进行数据的持久化,比如当做缓存使用的缓存数据库,拿redis来说,如果我们使用redis作为缓存或者用来存储用户会话这一类的数据,这种场景下这些临时数据是允许丢失的,因此数据库实例作为缓存这种场景时,数据库实例的容器化也是合适的。
三、有状态
数据需要持久化的数据库,这种场景下的数据库是有状态的,为了维持这个状态不随容器停止而销毁,数据库容器需要在容器上打一个洞,与底层操作系统上的数据卷相联通。这样的容器,不再是一个能够随意创建,销毁,搬运,转移的对象,而是与底层环境相绑定的对象。因此,传统应用使用容器的诸多优势,对于持久化的数据库容器来说都不复存在。应用跑起来和应用可靠地运行是两码事。数据库是数字化系统的核心,对于不少公司,数据是其生存之本,特别对互联网公司来说,如果数据库数据没了又没有可用备份,基本上就等于破产了。可靠性并没有一个很好的衡量方式。只有通过长时间的正确运行,我们才能对一个系统的可靠性逐渐建立信心。在裸机上部署数据库可谓自古以来的实践,通过几十年的持续工作,它很好的证明了自己的可靠性。Docker虽为DevOps带来一场革命,但仅仅五年的历史对于可靠性证明而言仍然是图样图森破。对关乎身家性命的生产数据库而言还远远不够:(1)想要提高可靠性,最重要的就是从故障中吸取经验。故障是宝贵的经验财富:它将未知问题变为已知问题,是运维知识的表现形式。A、社区的故障经验绝大多都基于裸机部署的假设,各式各样的故障在几十年里都已经被人们踩了个遍。如果你遇到一些问题,大概率是别人已经踩过的坑,可以比较方便地处理与解决。B、同样的故障如果加上一个“Docker”关键字,能找到的有用信息就要少的多。这也意味着当疑难杂症出现时,成功抢救恢复数据的概率要更低,处理紧急故障所需的时间会更长,因为还没有足够的小白鼠去趟雷😂😂😂。
C、可能出于人性的弱点,企业与个人通常并不愿意分享故障方面的经验。故障有损企业的声誉:可能暴露一些敏感信息,或者是企业与团队的垃圾程度。另一方面,故障经验几乎都是真金白银的损失与学费换来的,是运维人员的核心价值所在,因此有关故障方面的公开资料并不多。
五、总结
数据库要不要容器化这个问题并不是绝对的,需要结合具体的业务场景才能得出结论。比如,微服务的场景,如果我们的系统已经实现了微服务化,数据库实例的规模可以根据业务负载的实际情况进行动态的调整,这种场景下数据库实例的微服务化是比较有意义的,一般也是比较推荐的,且很多业务做了微服务化改造的企业确实也是这样做的。当然微服务化的过程中数据库的容器化也不是绝对的,笔者自己接触的一些业务已经微服务化落地的企业中就存在一些未对数据库做微服务化改造的情况或者使用云数据库进行微服务化。
六、个人建议
现阶段不推荐在容器中托管正式环境的数据库,目前数据库容器化还存在一些问题、不适应性以及质疑,并且还缺乏成熟的案例和方案。但是已经有很多厂商在做这块的探索了,比如:阿里、京东。数据库的容器化像应用或服务的容器化那样普及只是时间问题,随着Docker及其周边的配套技术的逐步成熟,相信在不久的将来大家会像使用Docker容器部署应用或服务一样来部署自己的各种数据库实例,会像使用kubernetes 编排应用或服务的实例一样来自由的编排自己的数据库实例。希望大家能多多留言发表自己的看法,大家一起探讨这个话题。