Fork me on GitHub

mongodb副本集的docker化安装

1. 定义

一般只要生产环境就需要考虑冗余设计,保证在某一台服务器由于某种原因宕机后服务还可以正常运行。

mongo副本集是一组服务器,其中有一个主服务器(primary),用于处理客户端请求;还有多个备份服务器(secondary),用于保存主服务器的数据副本。如果主服务器崩溃了,备份服务器就会自动将其中一个成员升级为新的主服务器。

副本集在选主的过程中有一个很重要的概念叫“大多数(majority)”,选择主节点需要由大多数决定,主节点只有在得到大多数支持时才能继续作为主节点,写操作被复制到大多数成员时,这个写操作就是安全的。这里的大多数被定义为“副本中一半以上成员”。这些副本集中的成员挂了或者不可用,并不会影响“大多数”,因为“大多数”是基于副本集的配置来计算的,如下表:

那怎样才能算大多数
1 1
2 2
3 2
4 3
5 3
6 4
7 4

副本集中通过设置priority的值来决定优先权的大小,这个值的范围是0--100,值越大,成为主的优先权越高。

目前读写分离的几种模式:

primary 主节点,默认模式,读操作只在主节点,如果主节点不可用,报错或者抛出异常。
primaryPreferred 首选主节点,大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点
secondary 从节点,读操作只在从节点, 如果从节点不可用,报错或者抛出异常。
secondaryPreferred 首选从节点,大多情况下读操作在从节点,特殊情况(如单主节点架构)读操作在主节点。
nearest 最邻近节点,读操作在最邻近的成员,可能是主节点或者从节点

 

2. 安装

有了以上概念,就开始来部署副本集,我们设计3个mongo节点,分别如下:

名称 数据存储位置 优先级 docker映射端口 mongo启动端口
mongo1 /data/mongo/data1 1 27117 27017
mongo2 /data/mongo/data2 0.5 27217 27017
mongo3 /data/mongo/data3 0.8 27317 27017

那么开始启动mongo容器:

docker run --name mongo1 -v /data/mongo/data1:/data/db -d  -p 27117:27017 mongo:3.4.2 --replSet ms
docker run --name mongo2 -v /data/mongo/data2:/data/db -d  -p 27217:27017 mongo:3.4.2 --replSet ms
docker run --name mongo3 -v /data/mongo/data3:/data/db -d  -p 27317:27017 mongo:3.4.2 --replSet ms

3个均启动完成,随便进入到一个容器里,如mongo1,并连接到数据库

[root@vhost18 mongo]# docker exec -it mongo1 bash
root@a04f48f03f1e:/#
root@a04f48f03f1e:/# mongo
MongoDB shell version v3.4.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.2
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-12-24T09:06:15.245+0000 I CONTROL [initandlisten]
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten]
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten]
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten]
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-12-24T09:06:15.246+0000 I CONTROL [initandlisten]
>

传入配置并初始化:

config={_id:"ms",members:[{_id:0,host:"ip:27117", priority:1},{_id:1,host:"ip:27217", priority:0.5},{_id:2,host:"ip:27317", priority:0.8}]}

rs.initiate(config);

执行成功后是这样的:

节点在经过短暂的同步后,登陆mongo的控制台会显示成ms:PRIMARY,备份节点会显示成ms:SECONDARY,此时副本集就安装好了。

3. 验证

进入primary服务器,随便创建一个测试数据库和测试表数据:

ms:PRIMARY> use test
switched to db test
ms:PRIMARY> db.testCollection.insert({"key":"value"})
WriteResult({ "nInserted" : 1 })
ms:PRIMARY> db.testCollection.find()
{ "_id" : ObjectId("5c20a3d7c5d174307dc3d516"), "key" : "value" }

然后进入secondary服务器查一下数据,会出现如下结果:

ms:SECONDARY> use test
switched to db test
ms:SECONDARY> db.testCollection.find()
Error: error: {
    "ok" : 0,
    "errmsg" : "not master and slaveOk=false",
    "code" : 13435,
    "codeName" : "NotMasterNoSlaveOk"
}

这是因为secondary服务器在写多读少的应用使用Replica Sets来实现读写分离。通过在连接时指定或者在主库指定slaveOk,由secondary来分担读的压力,primary只承担写操作

此时为了检测设置为slaveOk,并重新查询一下,会出现如下结果:

ms:SECONDARY> rs.slaveOk()
ms:SECONDARY> db.testCollection.find()
{ "_id" : ObjectId("5c20a3d7c5d174307dc3d516"), "key" : "value" }

可以检测到副本集生效了。

这时候主动把primary宕机或者删除,就可以看到主节点转移到mongo3了,为什么呢,因为我们配置的时候mongo3的priority比mongo2高。

 4. 开启密码验证

副本集的验证与mongo单机开启验证不同:

mongo单机版本只需要在admin库中的system.user表里加好用户后就默认开启了验证模式。

mongo副本集在admin库中的system.user表里加好用户后,需要显示开启验证模式(启动参数添加:--auth),那么副本集之间的互相反问就需要用到keyFile了。

keyFile几个注意点:

  1. 权限不能太大,不然会报“permissions on xxx are too open”
  2. 权限不能太小,不然会报“permission denied”

因此我们在创建keyFile的时候首要先把权限赋值好:

openssl rand -base64 741 >  mongodb.key
chmod 600 mongodb.key
#docker启动需要把赋为999
chown 999 mongodb.key

添加用户,需要到主节点上进行添加

docker exec -it mongo1 bash
mongo
use admin
db.createUser({user: "admin",pwd: "password",roles: [ { role: "root", db: "admin" } ]})

添加好用户后重启副本集,启动带上验证和keyFile

docker rm -f mongo1 mongo2 mongo3

docker run --name mongo1 -v /data/mongo/data1:/data/db -v /data/mongo/config/mongodb.key:/mongodb.key -d -p 27117:27017 mongo:3.4.2 --replSet ms --keyFile=mongodb.key --auth

docker run --name mongo2 -v /data/mongo/data2:/data/db -v /data/mongo/config/mongodb.key:/mongodb.key -d -p 27217:27017 mongo:3.4.2 --replSet ms --keyFile=mongodb.key --auth

docker run --name mongo3 -v /data/mongo/data3:/data/db -v /data/mongo/config/mongodb.key:/mongodb.key -d -p 27317:27017 mongo:3.4.2 --replSet ms --keyFile=mongodb.key --auth

重启完成后进行验证,与上一步的验证一致。

这样带有权限验证的mongo副本集就创建完毕了。

posted @ 2018-12-24 17:23  张q  阅读(...)  评论(...编辑  收藏