
介绍
想要在你的手提电脑上尝试 MongoDB 吗?执行一个命令,然后拥有一个轻量级,独立的沙箱;再执行一个命令,删除你完成之后所有的痕迹。是不是需要一个在多个环境中都跟你的应用程序堆栈一样的应用程序?创建一你自己的容器镜像,然后让你的开发,测试,操作和支持团队搭建一个跟你环境完全一样的克隆版本。
容器正在彻底改革整个软件生命周期:从最早的技术实验到贯穿开发,测试,配置到版本支持的概念验证。
编排工具是管理多个容器如何被创建、如何升级、如何发挥高可用性的。编排工具也可以控制多个容器之间的连接关系来达到 用多个容器来搭建一个复杂的应用的效果。
齐全的功能,简单的工具和强大的 API 令容器和编排功能成为运维团队的最爱,运维团队将这些功能整合到持续集成(CI)和持续交付(CD)工作流程之中。
这篇帖子深入研究了当你们尝试在容器中运行和编程 MongDB 时所面临的挑战,然后阐述了这些挑战如何克服。
MongoDB 注意事项
用容器和编排工具运行 MongoDB 介绍了一些额外注意事项:
MongoDB 数据库是有状态的。在容器运行失败,并且重新调度之后,数据丢失是不合需要的(可以通过从 replica set 中的其他节点恢复数据,但是需要耗费时间)。为了解决这个问题,Kubernetes 中的数据卷这种抽象功能就可以被用来映射在容器中原本是 MongoDB 数据目录,变成了一个持久数据目录位置,在这个位置,数据的存活比容器运行失败、重新调度要长。
在副本集合中的 MongoDB 数据库节点必须要互相交流——重新调度之后也要交流。在副本集合之中的所有节点必须知道他们所有的 peers,但是当一个容器重新调度之后,它很可能会用不同 IP 地址重新启动。比如,所有在一个 Kubernentes pod 里面的容器共享一个 IP 地址,pod 一旦重新调度,这个 IP 地址也会改变。有了 Kubernetes,这个现象就可以通过将每个 MongoDB 与 Kubernetes Service 关联来解决,使用的是 Kubernetes DNS Service 来为通过重新调度保持不变的 servi ce 提供 hostname。
一旦但个 MongoDB 节点在运行(每个都在自己的容器中),副本集合必须要初始化,而且每个节点都要添加。这大概就需要一些额外的逻辑性来提供现成的编制工具。尤其,在 intended 副本集合中,一个 MongoDB 节点必须被用来执行 rs.initiate 和 rs.add 命令。
如果编制框架提供自动的容器重调度(如同 Kubernetes 一样),那么这就能够增加 MongoDB 的弹性,因为运行失败的副本集合构建可以自动重新创建,因此可以实现恢复完整的冗余控制水平无需任何人工干预。
值得注意的是,编制工具可能监控容器的状态的同时,也可能监控在容器内运行的应用程序,或者备份他们的数据。这就意味着使用强大的监控功能,备份像 MongoDB Cloud Manager 解决方法都是不可能的,包括使用 Mongo DB Enterprise Advanced 也是不可能的。考虑一些创建自己的镜像,镜像可以包括自己喜欢包括 MongoDB 和 MongoDB 自动化代理的版本。
使用 Docker 和 Kubernetes 实现 MongoDB 副本集合
在之前的小节也讲过,像 MongoDB 这样的分布式数据库,在使用像 Kubernetes 这样的编制框架时,需要一些额外的警示。这个小节会讲到下个层次的细节,展示如何实施。
我们从在单个 Kubernetes 集群中创建整个 MongoDB 副本集合开始(这个正常的话,会在单个的数据中心——不会提供地理性备援)事实上,基本上不会有被改变到在多个集群上面运行的,这些步骤之后会讲到。
每个副本集合的构件都将作为自己的 pod 被运行,伴随着暴露外部 IP 地址和端口的服务。这个“固定的”(fixed)IP 地址十分重要,因为外部应用程序和其他副本集成构件可以在 pod 重新调度的时候保持不变,继续依赖它。
下图阐述了这些 pods 之中的一个,以及相关的 Replication Controller 和 service。

图 1:MongoDB 副本集合构建配置成为 Kubernetes Pod,作为 service 公开。
逐步通过描述的资源配置,我们有:
从核心开始,这里有叫做 mongo-node1 的单个容器,mongo-node1 包含了一个叫做 mongo 的镜像,它就是在 Docker Hub 上面集群的公开的 MongoD B 容器镜像。容器在集群里面暴露端口 27107。
Kubernetes 数据卷功能被用来在映射 /data/db 目录,在连接到叫做 mongo-persistent-storage1 持久性数据元素;这些依次都是映射到一个创建在 Google Cloud 的叫做 mongodb-disk1 的磁盘里的。这就是 MongoDB 存储数据的地方,这样,它就会被保存到容器中重新调度。
容器被保存在一个 pod 中,这个 pod 上有个标签标着它自己的名字 mongo-node,而且它还提供名字叫做 rod 的实例。
名字叫做 mongo-rc1 的 Replication Controller 被配置用来确保 mongo-node1pod 的单个实例是一直在运行的。
名字叫 mongo-svc-a 的 LoadBalancerservice 暴露了一个 IP 地址到外界,还暴露了 27017 借口,这个接口可以在容器中被 mapped 到同一个容器的接口数字。Service 使用选择器来识别正确 pod 匹配 pod 的标签。外部 IP 地址和接口会被用于应用程序,以及用于副本集成之间的交流。每个容器都有本地 IP 地址,但是这些 IP 地址会在容器被移动或者重新启动的时候改变,而使用副本集合就不会。
下一张图展示了副本集合的第二个构件。

90%的配置都是一样的,只有这些改变了:
磁盘和数据卷名字必须是唯一的,这样 mongodb-disk2 和 mongo-persistent-storage2 会被使用。
pod 被用来设置 instance: jane 和 name:mongo-node2 的标签,这样新的 service 就可以从图 1 中的 rodPod 区别它(通过选择器)。
Replication Controller 被命名为 mongo-rc2
Service 被命名为 mongo-svc-b ,并且有一个唯一的,外部 IP 地址(在这个实例中,Kubernetes 被赋值 104.1.4.5)。
第三个副本集合构件也是相同的模式,下图就展示了完整的副本集合:

注意,即使在 3 个或者更多节点的 Kubernetes 集群上运行像图 3 所示的配置,Kubernetes 可能(通常都会)会调度两个或者更多的 MongoDB 副本集合构件在同一个主机上。这是因为 Kubernetes 讲这三个节点看成三个独立的 service 了。
为了增加冗余(在 zone 里面),一个额外的 headless service 被创建。新的 service 没有提供新的性能来通知 Kubernetes 说,那三个 MongoDB pods 来自同一个 service,所以 KUbernetes 尝试在不同的节点上调度他们。

真实的需要编制和开启 MongoDB 的副本集合的配置文件和命令行可以点击这里查看。特别是,有些特殊的步骤要求将三个 Mongo DB 实例组合到一个运行的,强健的副本集合,这个的话,已经在论文中讲了。
多个可用性区域 MongoDB 副本集合
所有东西都在同一个 GCE 集群里面运行,所以副本集合创建的上述东西也还是伴随着风险的,在同一个可用区域也是一样的道理。假设有一个重大事故发生,可用区域离线了,那么 MongoDB 副本集合就不可用了。如果需要地理性备援,那么那三个 pods 就应该在三个不同的可用性地带或者区域运行。
令人吃惊的是,为了分别在三个区域内创建相似的副本集合,几乎不需要改变什么——这就要求三个集群。每个集群都需要各自的 KubernetesYAML 文件,这个文件只定义了 pod,Replication Controller 和 service 作为副本集合的一个构件。然后为每个区域都创建一个集群,持久性数据和 MongoDB。

下一步
为了了解更多关于容器和编制——两者涉及的技术,以及他们交付的业务利益——阅读这篇论文:https://www.mongodb.com/collateral/microservices-containers-and-orchestration-explained就是跟上文提到的那篇论文,在如何get到副本集合上以及在GCE上运行Docker和Kubernetes上提供指导。
加入我们的网络研讨会,一起讨论如何用 Docker,Kubernetes 和 MongoDB 来实施微服务,了解更多关于这个话题的东西。
评论