项目背景
由于历史原因,我们有一个作数据同步的业务,生产环境中MongoDB使用的是单节点。但随着业务增长,考虑到这个同步业务的重要性,避免由于单节点故障造成业务停止,所以需要升级为副本集保证高可用。
副本集架构
下面这架构图是这篇文章需要实现的MongoDB副本集高可用架构:
升级架构前注意事项
在生产环境中,做单节点升级到集群前,一定要先备份好mongodb的所有数据,避免操作失误导致数据丢失。
并且在保证在升级期间不会有程序连接到MongoDB进行读写操作,建议停服务升级,且在凌晨业务低峰期,进行操作。
服务器环境:
[root@node10 ~]# uname -a
Linux node10 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 2216:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[root@node10 ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[root@node10 ~]# rpm -qa | grep mongo
mongodb-org-tools-4.0.24-1.el7.x86_64
mongodb-org-mongos-4.0.24-1.el7.x86_64
mongodb-org-server-4.0.24-1.el7.x86_64
mongodb-org-4.0.24-1.el7.x86_64
mongodb-org-shell-4.0.24-1.el7.x86_64
一、原单节点MongoDB配置信息
IP: 192.168.166.10
Port: 27017
1.1 原配置文件
# mongod.conf
# for documentation of alloptions, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to write logging data.
systemLog:
destination: file
logAppend: true
path:/var/log/mongodb/mongod.log
# Where and how to store data.
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger:
# how the process runs
processManagement:
fork: true # forkand run in background
pidFilePath:/var/run/mongodb/mongod.pid # location of pidfile
timeZoneInfo:/usr/share/zoneinfo
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0 #Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, usethe net.bindIpAll setting.
#security:
#operationProfiling:
#replication:
#sharding:
##Enterprise-Only Options
#auditLog:
#snmp:
1.2 在原来配置文件增加副本集配置
replication:
oplogSizeMB: 4096
replSetName: rs1
注意:这里需要先把 认证 配置注释,副本集配置完成后再开启。
需要注意的是,创建账号这一步需要在开启认证之前操作。
上面这个是原数据节点,现在这个节点存在旧的数据,后面的配置需要以这个节点为主节点,在线配置以这个为MASTER主节点的副本集,如果配置完副本集,这个主节点的数据会自动同步到其它的SECONDARY节点
这个节点有配置用户的帐号和密码,如果没有配置,可以按下面的步骤来配置用户名和密码
注意:如果原先单节点mongo已经有了超级管理员账号,这可以忽略这个步鄹。
只需在主节点添加用户,副本集会自动同步主节点上的数据。
启用访问控制登录之前,首先需要在admin数据库中创建角色为userAdmin或userAdminAnyDatabase作为用户管理的用户,之后才能通过这个用户创建其它角色的用户,这个用户作为其它所有用户的管理者。
// 创建管理用户用户名为admin,密码admin123.
#mongo
> use admin
switched to db admin
>db.createUser({user:"admin",pwd:"admin123.",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})创建超级管理员root用户权限:
需要重启登录客户端,再操作:
>use admin
>db.createUser({user:'root',pwd:'root123.',roles:[{role:'root',db:'admin'}]})
创建单库中的管理员,这个管理员用户可以在这个库中进行任何操作
rs0:PRIMARY> use php
switched to db php
rs0:PRIMARY>db.createUser({user:"php",pwd:"123456",roles:[{role:"dbOwner",db:'php'}]})
查看已创建的账号
rs1:PRIMARY> use admin
switched to db admin
rs1:PRIMARY>db.getUsers();
[
{
"_id" : "admin.admin",
"userId" :UUID("d826a486-5450-4ced-a907-85ed81890d6d"),
"user" : "admin",
"db" : "admin",
"roles" : [
{
"role" : "readWrite",
"db" : "php"
},
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
},
{
"_id" :"admin.root",
"userId" :UUID("62f8200b-0574-4483-b3e7-04fd943bce17"),
"user" : "root",
"db" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]
以上用户名和密码配置完成后,要在各个节点开启验证:
在/etc/mongod.conf文件中添加以下命令:
security:
authorization: enabled
二、新增节点信息
角色
|
IP
|
Port
| |
PRIMARY
|
192.168.166.10
|
27017
|
原单节点MongoDB(有数据)
|
SECONDARY
|
192.168.166.11
|
27017
|
新增节点1(没有数据)
|
SECONDARY
|
192.168.166.12
|
27017
|
新增节点2(没有数据)
|
配置集群验证文件:三个节点都要配置
增加安全认证机制KeyFile:
集群之间的安全认证
所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上,且必须有读的权限,否则将来会报错。
一定要保证密钥文件一致,文件位置随便。但是为了方便查找,建议每台机器都放到一个固定的位置,都放到和配置文件一起的目录中。
集群之间的复制增加keyFile认证:
如何产生这个key ?按如下方式产生即可
#mkdir -p /var/lib/mongo/key
#cd /var/lib/mongo/
#chown mongod.mongod key -R
# openssl rand -base64 522>/var/lib/mongo/key/repl_set.key
# chmod 400 /var/lib/mongo/key/repl_set.key
#chown mongod.mongod ./repl_set.key
将这个keyfile复制到所有的部署节点上的/var/lib/mongo/key/repl_set.key下面,并设置400权限。
将该key放到集群中机器的每一台上,记住必须保持一致,权限设置成400;
2.1 新增节点配置文件
这两个SECONDARY节点配置文件,只需复制PRIMARY节点配置文件,并修改相应的 "bindIp"即可。
· SECONDARY 节点1配置文件
# mongod.conf
# for documentationof all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to writelogging data.
systemLog:
destination:file
logAppend:true
path:/var/log/mongodb/mongod.log
# Where and how tostore data.
storage:
dbPath:/var/lib/mongo
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger:
# how the processruns
processManagement:
fork:true # fork and run in background
pidFilePath:/var/run/mongodb/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
# networkinterfaces
net:
port: 27017
bindIp:0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or,alternatively, use the net.bindIpAll setting.
security:
clusterAuthMode: keyFile
keyFile:/var/lib/mongo/key/repl_set.key
authorization: enabled
#operationProfiling:
replication:
oplogSizeMB:4096
replSetName:rs1
#sharding:
## Enterprise-OnlyOptions
#auditLog:
#snmp:
· SECONDARY 节点2配置文件
# mongod.conf
# for documentationof all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# where to writelogging data.
systemLog:
destination:file
logAppend:true
path:/var/log/mongodb/mongod.log
# Where and how tostore data.
storage:
dbPath:/var/lib/mongo
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger:
# how the processruns
processManagement:
fork:true # fork and run in background
pidFilePath:/var/run/mongodb/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
# networkinterfaces
net:
port: 27017
bindIp:0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or,alternatively, use the net.bindIpAll setting.
security:
clusterAuthMode: keyFile
keyFile:/var/lib/mongo/key/repl_set.key
authorization: enabled
#operationProfiling:
replication:
oplogSizeMB:4096
replSetName:rs1
#sharding:
## Enterprise-OnlyOptions
#auditLog:
#snmp:
2.2 启动3个节点
PRIMARY节点需要重启,2个SECONDARY节点直接启动。
#启动命令
$ systemctl enable mongod&& systemctl start mongod
#停止命令
$ systemctl stop mongod
三、初始化副本集
使用mongo shell连接到其中一个节点(最好是MASTER主节点),执行初始化命令
3.1 初始化配置
> use admin
switched to db admin
>db.auth('root','root123.')
1
config = {
_id : "rs1",
members : [
{_id:0, host:"192.168.166.10:27017",priority:10}, #集群中priority值最大的被选举为主节点
{_id:1, host:"192.168.166.11:27017",priority:9}, #这个节点被选举为SECONDARY
{_id:2, host:"192.168.166.12:27017",priority:8}, #这个节点被选举为SECONDARY
]
}
3.2 对副本集进行初始化
>rs.initiate(config) //初始化副本集
{
"ok" : 1, //返回ok:1成功,返回ok:0失败
"operationTime" : Timestamp(1611042829,1),
"$clusterTime" : {
"clusterTime" : Timestamp(1611042829,1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
每台服务器上添加:
[root@node10 ~]# echo "rs.secondaryOk()">.mongorc.js
[root@node10 ~]# cat .mongorc.js
rs.secondaryOk()
3.3 查看副本集状态
· 查看集群状态信息
rs1:PRIMARY>rs.status()
查看节点的优先级:
rs1:PRIMARY>rs.config();
查看延时从库信息
rs1:PRIMARY>rs.printSlaveReplicationInfo()查看延时从库信息
rs1:PRIMARY>rs.printSlaveReplicationInfo()
查看集群与主节点
rs1:PRIMARY>rs.isMaster()
4.验证副本集认证
使用用户名、免密、认证库登录MongoDB副本集主节点
$ mongo -u mongouser -p123456 --host 192.168.166.10 --port 27017 -authenticationDatabase admin