Important prerequisites:
- Confirm connectivity between machines you want to set as replica set
- Confirm the same version of Mongodb is installed on each machine. I tried one with mongo 2.6 and another with mongo 3.0 and totally failed. Then I installed mongo 3.0 on every machine.
- Don’t set authentication for all the machines before you manage to set all replica sets. I spent a lot of time boggling by authentication issues.
- Suppose we have machine A which has a complete copy of data. All other machines, say B, C, D…. for example, need to sync data from A. Make sure all other machines besides A have a empty mongodb database before starting.
Now let’s start using a example where machine A has a complete copy of data and machine B is empty and needs to sync from A.
By default, mongod will read `/etc/mongod.conf` every time it starts. There are two formats of the config file: one is of “setting = value” format (http://docs.mongodb.org/v2.4/reference/configuration-options/) and the other is YAML (http://docs.mongodb.org/manual/reference/configuration-options/). The former format was used before Mongo 2.6 but is compatible for versions afterwards.
I use the same config file (of YAML format) on A and B:
storage: dbPath: "/media/mongodb/mongodb" directoryPerDB: false journal: enabled: true systemLog: destination: file path: "/var/log/mongodb/mongodb.log" logAppend: true timeStampFormat: iso8601-utc replication: oplogSizeMB: 10240 replSetName: "rs0" net: port: <your port>
(The correctness of the format of config file is very important. Sometimes, typos in config file can cause failure of start of a mongodb instance while no exception log can be traced.)
To make the config file taking effect, you need to restart mongodb on both machines:
sudo service mongod restart
Now go to A’s mongo shell, initiate its replica state:
rsconfig = {_id:"rs0",members:[{_id:0, host:"machine_B_host:port",priority:1},{_id:1, host:"machine_A_host:port",priority:2}]} rs.initiate(rsconfig)
Remember to replace machine A and B’s address:port. If you want A to be PRIMARY as much as possible, set its priority higher than B. After this command, it should return OK now. You can also use `rs.reconfig(rsconfig)` later if you want to modify your configuration.
When the first time you start mongod on B, you will find you can’t query anything. For example:
show dbs 2015-07-09T22:52:00.208-0400 E QUERY Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }
That’s fine since B is a secondary server. In order to allow B for querying, you need to use `rs.slaveOk()` on B first.
Till now, we have set up two machines connecting as a replica set. But they can be easily hacked. For security considerations, we need to use a keyfile as an authentication media on both machines.
We first stop mongod instance:
sudo service mongod stop
Generate a keyfile following: http://docs.mongodb.org/manual/tutorial/generate-key-file/. Then push this file to both machines. I recommend you to put this file in the data directory, with `mongodb:mongodb` as owner and group, and 600 permissions.
Now add security specification in ‘/etc/mongod.conf:
storage: dbPath: "/media/mongodb/mongodb" directoryPerDB: false journal: enabled: true systemLog: destination: file path: "/var/log/mongodb/mongodb.log" logAppend: true timeStampFormat: iso8601-utc replication: oplogSizeMB: 10240 replSetName: "rs0" net: port: <your port> security: keyFile: "/media/mongodb/mongodb/mongodb-keyfile"
As here suggested, specifying keyFile path automatically enables authentication. So before you start mongod instance with keyFile, you should add user and password to your mongo databases. For example:
use products db.createUser({ user: "accountUser", pwd: "password", roles: [ "readWrite"] })
Now start mongodb again:
sudo service mongod start
Reference