基于Docker的MongoDB集群搭建

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

实验环境

虚拟主机

在Window 10上使用 VMware 开启四个 Ubuntu 18 的虚拟主机。
image.png
MongoDB A192.168.204.156主节点
MongoDB B192.168.204.157
MongoDB C192.168.204.158
MongoDB D192.168.204.159

host 配置

host文件位于 C:\Windows\System32\drivers\etc\hosts

192.168.204.156 mongodba
192.168.204.157 mongodbb
192.168.204.158 mongodbc
192.168.204.159 mongodbd

拉取MongDB 的镜像

实验的MongoDB版本MongoDB server version: 5.0.5

# 查询镜像
root@ubuntu:/home/liangshijie/mongodb-docker-file# docker search mongodb
NAME                                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mongo                                                  MongoDB document databases provide high avai…   9439      [OK]
mongo-express                                          Web-based MongoDB admin interface, written w…   1279      [OK]
bitnami/mongodb                                        Bitnami MongoDB Docker Image                    205                  [OK]
percona/percona-server-mongodb                         Percona Server for MongoDB docker images        36
rapidfort/mongodb                                      RapidFort optimized, hardened image for Mong…   15
circleci/mongo                                         CircleCI images for MongoDB                     12                   [OK]
bitnami/mongodb-sharded                                                                                9
...

# 拉取第一个
docker pull mongo

集群配置

官方文档https://www.mongodb.com/compatibility/docker

一、配置主节点

1.准备

# 创建基本目录
cd /home/liangshijie/mongodb-docker-file
# 要注意创建的文件夹docker进程是否有权限操作
mkdir data
mkdir log
mkdir conf

chmod 777 data

# 创建日志文件。 # 提高权限不然权限错误
touch ./log/mongod.log
chmod 777 ./log/mongod.log

# 生成密钥文件。
# 后续要将密钥文件拷贝到服务器所以在降低key.file密钥文件权限前你可能需要先将其拷贝到其它服务器。
openssl rand -base64 756 > ./conf/key.file
# 降低权限不然权限错误
chmod 400 ./conf/key.file

# 创建配置文件。具体内容看后面
vim ./conf/mongod.conf.orig


# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb  # 数据存储的目录默认就好
  journal:
    enabled: true
#  engine:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file  # 日志写入到文件
  logAppend: true  # 追加的方式
  path: /var/log/mongodb/mongod.log   # 日志文件位置默认就好

# network interfaces
#net:
 # port: 27017
 # bindIp: 127.0.0.1


# how the process runs
processManagement:
  timeZoneInfo: /usr/share/zoneinfo

#security:
#security:
#  keyFile: /data/configdb/key.file  # 集群节点之间使用我们生成的密钥进行权限验证
#replication:
#  replSetName: mongoCluster  # 指定集群名称
net:
   bindIp: mongodba  # 要绑定的地址一般不写IP
#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:

🐖温馨提示后续要将密钥文件拷贝到服务器所以在降低key.file密钥文件权限前你可能需要先将其拷贝到其它服务器。

2.启动

docker run -u root --name mongodb -d -p 27017:27017 \
-v /home/liangshijie/mongodb-docker-file/data:/var/lib/mongodb \
-v /home/liangshijie/mongodb-docker-file/conf:/data/configdb \
-v /home/liangshijie/mongodb-docker-file/log:/var/log/mongodb \
--hostname="mongodba" \
mongo --config /data/configdb/mongod.conf.orig 

🐖由于指定了日志文件的位置所以使用容器命令 docker logs -f是不会打印日志的日志输出到这个位置了./log/mongod.log。
🐖配置文件mongod.conf.orig的位置指定的是容器内的位置。
🐖如果只是想快速启动一个 MongoDB 容器可以使用这条命令
docker run --name mongodb -d -p 27017:27017 -v /home/liangshijie/mongodb-docker-file/data:/data/db -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=123456 mongo

3.创建用户

# 进入容器
docker exec -it <容器ID> bash
cd /usr/bin
mongo --host mongodba

# 创建管理员用户用于登录主节点初始化集群
db.createUser( {
  user: "root",
  pwd: "123456",
  roles: [ { role: "root", db: "admin" } ]
});

# 创建读写用户可以后面再创建用于主节点的读写操作在从节点登录只能只读
db.createUser({ user:'user',pwd:'123456',roles:[ { role:'readWrite', db: 'study'}]});

# 退出
exit

4.配置密钥

集群通信需要密钥。

vim ./conf/mongod.conf.orig

# 在上面的配置文件中我已经写好了配置只需要把下面的注释放开即可:
security:
  keyFile: /data/configdb/key.file  # 集群节点之间使用我们生成的密钥进行权限验证
replication:
  replSetName: mongoCluster  # 指定集群名称

# 可选降低配置文件的权限
chmod 400 ./conf/mongod.conf.orig

🐖为什么之前不放开配置因为一早放开的话没有权限创建用户等创建好用户再放开。

5.重启

docker restart <容器ID>

6.初始化集群

# 进入容器
docker exec -it <容器ID> bash

cd /usr/bin
# 登录
mongo --host mongodba
# 认证
db.auth("root","123456")
# 初始化
rs.initiate()
# 结果如下
{
        "info2" : "no configuration specified. Using a default configuration for the set",
        "me" : "mongodba:27017",
        "ok" : 1
}

# 查看状态
rs.status()

# 在从节点已经就绪的情况下我们也可以通过下面配置初始化集群。

var cfg ={"_id":"heroMongoCluster",
  "protocolVersion" : 1,
  "members":[
    {"_id":1,"host":"mongodba:27017","priority":10},
    {"_id":2,"host":"mongodbb:27017","priority":1},
    {"_id":2,"host":"mongodbc:27017","priority":1},
    {"_id":2,"host":"mongodbd:27017","priority":1}
  ]
};

rs.initiate(cfg)

二、配置从节点

1.准备

从节点跳过生成密钥的步骤。

# 创建基本目录
cd /home/liangshijie/mongodb-docker-file
# 要注意创建的文件夹docker进程是否有权限操作
mkdir data
mkdir log
mkdir conf

chmod 777 data

# 创建日志文件。 # 提高权限不然权限错误
touch ./log/mongod.log
chmod 777 ./log/mongod.log

# 创建配置文件。具体复制后面的
vim ./conf/mongod.conf.orig

# 最后降低权限(可选)
chmod 400 ./conf/mongod.conf.orig

跟主节点配置不一样的地方就是一开始就放开 security 的注释完整配置如下

# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb  # 数据存储的目录默认就好
  journal:
    enabled: true
#  engine:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file  # 日志写入到文件
  logAppend: true  # 追加的方式
  path: /var/log/mongodb/mongod.log   # 日志文件位置默认就好

# network interfaces
#net:
 # port: 27017
 # bindIp: 127.0.0.1


# how the process runs
processManagement:
  timeZoneInfo: /usr/share/zoneinfo

#security:
security:
  keyFile: /data/configdb/key.file  # 集群节点之间使用我们生成的密钥进行权限验证
replication:
  replSetName: mongoCluster  # 指定集群名称
net:
  bindIp: mongodbb  # 要绑定的地址一般不写IP
#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:

2.复制主节点的密钥文件

将主节点的 key.file 文件复制到从节点的 ./conf 目录下。不拷贝文件也行cat输出文件内容复制粘贴也是可以的

🐖遇到拷贝不进conf的情况请检查目录权限。 chmod 777 ./conf 开放上传之后再 chmod 755 ./conf 收回。
注意conf目录下的 key.file 权限是 400。 配置文件是 755

3.启动

docker run --name mongodb -d -p 27017:27017 \
-v /home/liangshijie/mongodb-docker-file/data:/var/lib/mongodb \
-v /home/liangshijie/mongodb-docker-file/conf:/data/configdb \
-v /home/liangshijie/mongodb-docker-file/log:/var/log/mongodb \
--hostname="mongodbb" \
mongo --config /data/configdb/mongod.conf.orig 

同理其它几个从节点也是这样配置注意要改一下配置文件中 bindIp 属性以及启动命令中--hostname的属性。

三、在主节点中新增、删除从节点

新增从节点

🐖你需要确保主、从节点容器之间能正常通信。如果你想在容器内测试能不能ping同其它主机的mongo服务可以在容器内安装ping
apt-get update
apt-get install iputils-ping

# 进入主节点的mongodb容器
docker exec -it <容器ID> bash

cd /usr/bin
# 登录
mongo --host mongodba
# 认证
db.auth("root","123456")

# 增加从节点
rs.add("mongodbb:27017")
# 执行结果
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1675486280, 1),
                "signature" : {
                        "hash" : BinData(0,"cwO0f4QXhKNfNGKZstysMTqrQ9w="),
                        "keyId" : NumberLong("7196151896959090692")
                }
        },
        "operationTime" : Timestamp(1675486280, 1)
}

rs.add("mongodbc:27017")
rs.add("mongodbd:27017")

删除从节点选看

# 删除slave 节点
rs.remove("172.17.187.80:37019")

查看配置选看

rs.conf()
{
        "_id" : "mongoCluster",
        "version" : 9,
        "term" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "mongodba:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "mongodbb:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 3,
                        "host" : "mongodbc:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 4,
                        "host" : "mongodbd:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "secondaryDelaySecs" : NumberLong(0),
                        "votes" : 1
                }
        ],
        "protocolVersion" : NumberLong(1),
        "writeConcernMajorityJournalDefault" : true,
        "settings" : {
                "chainingAllowed" : true,
                "heartbeatIntervalMillis" : 2000,
                "heartbeatTimeoutSecs" : 10,
                "electionTimeoutMillis" : 10000,
                "catchUpTimeoutMillis" : -1,
                "catchUpTakeoverDelayMillis" : 30000,
                "getLastErrorModes" : {

                },
                "getLastErrorDefaults" : {
                        "w" : 1,
                        "wtimeout" : 0
                },
                "replicaSetId" : ObjectId("63ddde05097f7140da2e9c0a")
        }
}

查看状态选看

执行 rs.status() 查看状态在 members 属性中可以看到节点列表信息。

rs.status()
{
  "set" : "mongoCluster",
  "date" : ISODate("2023-02-04T04:52:11.084Z"),
  "myState" : 1,
  "term" : NumberLong(1),
  "syncSourceHost" : "",
  "syncSourceId" : -1,
  "heartbeatIntervalMillis" : NumberLong(2000),
  "majorityVoteCount" : 2,
  "writeMajorityCount" : 2,
  "votingMembersCount" : 2,
  "writableVotingMembersCount" : 2,
  "optimes" : {
    "lastCommittedOpTime" : {
      "ts" : Timestamp(1675486328, 1),
      "t" : NumberLong(1)
    },
    "lastCommittedWallTime" : ISODate("2023-02-04T04:52:08.443Z"),
    "readConcernMajorityOpTime" : {
      "ts" : Timestamp(1675486328, 1),
      "t" : NumberLong(1)
    },
    "appliedOpTime" : {
      "ts" : Timestamp(1675486328, 1),
      "t" : NumberLong(1)
    },
    "durableOpTime" : {
      "ts" : Timestamp(1675486328, 1),
      "t" : NumberLong(1)
    },
    "lastAppliedWallTime" : ISODate("2023-02-04T04:52:08.443Z"),
    "lastDurableWallTime" : ISODate("2023-02-04T04:52:08.443Z")
  },
  "lastStableRecoveryTimestamp" : Timestamp(1675486292, 1),
  "electionCandidateMetrics" : {
    "lastElectionReason" : "electionTimeout",
    "lastElectionDate" : ISODate("2023-02-04T04:24:38.141Z"),
    "electionTerm" : NumberLong(1),
    "lastCommittedOpTimeAtElection" : {
      "ts" : Timestamp(1675484677, 1),
      "t" : NumberLong(-1)
    },
    "lastSeenOpTimeAtElection" : {
      "ts" : Timestamp(1675484677, 1),
      "t" : NumberLong(-1)
    },
    "numVotesNeeded" : 1,
    "priorityAtElection" : 1,
    "electionTimeoutMillis" : NumberLong(10000),
    "newTermStartDate" : ISODate("2023-02-04T04:24:38.243Z"),
    "wMajorityWriteAvailabilityDate" : ISODate("2023-02-04T04:24:38.285Z")
  },
  "members" : [
    {
      "_id" : 0,
      "name" : "mongodba:27017",
      "health" : 1,
      "state" : 1,
      "stateStr" : "PRIMARY",
      "uptime" : 1932,
      "optime" : {
        "ts" : Timestamp(1675486328, 1),
        "t" : NumberLong(1)
      },
      "optimeDate" : ISODate("2023-02-04T04:52:08Z"),
      "lastAppliedWallTime" : ISODate("2023-02-04T04:52:08.443Z"),
      "lastDurableWallTime" : ISODate("2023-02-04T04:52:08.443Z"),
      "syncSourceHost" : "",
      "syncSourceId" : -1,
      "infoMessage" : "",
      "electionTime" : Timestamp(1675484678, 1),
      "electionDate" : ISODate("2023-02-04T04:24:38Z"),
      "configVersion" : 4,
      "configTerm" : 1,
      "self" : true,
      "lastHeartbeatMessage" : ""
    },
    {
      "_id" : 1,
      "name" : "172.17.187.80:37019",
      "health" : 0,
      "state" : 8,
      "stateStr" : "(not reachable/healthy)",
      "uptime" : 0,
      "optime" : {
        "ts" : Timestamp(0, 0),
        "t" : NumberLong(-1)
      },
      "optimeDurable" : {
        "ts" : Timestamp(0, 0),
        "t" : NumberLong(-1)
      },
      "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
      "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
      "lastAppliedWallTime" : ISODate("1970-01-01T00:00:00Z"),
      "lastDurableWallTime" : ISODate("1970-01-01T00:00:00Z"),
      "lastHeartbeat" : ISODate("2023-02-04T04:52:09.266Z"),
      "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
      "pingMs" : NumberLong(0),
      "lastHeartbeatMessage" : "Error connecting to 172.17.187.80:37019 :: caused by :: No route to host",
      "syncSourceHost" : "",
      "syncSourceId" : -1,
      "infoMessage" : "",
      "configVersion" : -1,
      "configTerm" : -1
    },
    {
      "_id" : 2,
      "name" : "mongodbb:27017",
      "health" : 1,
      "state" : 2,
      "stateStr" : "SECONDARY",
      "uptime" : 50,
      "optime" : {
        "ts" : Timestamp(1675486328, 1),
        "t" : NumberLong(1)
      },
      "optimeDurable" : {
        "ts" : Timestamp(1675486328, 1),
        "t" : NumberLong(1)
      },
      "optimeDate" : ISODate("2023-02-04T04:52:08Z"),
      "optimeDurableDate" : ISODate("2023-02-04T04:52:08Z"),
      "lastAppliedWallTime" : ISODate("2023-02-04T04:52:08.443Z"),
      "lastDurableWallTime" : ISODate("2023-02-04T04:52:08.443Z"),
      "lastHeartbeat" : ISODate("2023-02-04T04:52:10.446Z"),
      "lastHeartbeatRecv" : ISODate("2023-02-04T04:52:11.046Z"),
      "pingMs" : NumberLong(0),
      "lastHeartbeatMessage" : "",
      "syncSourceHost" : "mongodba:27017",
      "syncSourceId" : 0,
      "infoMessage" : "",
      "configVersion" : 4,
      "configTerm" : 1
    }
  ],
  "ok" : 1,
  "$clusterTime" : {
    "clusterTime" : Timestamp(1675486328, 1),
    "signature" : {
      "hash" : BinData(0,"qdS8hsuZZ6jdGUDjvFV2bKIFxkE="),
      "keyId" : NumberLong("7196151896959090692")
    }
  },
  "operationTime" : Timestamp(1675486328, 1)
}

四、从节点跟主节点进行同步

🐖容器重启一般要重新进行同步

# 登录从节点, 执行同步语句
db.auth("user", "123456")

# 同步。低版本的命令 rs.slaveOk()
rs.secondaryOk()

show dbs

五、测试

# 进入主节点执行
docker exec -it <容器ID> bash
cd /usr/bin

mongo --host mongodba

db.auth("user","123456")

use study

db.myt.insertMany([
  {xm:"李四",age:24},
  {xm:"王五",age:25},
  {xm:"赵六",age:26},
  {xm:"李四",age:34},
  {xm:"王五",age:35},
  {xm:"赵六",age:36}
])

db.myt.insertMany([
  {xm:"孙七",age:44},
])


# 登录从节点
db.auth("user", "123456")
use study
db.my.find()

补充重新加载集群配置重新生成集群节点

var cfg ={"_id":"heroMongoCluster",
  "protocolVersion" : 1,
  "members":[
    {"_id":1,"host":"172.17.187.80:37017","priority":10},
    {"_id":2,"host":"172.17.187.80:37018","priority":0},
    {"_id":3,"host":"172.17.187.80:37019","priority":5},
    {"_id":4,"host":"172.17.187.80:37020","arbiterOnly":true}
  ]
};


// 重新装载配置并重新生成集群节点。
rs.reconfig(cfg)

补充添加仲裁节点

rs.addArb("172.17.187.80:37020")

附复制集成员的配置参数

image.png

附关于常见角色

内置角色

  • read允许用户读取指定数据库
  • readWrite允许用户读写指定数据库
  • dbAdmin允许用户在指定数据库中执行管理函数如索引创建、删除查看统计或访问
  • userAdmin允许用户向system.users集合写入可以找指定数据库里创建、删除和管理用户
  • clusterAdmin只在admin数据库中可用赋予用户所有分片和复制集相关函数的管理权限
  • readAnyDatabase只在admin数据库中可用赋予用户所有数据库的读权限
  • readWriteAnyDatabase只在admin数据库中可用赋予用户所有数据库的读写权限
  • userAdminAnyDatabase只在admin数据库中可用赋予用户所有数据库的userAdmin权限
  • dbAdminAnyDatabase只在admin数据库中可用赋予用户所有数据库的dbAdmin权限
  • root只在admin数据库中可用。超级账号超级权限
  • dbOwner库拥有者权限即readWrite、dbAdmin、userAdmin角色的合体

角色分类

  • 数据库用户角色read、readWrite
  • 数据库管理角色dbAdmin、dbOwner、userAdmin
  • 集群管理角色clusterAdmin、clusterManager、clusterMonitor、hostManager
  • 备份恢复角色backup、restore
  • 所有数据库角色readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
  • 超级用户角色root
  • 这里还有几个角色间接或直接提供了系统超级用户的访问dbOwner 、userAdmin、userAdminAnyDatabase
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: goDocker