본문 바로가기

software engineering

Installation of MongoDB Cluster on Ubuntu on RaspberryPi

Installation of MongoDB

Install MongoDB on each of your Raspberry PI following the offical MongoDB installation guide.

docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

 

Install MongoDB Community Edition on Ubuntu — MongoDB Manual

 

docs.mongodb.com

Setting up the cluster

Keyfile Authentication

To enforce access control on internal members of replica set, MongoDB supports internal membership authentication via X.509 or keyfiles. Here I am going to us keyfiles.

First, let's create a keyfile and copy it to the nodes.

$ openssl rand -base64 756 > mongodb-keyfile

$ scp ./mongodb-keyfile ubuntu@mongo1:/tmp/mongodb-keyfile
$ scp ./mongodb-keyfile ubuntu@mongo2:/tmp/mongodb-keyfile
$ scp ./mongodb-keyfile ubuntu@mongo3:/tmp/mongodb-keyfile

And then on each host, move the key file to a safe place and change the permission so that MongoDB can access to it.

$ sudo mv /tmp/mongodb-keyfile /var/lib/mongodb-key/mongodb-keyfile
$ sudo chmod 400 /var/lib/mongodb-key/mongodb-keyfile
$ sudo chown -R mongodb:mongodb /var/lib/mongodb-key

Reference: docs.mongodb.com/manual/tutorial/deploy-replica-set-with-keyfile-access-control/

 

Deploy Replica Set With Keyfile Authentication — MongoDB Manual

Tip When possible, use a logical DNS hostname instead of an ip address, particularly when configuring replica set members or sharded cluster members. The use of logical DNS hostnames avoids configuration changes due to ip address changes. IP Binding Starti

docs.mongodb.com

Configuration

The default configuration file is /etc/mongod.conf on Linux (and thus on Ubuntu).

In the file I edited net, security and replication options

net:
  port: 27017
  bindIp: 127.0.0.1,<node ip here>
  
security:
  authorization: enabled
  keyFile: /var/lib/mongodb-key/mongodb-keyfile
  
replication:
  replSetName: my-replset

And restart mongod and verify it starts successfully

$ sudo systemctl enable mongod
$ sudo systemctl restart mongod
$ sudo systemctl status mongod
mongod.service - MongoDB Database Server
     Loaded: loaded (/lib/systemd/system/mongod.se>
     Active: active (running) since Thu 2020-12-31>
       Docs: https://docs.mongodb.org/manual
   Main PID: 1929107 (mongod)
     Memory: 155.3M
     CGroup: /system.slice/mongod.service
             └─1929107 /usr/bin/mongod --config /e

Reference: docs.mongodb.com/manual/reference/configuration-options/

 

Configuration File Options — MongoDB Manual

Reference > Configuration File Options Configuration File Options The following page describes the configuration options available in MongoDB 4.4. For configuration file options for other versions of MongoDB, see the appropriate version of the MongoDB Manu

docs.mongodb.com

Initialize replicaset

From one of the nodes type "mongo" to go into mongo shell.

$ mongo
MongoDB shell version v4.4.2
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("846d8931-4c6a-4ede-baf7-eadc52a400e5") }
MongoDB server version: 4.4.2
>

Use admin database and initialize the replicaset

> use admin
switched to db admin
> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.0.15:27017",
	"ok" : 1
}
my-replset:SECONDARY>

It seems work. But wait! it showed me it's "SECONDARY" of the replicaset. That's weired. Fortunately when I exit and re-enter to mongo shell it told me that the node is "PRIMARY".

my-replset:SECONDARY> exit
bye

$ mongo
MongoDB shell version v4.4.2
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("16aea886-f8d4-4c41-b9a8-83dd8079d201") }
MongoDB server version: 4.4.2
my-replset:PRIMARY>

Okay, now let's create an admin user.

my-replset:PRIMARY> db.createUser({user: "mongo-admin", pwd: <password here>, roles: [{role: "root", db: "admin"}]})
Successfully added user: {
	"user" : "mongo-admin",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}

Let's relogin with the new admin user.

my-replset:PRIMARY> exit
bye

$ mongo -u mongo-admon
MongoDB shell version v4.4.2
Enter password: <password here>
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("273389f0-a51e-4564-afb5-aeddc9c7e975") }
MongoDB server version: 4.4.2
my-replset:PRIMARY>

Switch to admin database and add nodes to the repliaset.

my-replset:PRIMARY> use admin
switched to db admin
my-replset:PRIMARY> rs.add("mongo2:27017")
{
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1609388600, 1),
		"signature" : {
			"hash" : BinData(0,"DmnRU6yE9MBgayeMEWHBMUNGBbU="),
			"keyId" : NumberLong("6912260923835023364")
		}
	},
	"operationTime" : Timestamp(1609388600, 1)
}

Troubleshooting.

In case you see error messagae that reads somethie like "the following nodes did not respond affirmatively: mongo2:27017 failed with Error connecting to mongo2:27017 (192.168.0.16:27017) :: caused by :: No route to host", this is probably because of firewall on your nodes. Unblock the port from your nodes and retry adding nodes to the cluster.

$ sudo firewall-cmd --permanent --add-port=27017/tcp
$ sudo firewall-cmd --reload

Connecting to the replica set

To connect to the replica set you can speicify the replica set name on host parameter.

$ mongo --host my-replset/mongo2 -u mongo-admin --authenticationDatabase admin
MongoDB shell version v4.4.1
Enter password:
connecting to: mongodb://mongo2:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb&replicaSet=my-replset
Implicit session: session { "id" : UUID("24790bb8-76f6-468b-89a1-3ffafc262ac6") }
MongoDB server version: 4.4.2

my-replset:PRIMARY> rs.isMaster()['ismaster']
true
my-replset:PRIMARY>

As you can see, connenting to the replicaset always routes to the master node.

Let's see if it is tolerable for dead master node by shutting down the service.

Check which node is the current master.

my-replset:PRIMARY> rs.isMaster()['me']
mongo1:27017

And stop the service from the node.

ubuntu@mongo1:~$ sudo systemctl stop mongod

And see if mongo is still available.

my-replset:PRIMARY> rs.isMaster()['ismaster']
true
my-replset:PRIMARY> rs.isMaster()['me']
mongo2:27017

As you can see, now the mongo2 node took the master responsibility.