使用docker-compose部署MongoDB shard-cluster

本文介绍如何使用Docker和docker-compose部署MongoDB分片集群,涉及镜像制作、集群结构和配置步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要参考官网文档:Deploy a Sharded Cluster — MongoDB Manual

1. docker镜像

可以使用官方提供的镜像,也可以自己做。

我自己做了一个,只要将从官网下载的二进制文件打入镜像,再下载一个依赖libcurl4即可。

FROM ubuntu:22.04
add bin/ /usr/bin
add sources.list /etc/apt
run apt update && apt install -y libcurl4
VOLUME /data/db
ENTRYPOINT ["/usr/bin/mongod"]

2. 集群架构

如上图所示,为简化部署,mongos和config节点都使用单节点,部署了两个用作分片的replica-set,分别命名为RS0和RS1。各使用两个节点做高可用。

3. 部署容器

3.1 docker-compose文件

涉及到6个docker容器,所以决定使用docker-compose来编排部署,

由于构建rs时需要录入每个节点的地址,这里给每个容器都事先分配好了地址,这样配置的时候直接使用即可。

version: "3.8"
services:
  configserver:
    image: mongodb/mongodb-community-server:latest
    volumes:
    - type: volume
      source: configserver
      target: /data/configdb
      read_only: false
    command: ["mongod", "--configsvr", "--replSet", "configRS", "--dbpath", "/data/configdb", "--bind_ip_all"]
    networks:
      shard_cluster:
        ipv4_address: 192.168.31.201
  rs00:
    image: mongodb/mongodb-community-server:latest
    volumes:
    - type: volume
      source: data00
      target: /data/db
    networks:
      shard_cluster:
        ipv4_address: 192.168.31.211
    command: ["mongod", "--shardsvr", "--replSet", "RS0", "--dbpath", "/data/db", "--bind_ip_all"]
  rs01:
    image: mongodb/mongodb-community-server:latest
    volumes:
    - type: volume
      source: data01
      target: /data/db
    networks:
      shard_cluster:
        ipv4_address: 192.168.31.212
    command: ["mongod", "--shardsvr", "--replSet", "RS0", "--dbpath", "/data/db", "--bind_ip_all"]
  rs10:
    image: mongodb/mongodb-community-server:latest
    volumes:
    - type: volume
      source: data10
      target: /data/db
    networks:
      shard_cluster:
        ipv4_address: 192.168.31.213
    command: ["mongod", "--shardsvr", "--replSet", "RS1", "--dbpath", "/data/db", "--bind_ip_all"]
  rs11:
    image: mongodb/mongodb-community-server:latest
    volumes:
    - type: volume
      source: data11
      target: /data/db
    networks:
      shard_cluster:
        ipv4_address: 192.168.31.214
    command: ["mongod", "--shardsvr", "--replSet", "RS1", "--dbpath", "/data/db", "--bind_ip_all"]
  mongos:
    image: mongodb/mongodb-community-server:latest
    command: ["mongos", "--configdb", "configRS/192.168.31.201:27019", "--bind_ip_all"]
    ports:
      - target: 27017
        published: 27017
        protocol: tcp
    networks:
      shard_cluster:
        ipv4_address: 192.168.31.221
networks:
  shard_cluster:
    ipam:
      config:
        - subnet: 192.168.31.0/24
volumes:
  configserver:
  data00:
  data01:
  data10:
  data11:

3.2 部署容器

执行命令即可部署

docker-compose up -d

3.3 配置集群

配置configserver

$docker exec -it mongo_cluster_configserver_1 mongosh --port 27019
test> rs.initiate({_id: "configRS", configsvr: true, members:[{_id: 0, host: "192.168.31.201:27019"}]})

配置数据节点

$ docker-compose exec rs00   mongosh --port 27018
test> rs.initiate({_id: "RS0", members: [{_id:0, "host": "192.168.31.211:27018"},{_id:1, host: "192.168.31.212:27018"}]})

$ docker-compose exec rs10   mongosh --port 27018
test> rs.initiate({_id: "RS1", members: [{_id:0, "host": "192.168.31.213:27018"},{_id:1, host: "192.168.31.214:27018"}]})

配置mongos

$ docker-compose exec mongos   mongosh --port 27017
[direct: mongos] test> sh.addShard( "RS0/192.168.31.211:27018,192.168.31.212:27018")
{
  shardAdded: 'RS0',
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1696212363, i: 5 }),
    signature: {
      hash: Binary.createFromBase64("AAAAAAAAAAAAAAAAAAAAAAAAAAA=", 0),
      keyId: Long("0")
    }
  },
  operationTime: Timestamp({ t: 1696212363, i: 5 })
}
[direct: mongos] test> sh.addShard( "RS1/192.168.31.213:27018,192.168.31.214:27018")
{
  shardAdded: 'RS1',
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1696212377, i: 13 }),
    signature: {
      hash: Binary.createFromBase64("AAAAAAAAAAAAAAAAAAAAAAAAAAA=", 0),
      keyId: Long("0")
    }
  },
  operationTime: Timestamp({ t: 1696212377, i: 3 })
}

验证功能

1. 在集合上开启分片
sh.shardCollection("test.testc", { _id : "hashed" } )
2. 在集合插入数据
for(i=0; i<1000;i++) {db.testc.insertOne({"name": "User_" + i});}
3. 到单个rs上查看
$ docker-compose exec rs00   mongosh --port 27018
RS0 [direct: primary] test> db.testc.countDocuments()
531

可以看到单个rs上存放了约一半的数据,分片生效
 

<think>嗯,用户在使用docker-compose部署MongoDB分片副本集时,初始化后执行分片脚本总是失败。这个问题可能由多个因素引起,我需要一步步分析可能的原因,并提供解决方案。 首先,用户可能遇到网络连接问题。在Docker环境中,各个容器之间的通信依赖于正确的网络配置。如果分片服务、配置服务器和路由服务(mongos)不在同一个Docker网络中,它们可能无法相互访问。需要确认docker-compose.yml中所有服务都连接到同一个自定义网络,并且使用容器名称作为主机名进行通信。 接下来,服务启动顺序可能是一个问题。MongoDB的副本集初始化需要在所有节点启动并准备好之后才能进行。如果脚本在容器启动后立即执行,可能某些节点还未完成启动过程,导致连接失败。可以考虑在脚本中添加等待机制,例如使用循环检查端口是否开放,或者使用类似wait-for-it的工具来确保依赖服务已就绪。 然后,副本集配置是否正确也很关键。初始化分片前,每个分片的副本集必须正确配置,包括正确的成员信息和正确的优先级。用户需要检查副本集的初始化脚本,确认rs.initiate()命令是否正确指定了所有成员,并且配置服务器副本集是否已经成功初始化。此外,分片添加到集群时需要使用副本集名称作为主机地址,例如shard1/shard1-1:27017,shard1-2:27017,而不是单独的容器IP。 权限问题也不容忽视。如果启用了MongoDB的身份验证,执行脚本时需要提供正确的用户名和密码。需要确认mongos连接字符串中包含认证信息,并且用户拥有足够的权限执行分片操作。此外,Docker卷的权限可能导致初始化脚本无法写入数据,需要检查宿主机的目录权限是否允许容器内的MongoDB进程读写。 脚本语法错误或执行顺序错误可能也是一个原因。比如,必须先初始化所有分片的副本集,然后初始化配置服务器副本集,最后启动mongos并添加分片。如果顺序颠倒,会导致添加分片失败。需要确保脚本中的命令按照正确的顺序执行,并且每个步骤都成功完成后再进行下一步。 此外,日志分析是解决问题的关键。用户应检查各个容器的日志,查看是否有错误信息。使用docker-compose logs [服务名]可以获取详细的日志输出,帮助定位问题所在。例如,副本集初始化失败时,日志中可能会有连接超时或认证失败的信息。 举个例子,用户可能在添加分片时使用了错误的副本集名称或主机地址。正确的做法是使用副本集名称和容器名称组成的地址,确保mongos能够正确解析并连接到各个分片节点。另外,MongoDB的版本兼容性也可能导致问题,不同版本在配置上可能有差异,需要确认所有容器使用相同或兼容的版本。 最后,建议用户分步骤验证每个环节。首先确认各个副本集初始化成功,然后检查配置服务器是否正常,接着验证mongos能否正确连接配置服务器,最后逐步执行添加分片的命令。如果可能,提供一个示例的docker-compose文件和初始化脚本供用户参考,确保配置的正确性。</think>以下针对Docker-compose部署MongoDB分片副本集时初始化分片失败的常见问题,给出分步排查指南: --- ### 一、网络连接问题排查 #### 1. 检查Docker网络配置 ```yaml # docker-compose.yml关键配置示例 services: shard1-rs1: networks: - mongo_cluster # 必须使用相同网络 mongos: networks: - mongo_cluster networks: mongo_cluster: driver: bridge ``` #### 2. 验证容器间通信 ```bash # 进入mongos容器执行 docker-compose exec mongos bash ping shard1-rs1 # 应能解析容器IP telnet shard1-rs1 27017 # 验证端口可达性 ``` --- ### 二、服务启动时序问题 #### 1. 添加等待机制脚本 ```bash # wait-for.sh示例(需放入容器) until nc -z shard1-rs1 27017; do echo "等待shard1节点启动..." sleep 2 done ``` #### 2. 在初始化脚本中添加延迟 ```bash # 初始化分片脚本示例 sleep 20 # 等待副本集选举完成 mongosh --host mongos --eval "sh.addShard('shard1/shard1-rs1:27017')" ``` --- ### 三、副本集配置验证 #### 1. 检查副本集状态 ```javascript // 连接到分片容器执行 rs.status() // 应返回: // { // "set": "shard1", // "members": [ ... ], // "ok": 1 // } ``` #### 2. 正确的分片添加命令格式 ```javascript // 必须使用副本集名称+成员列表格式 sh.addShard("shard1/shard1-rs1:27017,shard1-rs2:27017,shard1-rs3:27017") ``` --- ### 四、典型错误解决方案 #### 1. 认证失败问题 ```yaml # mongos服务环境变量需包含 environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example ``` ```javascript // 带认证的连接命令 mongosh -u root -p example --host mongos --eval "..." ``` #### 2. 数据持久化问题 ```yaml volumes: - ./shard1/data:/data/db # 确保宿主机目录存在且有写权限 ``` ```bash chmod -R 777 ./shard1/data # Linux系统权限修复 ``` --- ### 五、调试命令参考 #### 1. 查看实时日志 ```bash docker-compose logs -f shard1-rs1 # 查看指定分片日志 ``` #### 2. 强制重新初始化 ```bash docker-compose down -v # 清除旧数据卷 docker-compose up -d ``` --- ### 六、完整配置示例 ```yaml version: '3.7' services: configsvr1: image: mongo:6.0 command: mongod --configsvr --replSet cfgrs --bind_ip_all networks: - mongo_cluster shard1-rs1: image: mongo:6.0 command: mongod --shardsvr --replSet shard1 --bind_ip_all networks: - mongo_cluster mongos: image: mongo:6.0 command: mongos --configdb cfgrs/configsvr1:27017 --bind_ip_all ports: - "27017:27017" depends_on: - configsvr1 networks: - mongo_cluster networks: mongo_cluster: ``` --- ### 排查流程图 1. 检查网络连通性 → 2. 验证副本集状态 → 3. 检查认证配置 → 4. 查看错误日志 → 5. 验证分片添加命令格式 通过以上步骤,90%以上的分片初始化失败问题可以得到解决。若仍存在问题,建议提供具体的错误日志信息以便进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值