In this guide, I’m going to show you how to configure MongoDB Replica Set on Ubuntu 20.04|18.04 server. MongoDB is an enterprise-class NoSQL database system with auto-scaling, high availability and high performance. In a NoSQL database, data is stored in a document structure using MongoDB BSON format. SQL statements cannot be used in MongoDB to insert or retrieve data.

What is MongoDB Replication / Replica set?

In MongoDB, a replica set is a group of mongod processes that maintain the same data set. Replica sets are the basis for all production deployments as they provide data redundancy and high availability.

mongodb replica set

This tutorial will describe the steps required to create a working three nodes replica set without configured access control to restrict access. This guide is based on below system IP Addresses:

Node1: 10.10.5.2
Node2: 10.10.5.3
Node3: 10.10.5.4

Step 1: Setup Requirements

Before you can configure a replica set, you must install MongoDB on each system that will be part of the replica set. Set correct hostnames for all the servers. If you have an active DNS server, add A records for all servers, or modify /etc/hosts file. Add these on all nodes.

$ sudo vim /etc/hosts
10.10.5.2 mongodb-01 
10.10.5.3 mongodb-02 
10.10.5.4 mongodb-03

FYI: My Lab Setup is based on below Vagrantfile running on KVM.

# -*- mode: ruby -*-
# vim: set ft=ruby :

ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt'

# Check required plugins
REQUIRED_PLUGINS_LIBVIRT = %w(vagrant-libvirt)
exit unless REQUIRED_PLUGINS_LIBVIRT.all? do |plugin|
  Vagrant.has_plugin?(plugin) || (
    puts "The #{plugin} plugin is required. Please install it with:"
    puts "$ vagrant plugin install #{plugin}"
    false
  )
end

Vagrant.configure("2") do |config|
  config.vm.define "mongodb-01" do |node|
    node.vm.hostname = "mongodb-01"
    node.vm.box = "generic/ubuntu1804"
    node.vm.box_check_update = false
    #node.vm.synced_folder '.', '/vagrant', :disabled => true
    node.vm.network "private_network", ip: "10.10.5.2"
    node.vm.provider :libvirt do |domain|
      domain.memory = 512
      domain.storage :file, :size => '10G'
    end
  end
  config.vm.define "mongodb-02" do |node|
    node.vm.hostname = "mongodb-02"
    node.vm.box = "generic/ubuntu1804"
    node.vm.box_check_update = false
    #node.vm.synced_folder '.', '/vagrant', :disabled => true
    node.vm.network "private_network", ip: "10.10.5.3"
    node.vm.provider :libvirt do |domain|
      domain.memory = 512
      domain.storage :file, :size => '10G'
    end
  end
  config.vm.define "mongodb-03" do |node|
    node.vm.hostname = "mongodb-03"
    node.vm.box = "generic/ubuntu1804"
    node.vm.box_check_update = false
    #node.vm.synced_folder '.', '/vagrant', :disabled => true
    node.vm.network "private_network", ip: "10.10.5.4"
    node.vm.provider :libvirt do |domain|
      domain.memory = 512
      domain.storage :file, :size => '10G'
    end
  end
end

I then ran vagrant up to start all VMs

Step 2: Install MongoDB on all Ubuntu 20.04|18.04 Nodes

If you have not already installed MongoDB, see our installation guide How to Install MongoDB Server on Ubuntu. I will include installation guide here for convenience.

Update OS repository list and packages index:

sudo apt-get update

Import MongoDB public GPG Key:

wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -

Output:

OK

Once the key has been imported, add the repository:

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list

Update package APT index:

$ sudo apt update
Hit:1 http://security.ubuntu.com/ubuntu focal-security InRelease
Get:2 http://mirrors.digitalocean.com/ubuntu focal InRelease [265 kB]
Ign:3 https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 InRelease
Get:4 https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 Release [5372 B]
Hit:5 http://repo.zabbix.com/zabbix/5.0/ubuntu focal InRelease
Hit:6 http://mirrors.digitalocean.com/ubuntu focal-updates InRelease
Get:7 https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 Release.gpg [801 B]
Hit:8 http://mirrors.digitalocean.com/ubuntu focal-backports InRelease
Get:9 https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4/multiverse amd64 Packages [10.7 kB]
Get:10 https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4/multiverse arm64 Packages [7669 B]
Fetched 289 kB in 1s (347 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done

Perform system upgrade

sudo apt-get upgrade -y

Using dedicated disk for MongoDB data (Optional)

For my setup, I have 10GB secondary storage dedicated for MongoDB data. I’ll partition it and mount to /data/mongodb.

$ sudo lsblk 
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   32G  0 disk 
|-sda1   8:1    0  487M  0 part /boot
|-sda2   8:2    0  1.9G  0 part [SWAP]
`-sda3   8:3    0 29.6G  0 part /
vda    252:0    0   10G  0 disk

Create a GPT partition table for the secondary disk, it can be more than one disk

parted -s -a optimal -- /dev/vda mklabel gpt
parted -s -a optimal -- /dev/vda mkpart primary 0% 100%
parted -s -- /dev/vda align-check optimal 1

Then create LVM volume, this will make it easy to extend the partition

$ sudo pvcreate  /dev/vda1
  Physical volume "/dev/vda1" successfully created.

$ sudo vgcreate vg11 /dev/vda1
  Volume group "vg11" successfully created

$ sudo lvcreate -n data -l 100%FREE vg11
Logical volume "data" created

Create a ext4filesystem on the Logical Volume created.

$ sudo mkfs.ext4 /dev/mapper/vg11-data
mke2fs 1.44.1 (24-Mar-2018)
Creating filesystem with 2620416 4k blocks and 655360 inodes
Filesystem UUID: b98e07e5-1b04-4282-a9db-fa5b73c74d2f
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

Create a mount point and mount the partition

$ sudo vim /etc/fstab
# Add mount settings
/dev/mapper/vg11-data /data ext4 defaults 0 0

$ sudo mkdir /data
$ sudo mount -a

Confirm that the partition mount was successful:

$ df -hT | grep /data
/dev/mapper/vg11-data ext4      9.8G   37M  9.3G   1% /data

Install MongoDB packages

sudo apt update
sudo apt install -y openssl libcurl3 mongodb-org

Create a folder for MongoDB data

sudo mkdir /data/mongodb
sudo chown -R mongodb:mongodb /data/mongodb
sudo chmod -R 775 /data/mongodb

Step 3: Configure MongoDB Replica set

Now that we have everything needed ready, let’s proceed to configure MongoDB replica set.

Change MongoDB Listen Address from localhost IP on all nodes

sudo vim /etc/mongod.conf

See my configurations as shared below:

# node 1
# network interfaces
net:
  port: 27017
  bindIp: 10.10.5.2  # Listen to local interface only, comment to listen on all interfaces.

# node 2
# network interfaces
net:
  port: 27017
  bindIp: 10.10.5.3  # Listen to local interface only, comment to listen on all interfaces.


# node 3
# network interfaces
net:
  port: 27017
  bindIp: 10.10.5.4  # Listen to local interface only, comment to listen on all interfaces.

Configure the storage path to the one created earlier on all nodes

# Where and how to store data.
storage:
  dbPath: /data/mongodb
  journal:
    enabled: true

Configuring MongoDB Replica Set

One of the MongoDB nodes run as the PRIMARY, and all other nodes will work as SECONDARY. Data is always to the PRIMARY node and the data sets are then replicated to all other SECONDARYnodes.

Edit the MongoDB configuration file mongod.conf and enable replica set on all nodes

replication:
  replSetName: "replica01"

Open port 27017/tcp on the firewall:

sudo ufw enable
sudo ufw allow ssh
sudo ufw allow 27017/tcp

Configure MongoDB to start during the operating system’s boot

sudo systemctl enable mongod.service
sudo systemctl restart mongod.service

Check the listen Address of MongoDB service:

$ sudo ss -tunelp | grep -i mongo
tcp   LISTEN  0       128                10.10.5.2:27017          0.0.0.0:*      users:(("mongod",pid=15288,fd=11)) uid:111 ino:46927 sk:4 <->

Initiate MongoDB Replica Set

Our MongoDB Node1 (mongodb-01) will be the PRIMARY and the other two will act as SECONDARY

Login to the mongodb-01 server and start the mongo shell.

$ mongo 10.10.5.2
MongoDB shell version v4.0.1
connecting to: mongodb://10.10.5.2:27017/test
MongoDB server version: 4.0.1
Welcome to the MongoDB shell.
For interactive help, type "help".
...
>

Initialize replica set on node1 by running below command:

> rs.initiate()
{
        "info2" : "no configuration specified. Using a default configuration for the set",                                                           
        "me" : "10.10.5.2:27017",
        "ok" : 1,
        "operationTime" : Timestamp(1534797235, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1534797235, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),                                                                          
                        "keyId" : NumberLong(0)
                }
        }
}

Make sure you get 1 for ok state

Add secondary nodes

replica01:PRIMARY> rs.add("mongodb-02")
{
        "ok" : 1,
        "operationTime" : Timestamp(1534797580, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1534797580, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

replica01:PRIMARY> rs.add("mongodb-03")
{
        "ok" : 1,
        "operationTime" : Timestamp(1534797614, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1534797614, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

Check replica set status using:

replica01:PRIMARY> rs.status()

Check the status of the master

replica01:PRIMARY> rs.isMaster()

Testing MongoDB Replication

Create a test database on mongodb-01

replica01:PRIMARY> use test_db
switched to db test_db

Add some data

> db.test.save(
{
    "desc": "My Test Database",
    "apps":  ["Test1", "Test2", "Test3", "Test4"],
})

replica01:PRIMARY> show dbs
admin    0.000GB
config   0.000GB
local    0.000GB
test_db  0.000GB
replica01:PRIMARY> use test_db
switched to db test_db
replica01:PRIMARY> show collections
test

Conclusion

You now have a working MongoDB replication. You can increase the cluster size from three nodes to five nodes, seven nodes or more. This number is calculated from: [Master Eligible Nodes) / 2 + 1], which means an odd number of nodes is required for high availability, the minimum number is three.

Reference:

Your support is our everlasting motivation,
that cup of coffee is what keeps us going!


As we continue to grow, we would wish to reach and impact more people who visit and take advantage of the guides we have on our blog. This is a big task for us and we are so far extremely grateful for the kind people who have shown amazing support for our work over the time we have been online.

Thank You for your support as we work to give you the best of guides and articles. Click below to buy us a coffee.

LEAVE A REPLY

Please enter your comment!
Please enter your name here