Following write up describe how one can set up Replica Set in MongoDB (3x version). It is tested on CenOS-6x version. The same setup should work in any *nix based system.
The IPs cited here are for example only.
A. Participating Servers
1. primary-ins ======== 172.16.20.3
2. secondary-ins ======== 172.16.20.4
3. arbiter ======== 172.16.20.5
# cat /etc/centos-release
CentOS release 6.8 (Final)
[On Openstack cloud platform]
B. Host resolution (on all three servers)
/etc/hosts
172.16.20.3 primary-ins
172.16.20.4 secondary-ins
172.16.20.5 arbiter
C. Installed packages (On all three)
mongodb-org-shell-3.4.2-1.el6.x86_64
mongodb-org-tools-3.4.2-1.el6.x86_64
mongodb-org-server-3.4.2-1.el6.x86_64
mongodb-org-mongos-3.4.2-1.el6.x86_64
mongodb-org-3.4.2-1.el6.x86_64
D. Firewall considerations
* MongoDB listen on all interfaces instead of Loopback on all
three hosts.
three hosts.
[tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 22913/mongod]
1. IPTABLES:
Allowed entire subnet in Iptables INPUT chain for port 27017 (in all three hosts)
# iptables -I INPUT -p tcp -s 172.16.20.0/24 --dport 27017 -j ACCEPT
# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
# service iptables restart
iptables: Setting chains to policy ACCEPT: filter [ OK ]
iptables: Flushing firewall rules: [ OK ]
iptables: Unloading modules: [ OK ]
iptables: Applying firewall rules: [ OK ]
# iptables -L | grep 27017
ACCEPT tcp -- 172.16.20.0/24 anywhere tcp dpt:27017
2. SeLinux
SeLinux changed from Enforcing to Permissive:
# getenforce
Enforcing
#setenforce permissive
E. Replication Setup (all three) /etc/mongod.conf
replication:
## Replica Set name, consistent across all the systems
replSetName: myRepSet
## Operation Log file size
oplogSizeMB: 64
F. Restart Mongo service (on all three, any order)
# service mongod restart
G. Initiate replica set
Connect to any Mongo Server and run rs.initiate() to initiate the new replica set (preferably connect to the one that would act as Primary):
# mongo
> rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "primary-ins:27017",
"ok" : 1
}
myRepSet:OTHER>
Note:
Once the initialization is done, the prompt would change to;
myRepSet:PRIMARY>
H. Add replica set members
Now, while on the Primary Server's prompt, add the other members (Secondary and the Arbiter) as follows;
i. Add seondary:
myRepSet:PRIMARY> rs.add("secondary-ins:27017")
{ "ok" : 1 }
ii. Add arbiter
myRepSet:PRIMARY> rs.addArb("arbiter:27017")
{ "ok" : 1 }
I. Connect to other two Mongo servers and check the prompt(s):
myRepSet:SECONDARY>
myRepSet:ARBITER>
J. Allow read from secondary members
Execute rs.slaveOk(). This is to allow you to read from secondary members (including the Arbiter);
myRepSet:SECONDARY> rs.slaveOk()
myRepSet:ARBITER> rs.slaveOk()
K. Test
Create a DB and insert a document to a collection on the primary
and check if it that has been replicated to the secondary;
i. Create DB and insert document on Primary Mongo server;
myRepSet:PRIMARY> use test_replica
switched to db test_replica
myRepSet:PRIMARY> db.movie.insert({"name":"Jungle Book"})
WriteResult({ "nInserted" : 1 })
ii. On the secondary Mongo server;
myRepSet:SECONDARY> show dbs
admin 0.000GB
local 0.000GB
test_replica 0.000GB
myRepSet:SECONDARY> use test_replica
switched to db test_replica
myRepSet:SECONDARY> show collections
movie
myRepSet:SECONDARY> db.movie.find({})
{ "_id" : ObjectId("58963c37bede8f63243f5e52"), "name" : "Jungle Book" }
iii. On Arbiter (Remember Arbiter does not take part in Data
replication, its only job is to elect member during a Failover)
myRepSet:ARBITER> show dbs
admin 0.000GB
local 0.000GB
L. Check the configuration
myRepSet:PRIMARY> rs.conf()
{
"_id" : "myRepSet",
"version" : 3,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "primary-ins:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "secondary-ins:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "arbiter:27017",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("589632c875b52533db9c7540")
}
}