Docker Swarm 上的 MongoDB 副本集

Docker Swarm 上的 MongoDB 副本集

我尝试在 docker swarm 服务中创建 MongoDB 副本集。到目前为止一切顺利。我面临的问题是,当容器停止或移动到其他 docker 主机时,集群会中断,我无法连接到它,因为容器名称已更改,无法进行复制。

我根据 MongoDB 文档创建了一个简单的服务 (https://www.mongodb.com/compatibility/deploying-a-mongodb-cluster-with-docker) 如下:

docker service create --replicas=3 --network=paas --name=database mongo --replSet myReplicaSet --bind_ip 0.0.0.0

它在我的 3 个 docker 主机(配置为一个 swarm)上运行,每个主机上都有一个 docker 容器。

为了创建一个副本集,我在一个docker主机上运行:

docker exec -it database.2.9qx7fuko225k8sojd0clx2r0e mongosh --eval "rs.initiate({
 _id: \"myReplicaSet\",
 members: [
   {_id: 0, host: \"database.2.9qx7fuko225k8sojd0clx2r0e\"},
   {_id: 1, host: \"database.3.7bd9fotnkroq00c0n6rgyjm36\"},
   {_id: 2, host: \"database.1.vb17p0vpp6kgw4bpbat1a9sbh\"}
 ]
})"

用作“主机”的名称,每个 docker 主机都有 i 和docker container ls。输出:

[root@n1 ~]# docker container ls
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS       NAMES
f83f4fe69e87   mongo:latest   "docker-entrypoint.s…"   25 seconds ago   Up 20 seconds   27017/tcp   database.2.9qx7fuko225k8sojd0clx2r0e
[root@n2 ~]# docker container ls
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS       NAMES
99694587656b   mongo:latest   "docker-entrypoint.s…"   19 seconds ago   Up 13 seconds   27017/tcp   database.3.7bd9fotnkroq00c0n6rgyjm36
[root@n3 ~]# docker container ls
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS       NAMES
f83f4fe69e87   mongo:latest   "docker-entrypoint.s…"   38 seconds ago   Up 33 seconds   27017/tcp   database.1.vb17p0vpp6kgw4bpbat1a9sbh

到目前为止,一切都运行良好,我可以用 MongoDB 集群做任何我想做的事情。

现在,当我重新启动 docker 成员或故意停止 mongodb 容器进行测试时,只要所有 3 个数据库容器重新启动,集群就会损坏。

原因是,在其他 docker 主机上(重新)启动时,容器的名称不同。名称的最后一部分发生了变化,这破坏了我的集群配置。

例如:每次容器发生某些事情(重启/移动/崩溃)时,database.n.<whatever>这个值都会发生变化。<whatever>

我如何修复此问题并在 docker swarm 上部署 MongoDB 集群?

答案1

您的问题没有直接的解决方案,docker swarm 服务的容器不能设置静态主机名(而不是由 docker compose 在 docker 引擎中“手动”创建的主机名)。但是,有一个解决方法:

不要定义一个单独的群,使用您的服务replicas=3,而是定义三个单独的服务(可能在一个堆栈内),每个服务使用replicas=1,并根据服务名称(而不是单个容器名称)组装您的 mongo 副本集。

请注意,如果您的集群中有多个节点并且正在运行本地卷,您还需要确保每个副本始终在同一个物理节点上运行。您可以通过为每个节点分配一个唯一标签(例如docker node update --label-add mongo_replica=replica01 nodename),然后在此基础上添加放置约束(例如--constraint 'node.labels.mongo_replica == replica01',请注意此处的双重等号!)来实现这一点。

这种方法的缺点是,随着副本数量的增长,扩展需要为每个副本创建一个全新的附加服务,而不是简单docker service scale mongodb=4或类似的。

相关内容