基于Docker的MongoDB集群搭建

原文:https://www.yuque.com/wfzx/ninzck/dagu5akm0ztfuobw?singleDoc# 《基于Docker的MongoDB集群搭建》

实验环境

虚拟主机

在Window 10上使用 VMware 开启四个 Ubuntu 18 的虚拟主机。
基于Docker的MongoDB集群搭建_第1张图片
MongoDB A:192.168.204.156(主节点)
MongoDB B:192.168.204.157
MongoDB C:192.168.204.158
MongoDB D:192.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 的注释,在这里,需要注意修改bindIp的值,完整配置如下:

# 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)
}

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

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

use study
# 登录从节点, 执行同步语句
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},
])


# 登录从节点
use study
db.auth("user", "123456")
use study
db.myt.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")

附:复制集成员的配置参数

基于Docker的MongoDB集群搭建_第2张图片

附:关于常见角色

内置角色

  • 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)

你可能感兴趣的:(《高级,Java,工程师体系课》训练营学习笔记,mongodb,docker,集群,复制集,读写分离)