我尝试在 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
或类似的。