This post is a reminder to myself for setting up replication for MongoDb for Disaster Recovery, as all the AI agents seemed to have this wrong and/or missed a number of steps. This should work for versions 5 and 6 of MongoDb, but for the purposes of this article it was only done on v4.
Note that this is for replication for DR - with the deliberate decision to not set up the replicate set for high availability. In this case, the replication secondary is intended for use only if the primary site fails - we don’t want it assuming lead status if the original primary fails (or is rebooted!).
Preparation
You will need:
- Two running instances of MongoDb
- Administrative access to both servers and MongoDb instances
- OpenSSL installed locally to generate a key file - I used the Shining Light Productions version
winget install --Id=ShiningLight.OpenSSL.Dev
Generate a Key file
Before we start, we need a keyfile placed on each of the MongoDb servers - the running service will need read access to the file.
openssl rand -base64 756 > mongodb-keyfile
Update Mongo Configuration
Add the following to your mongodb.config
file (this is a YAML file) on BOTH servers:
replication:
replSetName: rs0
security:
authorization: enabled
keyFile: C:\MongoDb\v4\mongodb-keyfile
Some important notes here:
- When you restart your MongoDb instances after making these changes, they will be inaccessible until you fire up the replica set as per the next step
- My keyfile is on Windows, for Linux you will need to apply permissions to the file and set a Linux path to the file.
- It is also important ti note that YAML is very iffy with spacing and tabs. Make sure all “empty” lines are really empty, and leading spaces are spaces and not tabs. Test this out before making your changes.
Initialize the Replica Set
Restart MongoDb on both servers - no-one will be able to connect until the following steps are complete, so you need to be quick if this is a production environment.
On the primary instance, log into it via the shell
mongo --username admin --password password --authenticationDatabase "admin"
From the shell, initialise the replica set, switching out PRIMARY-HOST
with your server’s host name:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "PRIMARY-HOST:27017" }
]
});
Your primary server will now be open to connections, and you should be able to check the replication status:
rs.status();
Now, we can initialise replication, switching SECONDARY-HOST
with your secondary server name:
rs.add("SECONDARY-HOST:27017");
Remove High Availability
With the current configuration, if your primary fails, your secondary will automatically kick in. For the purposes of this article, this is not what we want, so we need to remove this configuration.
Still connected to the mongo shell on the primary server, get the current config:
cfg = rs.conf();
Set the secondary’s priority to 0. You will need to work out where the secondary server is in the config members collection, although it will be at index 1 in this example of only two servers. You can work it out by looking at cfg.members[i].host
.
cfg.members[1].priority = 0;
Reapply the config:
rs.reconfig(cfg);
Once this is complete:
- All data will still be replicated from the primary to the secondary.
- The secondary will never stand for election as primary. That means if your primary reboots:
- The secondary stays as secondary.
- The replica set will be read-only until the primary is back.
Monitoring
The following commands can be used to monitor the status of replication:
Status
This command can be run on both the primary and the secondary, and will show the status of replication. The primary will have no syncSourceHost
value, and the secondary will reflect the host name of the primary. For MongoDb versions 5 and above, the stateStr
property will have a value of PRIMARY
.
rs.status();
Replication Info
This command can show replication info, including the last time an item was replicated:
rs.printReplicationInfo();
This command will show you the lag between primary and secondary:
rs.printSlaveReplicationInfo();
For MongoDb version 4 and below, this command can be used to determine which server is primary. The property ismaster
will reflect true
and secondary
will be false
for the primary server, and obviously reversed on the secondary.
db.isMaster();