Docker部署MongoDB集群(一主一从一仲裁)
在一个MongoDB复制集集群中,各个服务器有以下几种状态:
- master 主节点,一个复制集有且仅有一台服务器处于Primary状态,只有主节点才对外提供读写服务。如果主节点挂掉,复制集将投票选出一个备节点成为新的主节点。
- slave 备用节点,复制集允许有多台Secondary,每个备用节点的数据与主节点的数据是完全同步的。Recovering 恢复中,当复制集中某台服务器挂掉或者掉线后数据无法同步,重新恢复服务后从其他成员复制数据,这时就处于恢复过程,数据同步后,该节点又回到备用状态。
- Arbiter 仲裁节点,该类节点可以不用单独存在,如果配置为仲裁节点,就主要负责在复本集中监控其他节点状态,投票选出主节点。该节点将不会用于存放数据。如果没有仲裁节点,那么投票工作将由所有节点共同进行。
准备工作:
- centos7系统及已安装的docker
- mongodb4.0
- 三台机器 :
主节点:192.168.3.80 ------master(node1)
从节点:192.168.3.81 ------slave(node2)
仲裁节点:192.168.3.103 ------arbiter(node3)
架构图:
参考链接:
https://www.jianshu.com/p/7bfda4943034
步骤:
1.将下面给出的IP地址配置到所有的服务器上面,每一台服务器都要执行如下命令(记得要替换掉IP地址哦):
# export node1=192.168.3.80
# export node2=192.168.3.81
# export node3=192.168.3.103
2.在master服务器上面执行如下的命令,然后把密钥文件复制到其余两个服务器的同样的位置。
# mkdir -p /home/core/mongo-files
# cd /home/core/mongo-files
# openssl rand -base64 741 > mongodb-keyfile
# chmod 600 mongodb-keyfile
# sudo chown 999
mongodb-keyfile
这个密钥文件的所有者被设置成id为“999”的用户了,因为在MongoDB的Docker容器中,这个用户需要有操作密钥文件的权限
3.传输密钥并添加权限
在master节点上操作,把秘钥文件mongo-files,复制到slave的/home/core/mongo-files下,命令如下:
scp -r mongodb-keyfile root@192.168.3.81:/home/core/mongo-files
然后切换到slave节点里,给秘钥增加权限
chmod 600 mongodb-keyfile
sudo chown 999 mongodb-keyfile
scp -r mongodb-keyfile root@192.168.3.103:/home/core/mongo-files
把秘钥文件mongo-files,复制到arbiter的/home/core/mongo-files下,命令如下:
在master节点操作:mongodb-keyfile root@192.168.3.103:/home/core/mongo-files
然后切换到arbiter节点里,给秘钥增加权限
chmod 600 mongodb-keyfile
sudo chown 999 mongodb-keyfile
4.启动master(即第一台Docker服务器)的MongoDB容器。它会启动一个没有身份验证机制的容器,所以我们要设置一个用户。
root@master:/# docker run --name mongo \
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node1.example.com" \
-p 27017:27017 \
-d mongo:4.0 --smallfiles
注:没mongo:4.0镜像时,执行上面命令时会自动下载mongo:4.0
现在创建一个admin用户。我们可以连接到刚刚启动的mongoDB容器,并进入一个交互式的shell环境
root@master:/# docker exec -it mongo /bin/bash
这时候,我们就进到MongoDB的Docker容器里面了,然后我们要打开一个mongo shell环境:
root@master:/# mongo
上面的命令可以打开mongo shell环境。执行后你会看到这样的输出:
切换到admin用户:
> use admin
switched to db admin
创建一个新的site admin 用户
> db.createUser( {
user:
"siteUserAdmin",
pwd: "password",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]});
创建成功的话你会看到如下的成功信息:
创建一个root用户:
> db.createUser( { user: "siteRootAdmin",
pwd: "password",
roles: [
{
role: "root",
db: "admin"
}
]});
你会看到如下的成功信息:
我们已经创建好了我们以后要使用的几个用户,现在我们会退出交互式shell环境(mongo和Docker容器的环境)。我们输入两次exit退出去
5.停止并删除第一个MongoDB实例:
root@master:/# docker stop mongo (停止容器)
root@master:/# docker rm mongo (删除容器)
6.这次使用密钥文件启动第一台MongoDB实例(还是在master上面操作的)
docker run \
--name
mongo \
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node1.example.com" \
--add-host node1.example.com:${node1}
\
--add-host
node2.example.com:${node2} \
--add-host
node3.example.com:${node3} \
-p 27017:27017 -d mongo:4.0 \
--smallfiles
\
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0"
注意:
- --keyFile的路径是/opt/keyfile/mongodb-keyfile,这是正确的。这是密钥文件在Docker内部的地址,我们用-v选项将密钥文件映射到容器内部的那个路径上(即:/opt/keyfile/mongodb-keyfile)。
- --add-host把这些信息添加到Docker容器的/etc/hosts文件中,所以我们可以使用域名而不是IP地址了。在实际的生产环境中这些信息都是DNS,这些参数都可以忽略。
7.连接到副本集上并且安装配置好它。这还是在node1上面进行的。我们要开启另外一个新的交互式shell环境进入mongo容器,同时开启一个mongo shell环境:
root@master:/# docker exec -it mongo /bin/bash
root@master:/# mongo
MongoDB shell
version: v4.0.13
>
切换到admin用户下:
> use admin
switched to db admin
因为我们已经设置了一个密码,所以这次我们不得不做身份验证。我们把密码设置为:password。
> db.auth("siteRootAdmin", "password");
1
现在我们可以开启副本集:
> rs.initiate()
8.验证已经初始化的副本集的配置:
>rs0:PRIMARY> rs.conf()
9.在其余的两个节点启动MongoDB
在slave上面执行命令:
# docker run \
--name mongo
\
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node2.example.com" \
--add-host
node1.example.com:${node1} \
--add-host
node2.example.com:${node2} \
--add-host
node3.example.com:${node3} \
-p 27017:27017 -d mongo:4.0 \
--smallfiles
\
--keyFile /opt/keyfile/mongodb-keyfile \--replSet "rs0"
在arbiter上面执行命令:
# docker run \
--name mongo
\
-v /home/core/mongo-files/data:/data/db \
-v /home/core/mongo-files:/opt/keyfile \
--hostname="node3.example.com" \
--add-host
node1.example.com:${node1} \
--add-host
node2.example.com:${node2} \
--add-host node3.example.com:${node3}
\
-p 27017:27017 -d mongo:4.0 \
--smallfiles
\
--keyFile /opt/keyfile/mongodb-keyfile \
--replSet "rs0"
10.将那两个节点加到副本集上
回到master节点,如果你在这里按了几次回车键(enter)的话,你会看到下面的提示:“rs0:PRIMARY”。这是因为这个节点是副本集“rs0”的主节点。
首先将节点加入复制集:
rs0:PRIMARY> rs.add("node2.example.com")
rs0:PRIMARY> rs.addArb("node3.example.com")
修改节点的优先级:
db.auth("siteRootAdmin", "password"); --首先授权认证
将主节点的优先级设置为10
PRIMARY>rscfg.members[0].priority = 10
将从节点的优先级设置为2
PRIMARY>rscfg.members[1].priority = 2
PRIMARY> rs.reconfig(rscfg)
查看设置的优先级:
rs0:PRIMARY> rs.conf()
验证其它节点是否正确的加到这个副本集当中:
rs0:PRIMARY> rs.status()
结果如下说明节点添加成功
从库开启读操作(此时可以测试主库插入,从库查看,同步正常):
rs.slaveOk();
show dbs
local 0.000GB
mydb 0.000GB
可能会花几分钟的时间来将master上面的数据同步到其余的两个节点上面。你可以通过查看日志来观察每一个MongoDB的Docker容器里面发生了什么。在任意一个服务器上面执行下面的命令就可以了:
root@master*:/# docker logs -ft mongo
查看各节点的状态
rs.status()
查看各节点的配置及优先级
rs.conf()
查看整体状态:
rs.status()
查看主从节点的切换
停掉主节点
docker stop master_mongo
查看从节点变化
docker stop slave_mongo
可以看到从节点已经变成了primary
当主节点再次启动
它又再次变为primary
查看主从数据库同步:
插入数据库:
rs0:PRIMARY> use admin
rs0:PRIMARY> db.auth('rootAdmin','Admin168+);
rs0:PRIMARY> use Test01
rs0:PRIMARY> db.createUser( {
... ... user: "Test01",
... ... pwd: "password",
... ... roles: [ { role: "dbOwner", db: "Test01" } ]});
rs0:PRIMARY> db.Test01.insert([ { "title" : "fczlm", "year" : 2019, "imdb_rating" : 8.1 },{ "title" : "AAA", "year" : 2020, "imdb_rating" : 7.6 } ]);
查看数据库
rs0:PRIMARY> show dbs
验证 主从节点切换
优点:当主库挂掉,从库会被选为主库!当原先挂掉的主库再次启动,由于优先级的设置,挂掉的主库还是会变为主库
192.168.3.81变为主节点
再次启动主节点(192.168.3.80)查看其变化
测试 数据库同步
连接mongo数据库操作(其它两台操作同下)
输入IP地址及端口号
输入之前创建的root用户名和密码
user: "siteUserAdmin"
pwd: "password"
在主节点上创建数据库
创建思路:
在从节点中认证并查看
在Robo 3T上查验证
结论
现在你拥有了一个MongoDB集群。你可以自由的在任何时刻添加节点到这个集群上。你甚至可以关闭其中的一个节点,包括主节点,然后观察一个另外一个节点重新变成了主节点。由于这些数据都被写在了你的本机文件系统当中了,所以重启任何一个节点都不是什么大问题。