https://github.com/xverges/mongo-replica-set
MONGO_INITDB_ROOT_USERNAME and additional accounts created with a script in
docker-entrypoint-initdb.d.vagrant plugin install vagrant-docker-composefirst, second and arbitrerdocker-entrypoint.sh to run mongo commands is not valid approach:
it only works on empty instancesmongodump first and secondmongorestore second’s dump into first (alternatively, could mongoexport and mongoimport)second. Delete its data folder (Would not do that if I could have file system snapshot backups)secondI was looking into some simple way to setup/activate a virtualenv associated to the project, and
went jumping from cool project to cool project: from autoenv
to direnv and finally betting on Pipenv: Python Development Workflow for
Humans. Thus, the project dependencies are tracked in Pipfile.
Get our python dependencies and the environment variables defined in .env.
$ pipnenv shell
(mongo-replica-set-qvtM3FSm)$
Start the first and second vagrant boxes and their docker-compose (vagrant destroy +
vagrant up). Requires installing docker inside the guests, getting the mongodb docker
image… takes its time (15 minute-ish on my home network).
(mongo-replica-set-qvtM3FSm)$ ./scripts/01-start-standalone.sh
Reset the boxes. Trial an error required getting to this step very often.
/docker-entrypoint-initdb.d are created. These scripts won’t be
executed once the data folder is not empty.xv_mongo_rw account privileges to access collections in the local database.(mongo-replica-set-qvtM3FSm)$ ./scripts/reset-standalone.sh all
Create dbs, collections and documents in the first and second instances
(mongo-replica-set-qvtM3FSm)$ ./scripts/02-feed-standalone.py
(mongo-replica-set-qvtM3FSm)$ ./scripts/read-standalone.py
02-feed-standalone.py read-standalone.sh all
Consolidate all the info on the first.
mongodump + mongorestore to have everything in the firstsecond to remove its contents(mongo-replica-set-qvtM3FSm)$ ./scripts/backup.sh
(mongo-replica-set-qvtM3FSm)$ ./scripts/restore.sh second 192.168.100.10
(mongo-replica-set-qvtM3FSm)$ ./scripts/reset-standalone.sh second
(mongo-replica-set-qvtM3FSm)$ ./scripts/read-standalone.py
backup.sh restore.sh reset-standalone.sh read-standalone.sh
Restart the instances, now with the --replSet param set and allowing
to have other hosts that localhost to connect to mongodb. I allowed
everything with param --bind_ip 0.0.0.0 .
Note that, when I specified the --replSet param with an empty data directory,
the scripts in /docker-entrypoint-initdb.d were not executed.
(mongo-replica-set-qvtM3FSm)$ ./scripts/03-stop-standalone.sh
(mongo-replica-set-qvtM3FSm)$ ./scripts/04-start-with-repl-param.sh
03-stop-standalone.sh 04-start-with-repl-param.sh
The instances are not operative now. If we try to read them…
(mongo-replica-set-qvtM3FSm)$ ./scripts/read-standalone.py
(mongo-replica-set-qvtM3FSm) bash-3.2$ ./scripts/read-standalone.py
----FIRST----
node is not in primary or recovering state
----SECOND----
{'local': {'not_replicated': ()}}
…and the reported error is on track:
(mongo-replica-set-qvtM3FSm) bash-3.2$ ./scripts/get-replicaset-status.sh
Working with first... Mapped to the host port 27110
MongoDB shell version v3.4.4
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.4
{
"info" : "run rs.initiate(...) if not yet done for the set",
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94,
"codeName" : "NotYetInitialized"
}
Working with second... Mapped to the host port 27111
MongoDB shell version v3.4.4
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.4
{
"info" : "run rs.initiate(...) if not yet done for the set",
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94,
"codeName" : "NotYetInitialized"
}
And, all the previous commands in a single line to make trial-and-error faster:
(mongo-replica-set-qvtM3FSm)$ ./scripts/reset-standalone.sh all && ./scripts/02-feed-standalone.py && ./scripts/backup.sh && ./scripts/restore.sh second 192.168.100.10 && ./scripts/reset-standalone.sh second && ./scripts/03-stop-standalone.sh && ./scripts/04-start-with-repl-param.sh
Initialize the replica set. This is done in the replicaset-init.js
and replicaset-add-additional.js
first, because, when I used
rs.initiate() without params, the configuration for the primary member of the replica set
pointed to an unreachable address, and second was unable to reach first.second as a second member in the config param of rs.initiate() also resulted in
failure.second right after rs.initiate() could also fail: you have to wait until
its stateStr is set to PRIMARY.(mongo-replica-set-qvtM3FSm)$ ./scripts/05-init-replicaset.sh
(mongo-replica-set-qvtM3FSm)$ ./scripts/read-standalone.py
The arbitrer has not been setup, but we can access both instances. Using the previous connection params, that do not specify anything related to the replicaset:
pymongo.errors.NotMasterError: not master)When trying to use the replicaset param when creating MongoClient, I learned that my OSX host
can not reach my VirtualBox guests, or my guests reach the
hostonly address where I
expected my host to be. Lots of googling but nothing helped.
For the record:
$ VBoxManage list hostonlyifs
...
Name: vboxnet2
GUID: 786f6276-656e-4274-8000-0a0027000002
DHCP: Disabled
IPAddress: 192.168.100.1
NetworkMask: 255.255.255.0
IPV6Address:
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: 0a:00:27:00:00:02
MediumType: Ethernet
Wireless: No
Status: Up
VBoxNetworkName: HostInterfaceNetworking-vboxnet2
$ ifconfig
...
vboxnet2: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
ether 0a:00:27:00:00:02
inet 192.168.100.1 netmask 0xffffff00 broadcast 192.168.100.255
...
$ VBoxManage showvminfo mongo-replica-set_arbitrer_1537298209734_479
...
Guest OS: Red Hat (64-bit)
...
NIC 1: MAC: 08002737F846, Attachment: NAT, Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none
NIC 1 Settings: MTU: 0, Socket (send: 64, receive: 64), TCP Window (send:64, receive: 64)
NIC 1 Rule(0): name = ssh, protocol = tcp, host ip = 127.0.0.1, host port = 2201, guest ip = , guest port = 22
NIC 1 Rule(1): name = tcp27112, protocol = tcp, host ip = , host port = 27112, guest ip = , guest port = 27017
NIC 2: MAC: 080027EA7320, Attachment: Host-only Interface 'vboxnet2', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: allow-all, Bandwidth group: none
...
Guest:
Configured memory balloon size: 0 MB
OS type: Linux26_64
Additions run level: 2
Additions version: 5.1.26 r117224
Guest Facilities:
Facility "VirtualBox Base Driver": active/running (last update: 2018/09/18 19:17:03 UTC)
Facility "VirtualBox System Service": active/running (last update: 2018/09/18 19:17:06 UTC)
Facility "Seamless Mode": not active (last update: 2018/09/18 19:17:03 UTC)
Facility "Graphics Mode": not active (last update: 2018/09/18 19:17:03 UTC)
The vagrant boxes see each other, and there we can connect to mongo specifying that we are connecting to a replica set:
MongoClient(url_to_local, replicaset=replicaset_name, read_preference=ReadPreference.NEAREST)
We can read and write using this client, from both the box that has the primary and the box that has the secondary.
So far the tests have been run using mongo root’s credentials and regular databases. We now need to verify that we can work with less privileged credentials and with the local databases. We will
The tests show that
local database can be updated when using the secondary and no replicaset specificationlocal database of the secondary WON’T be updated if we specify a replicaset.local the databases that we don’t want replicatedpymongo.MongoClient if we are targeting
the local database or a database that we want replicatedmongodump to create a backup of the two instancesmongorestore to consolidate all the info in first--keyFile, --bind_ip and --replSet params for the mongodb containerrs.initiate() on the first serverPRIMARY and then add the rest of servers: rs.add() and rs.addArb()pymongo.MongoClient to be used for
databases that we want replicated