所有的服务都开始了容器化升级,在一切皆容器的主流思想下,无状态的服务采用容器化已经是大势所趋,常常困扰架构师的一个问题是,数据库是否需要容器化?
数据库不适合容器化的七大原因
1. 数据不安全
即使你要把 Docker 数据放在主机来存储 ,它依然不能保证不丢数据。 Docker volumes 的设计围绕 Union FS 镜像层提供持久存储,但它仍然缺乏保证。
使用当前的存储驱动程序,Docker 仍然存在不可靠的风险。 如果容器崩溃并数据库未正确关闭,则可能会损坏数据。
2. 运行数据库的环境需求
常看到 DBMS 容器和其他服务运行在同一主机上。 然而这些服务对硬件要求是非常不同的
数据库(特别是关系型数据库)对 IO 的要求较高。 一般数据库引擎为了避免并发资源竞争而使用专用环境。如果将你的数据库放在容器中,那么将浪
费你的项目的资源。 因为你需要为该实例配置大量额外的资源。 在公有云,当你需要 34G 内存时,你启动的实例却必须开 64G 内存。在实践中,这些
资源并未完全使用。
怎么解决? 您可以分层设计,并使用固定资源来启动不同层次的多个实例。 水平伸缩总是比垂直伸缩更好。
3. 网络问题
要理解 Docker 网络,您必须对网络虚拟化有深入的了解。也必须准备应付好意外情况。你可能需要在没有支持或没有额外工具的情况下,进行 bug 修复。
我们知道:数据库需要专用的和持久的吞吐量,以实现更高的负载。我们还知道容器是虚拟机管理程序和主机虚拟机背后的一个隔离层。然而网络对于
数据库复制是至关重要的,其中需要主从数据库间 24/7 的稳定连接。未解决的 Docker 网络问题在1.9版本依然没有得到解决。
把这些问题放在一起,容器化使数据库容器很难管理。我知道你是一个顶级的工程师,什么问题都可以得到解决。但是,你需要花多少时间解决 Docker
网络问题?将数据库放在专用环境不会更好吗?节省时间来专注于真正重要的业务目标。
4.状态
在 Docker 中打包无状态服务是很酷的,可以实现编排容器并解决单点故障问题。 但是数据库呢? 将数据库放在同一个环境中,它将会是有状态的,并
使系统故障的范围更大。下次您的应用程序实例或应用程序崩溃,可能会影响数据库。
5.数据库不适合使用主要的docker功能
考虑容器中的数据库,我们来思考它的价值。 我们先看看 Docker 官方对其的定义:
Docker 是为开发人员和系统管理员构建,分发和运行分布式应用程序的开放平台。 Docker 包括 Docker Engine(便携式,轻量级运行时和打包工具)
以及 Docker Hub(用于共享应用程序和自动化工作流的云服务),Docker 使应用程序能够以组件快速组装,并消除开发,QA 和生产环境之间的不
同。 因此,IT 可以更快地分发程序,并在笔记本电脑,数据中心虚拟机和任何云上运行相同的应用程序。
根据该答案,我们可以很容易定义 Docke r的主要特性:
-
-
- 易于构建新环境
- 易于重新部署(持续集成)
- 容易水平伸缩(从实践得出)
- 易于维护环境一致
-
让我们开始思考这些功能如何适应数据库世界。
容易设置数据库? 让我们看看,容器化或者在本地运行数据库,在运行上是否有巨大的差异。
docker run -d mongod:3.4
对比:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list sudo apt-get update && sudo apt-get install -y mongodb-org
易于构建新环境?如果我们谈论是 MongoDB集群 - 可能容器化效率更高。但是配置管理系统呢?它们旨在通过运行一个命令来解决配置问题。使用
Ansible 你可以轻松设置几十个 Mongo 实例。正如你所看到的,没有显著的价值增长。
容易重新部署?您重新部署数据库升级到下一个版本的频率是多少呢?数据库升级不是可用性问题,而是工程问题(即在群集中的可用性)。想想你的
应用程序将如何使用新的数据库引擎版本。引擎更换时可能导致的问题。
容易水平伸缩?是否要在多个实例之间共享数据目录?你不害怕直接数据并发问题和可能的数据损坏吗?使用专用数据环境部署多个实例不会更安全
吗?最后搞一个主从复制?
易于维护环境一致?数据库实例环境的变化频率如何?每天升级操作系统吗?还是数据库版本或依赖软件变化频繁?或者是不容易与工程团队达成共
识?
最后看来,没有一个特性足以让我考虑数据库容器化。
6. 额外的隔离对数据库是不利的
其实我在第二点和第三点原因中提到了这一点。 但我把这个列为单独的原因,因为我想再次强调这一事实。 我们拥有的隔离级别越多,我们获得的资源
开销就越多。 相比专用环境而言,容易水平伸缩可以使我们得到更多的好处。 然而在 Docker 中水平伸缩只能用于无状态计算服务,而不是数据库。
我们没有看到任何针对数据库的隔离功能,那为什么我们应该把它放在容器中?
7.云平台的不适用性
大部分人通过共有云开始项目。 云简化了虚拟机操作和替换的复杂性,因此不需要在夜间或周末没有人工作时间来测试新的硬件环境。当我们可以迅速
启动一个实例的时候,为什么我们需要担心这个实例运行的环境?
这就是为什么我们向云提供商支付很多费用的原因。 当我们为实例放置数据库容器时,上面说的这些便利性就不存在了。因为数据不匹配,新实例不会
与现有的实例兼容,如果要限制实例使用单机服务,应该让 DB 使用非容器化环境,我们仅仅需要为计算服务层保留弹性扩展的能力。
这 7 点适用于所有数据库吗?
也许不是全部,但是应该是一切需要持久化数据的数据库,以及所有具有特殊硬件环境要求的数据库。
如果我们使用 Redis 作为缓存或用户会话存储- 使用容器就不应该有任何问题。因为不需要保证该数据落地,那么数据没有丢失的风险。但是如果我们
考虑使用 Redis 作为一个持久的数据存储,那么你最好把数据放在容器外面,即使您不断刷新 RDB 快照,在快速变化的计算集群中找到这个快照也会
很复杂。
我们还可以谈谈容器内的 Elasticsearch。我们可以存储在 ES 中的索引,并且可以从持久性数据源重建它们。但是看看要求!默认情况下,
Elasticsearch 需要 2 到 3GB 的内存。由于 Java 的 GC,内存使用并不一致。您确定Elasticsearch 适合用于资源限制的容器吗?让不同的
Elasticsearch 实例使用不同的硬件配置不是更好吗?
不要担心本地开发环境的数据库容器化。将数据库放在本地环境的容器中,你将节省大量的时间和精力。你将能够复制生产环境操作系统。原生
Postgres for OS X或Windows不是100%兼容Linux版本。在主机操作系统上设置容器而不是软件包,你会克服这种问题。