一、配置文件 /etc/mongod.conf
[root@mongo01 ~]# egrep -v "^(#|$)" /etc/mongod.conf
systemLog:
destination: file
logAppend: true
path: /data/mongodb/log/rs1.log
storage:
dbPath: /data/mongodb/data
directoryPerDB: true
journal:
enabled: true
processManagement:
fork: true # fork and run in background
pidFilePath: /data/mongodb/conf/mongod.pid # location of pidfile
net:
port: 27027
replication:
oplogSizeMB: 50000
replSetName: rs1
[root@mongo01 ~]#
[root@mongo01 ~]# ls /data/mongodb/
arbiter conf data log startaribiter.sh
[root@mongo01 ~]# ls /data/mongodb/arbiter/
arbiter.conf conf data log
[root@mongo01 ~]# egrep -v "^(#|$)" /data/mongodb/arbiter/arbiter.conf
systemLog:
destination: file
logAppend: true
path: /data/mongodb/arbiter/log/rs1.log
storage:
dbPath: /data/mongodb/arbiter/data
directoryPerDB: true
journal:
enabled: true
processManagement:
fork: true # fork and run in background
pidFilePath: /data/mongodb/arbiter/conf/mongod.pid # location of pidfile
net:
port: 27029
replication:
oplogSizeMB: 50000
replSetName: rs1
[root@mongo01 ~]# cat /data/mongodb/startarbiter.sh
#!/bin/sh
. /etc/rc.d/init.d/functions
cd ${0%/*}/arbiter
daemon --user mongod "mongod --config arbiter.conf"
[root@mongo01 ~]#
注意:arbiter.conf文件的属主、属组为mongod
二、启动服务,配置副本集
service mongod start
/data/mongodb/startaribiter.sh
启动第二个节点,然后在primary上操作如下:
rs.initiate()
rs.add("mongodb2.example.net")
rs.add("mongodb3.example.net")
rs.addArb("mongodb1.example.net:27029")
如果希望降低primary的优先级:
cfg = rs.conf()
cfg.members[2].priority = 0.5
rs.reconfig(cfg)
rs.status()
实现复制后,在从节点上查看数据如下:
SECONDARY> rs.slaveOk()
SECONDARY> show collections
三、 使用keyFile实现复制验证
在主节点上创建群集用户及密码如下:
admin = db.getSiblingDB("admin")
admin.createUser(
{
user: “clusteradmin”,
pwd: “clusterpwd”,
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: “clusterAdmin”, db: "admin" },
{ role: “root”, db: "admin" }
]
}
)
测试用户:
db.getSiblingDB("admin").auth(“clusteradmin”, “clusterpwd” )
在各从节点上关闭服务:
use admin
db.shutdownServer()
包括arbiter节点也要关闭服务,最后再关闭primary节点的服务。
在各配置文件mongod.conf文件中添加auth相关的文件,配置如下所示:
security:
keyFile: /data/mongodb/conf/keyfile.key
[root@mongo01 ~]# cat /data/mongodb/conf/keyfile.key
abcdefgh
该文件的权限必须是600或400,并把该文件复制到各节点上(保持内容相同),该文件也可以使用以下命令生成:
openssl rand -base64 755 > path-to-keyfile
最后再新启动各节点的mongodb服务,并重新login ,测试。
参考:
https://docs.mongodb.com/manual/tutorial/deploy-replica-set/
https://docs.mongodb.com/manual/tutorial/enforce-keyfile-access-control-in-existing-replica-set/
四、补充 CentOS7上部署mongodb 3.6的 RS
(1) 在vm2主机上配置mongod如下所示:
[root@vm2 ~]# mkdir -p /data/mongodb/{conf,run,logs,data}
[root@vm2 ~]# chown -R mongod.mongod /data/mongodb
[root@vm2 ~]# vim /etc/mongod.conf
[root@vm2 ~]# grep -Pv "^(#|$)" /etc/mongod.conf
systemLog:
destination: file
logAppend: true
path: /data/mongodb/logs/mongod.log
storage:
dbPath: /data/mongodb/data/
directoryPerDB: true
journal:
enabled: true
processManagement:
fork: true # fork and run in background
pidFilePath: /data/mongodb/run/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27027
bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces.
security:
authorization: enabled
keyFile: /data/mongodb/conf/keyFile
replication:
replSetName: rs0
[root@vm2 ~]# 注:必须保证 mongod.conf文件与mongod.service文件中的各路径设置一致,否则会导致启动失败
[root@vm2 ~]# cd /usr/lib/systemd/system/
[root@vm2 system]# head -15 mongod.service
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target
Documentation=https://docs.mongodb.org/manual
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /etc/mongod.conf"
ExecStart=/usr/bin/mongod $OPTIONS
ExecStartPre=/usr/bin/mkdir -p /data/mongodb/run
ExecStartPre=/usr/bin/chown mongod:mongod /data/mongodb/run
ExecStartPre=/usr/bin/chmod 0755 /data/mongodb/run
PermissionsStartOnly=true
PIDFile=/data/mongodb/run/mongod.pid
[root@vm2 system]#
[root@vm2 ~]# openssl rand -base64 755 > /data/mongodb/conf/keyFile
[root@vm2 ~]# chown mongod.mongod /data/mongodb/conf/keyFile
[root@vm2 ~]# chmod 400 /data/mongodb/conf/keyFile
(2)在vm2主机上配置arbiter 如下所示:
[root@vm2 data]# mkdir arbiter/{conf,data,logs,run} -p
[root@vm2 data]# cp mongodb/conf/keyFile arbiter/conf/
[root@vm2 data]# chmod 400 /data/arbiter/conf/
[root@vm2 data]# cp /etc/mongod.conf arbiter/conf/
[root@vm2 data]# mv conf/mongod.conf conf/arbiter.conf
[root@vm2 data]# vim arbiter/conf/arbiter.conf
[root@vm2 data]# chown -R mongod.mongod arbiter
[root@vm2 data]# grep -Pv "^(#|$)" arbiter/conf/arbiter.conf
systemLog:
destination: file
logAppend: true
path: /data/arbiter/logs/arbiter.log
storage:
dbPath: /data/arbiter/data/
directoryPerDB: true
journal:
enabled: true
processManagement:
fork: true # fork and run in background
pidFilePath: /data/arbiter/run/arbiter.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
net:
port: 37027
bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces.
security:
authorization: enabled
keyFile: /data/arbiter/conf/keyFile
replication:
replSetName: rs0
[root@vm2 data]#
[root@vm2 data]# cd /usr/lib/systemd/system
[root@vm2 system]# cp mongod.service arbiter.service
[root@vm2 system]# vim arbiter.service
[root@vm2 system]# head -15 arbiter.service
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target
Documentation=https://docs.mongodb.org/manual
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /data/arbiter/conf/arbiter.conf"
ExecStart=/usr/bin/mongod $OPTIONS
ExecStartPre=/usr/bin/mkdir -p /data/arbiter/run
ExecStartPre=/usr/bin/chown mongod:mongod /data/arbiter/run
ExecStartPre=/usr/bin/chmod 0755 /data/arbiter/run
PermissionsStartOnly=true
PIDFile=/data/arbiter/run/arbiter.pid
[root@vm2 system]#
[root@vm2 system]# systemctl daemon-reload
[root@vm2 arbiter]# tree
.
├── conf
│ ├── arbiter.conf
│ └── keyFile
├── data
├── logs
└── run
4 directories, 2 files
[root@vm2 arbiter]#
[root@vm2 data]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@vm2 data]# systemctl restart mongod
[root@vm2 data]# systemctl restart arbiter
[root@vm2 data]# ps -ef | grep mongod
mongod 130256 1 8 12:46 ? 00:00:01 /usr/bin/mongod -f /etc/mongod.conf
mongod 130354 1 14 12:46 ? 00:00:01 /usr/bin/mongod -f /data/arbiter/conf/arbiter.conf
root 130387 125564 0 12:46 pts/0 00:00:00 grep --color=auto mongod
[root@vm2 data]#
(3)在另一台mongodb server上安装并配置mongodb,配置内容与vm2上完全相同。然后添加rs,操作如下:
[root@meteor ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
[root@meteor ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@meteor ~]# systemctl restart mongod
[root@meteor ~]# mongo localhost:27027/admin -uroot -p
MongoDB shell version v3.6.5
Enter password:
connecting to: mongodb://localhost:27027/admin
MongoDB server version: 3.6.5
> show dbs
2018-05-26T20:41:42.392+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:65:1
shellHelper.show@src/mongo/shell/utils.js:849:19
shellHelper@src/mongo/shell/utils.js:739:15
@(shellhelp2):1:1
> rs.slaveOk()
> rs.status()
{
"info" : "run rs.initiate(...) if not yet done for the set",
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94,
"codeName" : "NotYetInitialized"
}
> config={"_id":"rs0","members":[
... {"_id":0,"host":"192.168.20.221:27027","priority":100},
... {"_id":1,"host":"192.168.40.206:27027","priority":1},
... {"_id":2,"host":"192.168.40.206:37027","priority":0,"arbiterOnly":true}
... ] }
{
"_id" : "rs0",
"members" : [
{
"_id" : 0,
"host" : "192.168.20.221:27027",
"priority" : 100
},
{
"_id" : 1,
"host" : "192.168.40.206:27027",
"priority" : 1
},
{
"_id" : 2,
"host" : "192.168.40.206:37027",
"priority" : 0,
"arbiterOnly" : true
}
]
}
> rs.initiate(config)
{ "ok" : 1 }
rs0:SECONDARY>
rs0:SECONDARY>
rs0:PRIMARY>
rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2018-05-26T12:49:29.987Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.20.221:27027",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 503,
"optime" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-26T12:49:23Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1527338942, 1),
"electionDate" : ISODate("2018-05-26T12:49:02Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.40.206:27027",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 38,
"optime" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1527338963, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2018-05-26T12:49:23Z"),
"optimeDurableDate" : ISODate("2018-05-26T12:49:23Z"),
"lastHeartbeat" : ISODate("2018-05-26T12:49:28.268Z"),
"lastHeartbeatRecv" : ISODate("2018-05-26T12:49:28.274Z"),
"pingMs" : NumberLong(1),
"syncingTo" : "192.168.20.221:27027",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "192.168.40.206:37027",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 38,
"lastHeartbeat" : ISODate("2018-05-26T12:49:28.266Z"),
"lastHeartbeatRecv" : ISODate("2018-05-26T12:49:29.107Z"),
"pingMs" : NumberLong(1),
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1527338963, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1527338963, 1),
"signature" : {
"hash" : BinData(0,"xxW1WBNE99FOs8BNdAanWKOhFUk="),
"keyId" : NumberLong("6559870810092208129")
}
}
}
rs0:PRIMARY>
(4)在secondary节点上登录,并查看状态,验证数据一致性。
说明:
priority:表示一个成员被选举为Primary节点的优先级,默认值是1,取值范围是从0到100,将priority设置为0有特殊含义:Priority为0的成员永远不能成为Primary 节点。Replica Set中,Priority最高的成员,会优先被选举为Primary 节点,只要其满足条件。
hidden:将成员配置为隐藏成员,要求Priority 为0。Client不会向隐藏成员发送请求,因此隐藏成员不会收到Client的Request。
slaveDelay:单位是秒,将Secondary 成员配置为延迟备份节点,要求Priority 为0,表示该成员比Primary 成员滞后指定的时间,才能将Primary上进行的写操作同步到本地。为了数据读取的一致性,应将延迟备份节点的hidden设置为true,避免用户读取到明显滞后的数据。Delayed members maintain a copy of the data that reflects the state of the data at some time in the past.
votes:有效值是0或1,默认值是1,如果votes是1,表示该成员(voting member)有权限选举Primary 成员。在一个Replica Set中,最多有7个成员,其votes 属性的值是1。
arbiterOnly:表示该成员是仲裁者,arbiter的唯一作用是就是参与选举,其votes属性是1,arbiter不保存数据,也不会为client提供服务。
总结:本内容前半部分是使用rs.add("....")的方法添加副本集,而后半部分是使用 先定义config ,然后再 rs.initiate(config)的方法 添加副本集。各位朋友可根据需要各自选用不同的方法