Deploying a MongoDB replica set on AWS EC2 instance
Tags: mongodb, aws, ec2, replicaset
Published: 2020-01-08 20:25:29

---
title: Deploying a MongoDB replica set on AWS EC2 instance
published: true
description: Configuring a 3 member mongoDB replica set for fault-tolerance, high data availability against loss of a single data server.
tags: #mongodb, #aws, #ec2, #replica-set
---

According to Mongodb's website, "A replica set in MongoDB is a group of 
<a href="https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod">mongod</a> processes that maintain the same data set. Replica sets provide redundancy and high availability, and are the basis for all production deployments." Meaning if you are using MongoDB as your data source and you are ready to deploy in production, you need a replica set for some system reliability. 

It is advised that each member of your replica set have their own standalone servers. 

For this tutorial, I will be setting up a replica set with an arbiter.
For more on replication and replica set architecture, see <a href="https://docs.mongodb.com/manual/replication/"> Replica Set Architecture </a>.

<strong>STEP 1: Create 3 EC2 instance and Install MongoDB</strong>

Create 3 ec2 instance, they can be of any OS, just make sure you can install Mongodb on each of them.

I will be using Red Hat Enterprise Linux 8 for the 3 instance.

For MongoDB installation guide, checkout <a href="https://docs.mongodb.com/manual/installation/">MongoDB Installation</a>

Make sure the 3 instance created are in the same security group and the inbound rule allows them to talk with each other on port 27017.

<strong>STEP 2: Enable Access Control (Authentication and Authorization)</strong>

<ul>
<li>Create a Keyfile:
<p>With <a href="https://docs.mongodb.com/manual/core/security-internal-authentication/#internal-auth-keyfile">keyfile</a> authentication, each mongod instances in the replica set uses the contents of the keyfile as the shared password for authenticating other members in the deployment. Only mongod instances with the correct keyfile can join the replica set.</p>
Run the following command to generate a keyfile
<ol><li>
  openssl rand -base64 756 > <strong>/opt/mongo/mongod-keyfile</strong>
</i>
 </li>
<li>

  chmod 400 <strong>/opt/mongo/mongod-keyfile</strong>
</i>
 </li>
<li><i> sudo chown mongodb:mongodb <strong>/opt/mongo/mongod-keyfile</strong> </i> </li>
</ol>
</li>
<p>The above commands will generate a keyfile for you located in <strong>/opt/mongo/mongod-keyfile</strong>. It will give read permissions to the owner and allow mongodb to be able to read it.</p>
<li>Copy the Keyfile to other replica-set members:
<p>This means copying the keyfile generated to the other EC2-instances where your member replica-set members are located. You might have to run the second and third command above in the replica-set instances after copying them to enable read permission.</p>
<p> To transfer files from one EC2 instance to another, you can follow this tutorial, <a href="https://blog.e-zest.com/how-to-do-scp-from-one-ec2-instance-to-another-ec2-instance/">File Transfer between 2 EC2 Instance</a> </p>
</li>

<li>Update the configuration file:
<ol>
 <li>Open the file: <i>sudo nano /etc/mongod.conf</i></li>
 <li>Under <strong>bindIp</strong> in <strong>net</strong>, add the private address of the current machine along with the localhost because mongodb binds to the localhost by default</li>
<li>Under <strong>replication</strong> add <strong>replSetName</strong> with the name of your replica set</li>
<li>Under <strong>security</strong>, add <strong><i>keyFile: 'path to keyfile you generated'</i></strong></li>
<li>Save the file and restart mongodb: <i>sudo systemctl restart mongod</i></li>
<liRepeat for the servers you want to add as members of the replicaSet</li>
</ol>
</li> 
</ul>

<strong>STEP 3: Create and connect your replicaset members</strong>
<ul>
<li>Connect to the mongo shell(typing <i>mongo</i> should get you there) in any of the servers you want to make the primary</li>
<li>run <strong> rs.initiate()</strong> to create your Primary. This sets the current instance as the primary replica</li>
<li><p>Create the user admin: This admin user must have privileges to create other users, such as a user with the <strong>userAdminAnyDatabase</strong> role.</p>
<p>run <strong><p><i>db.createUser({user: “admin”, pwd: “admin”, 
roles: [{role: “userAdminAnyDatabase”, db: “admin"}]})</i></p></strong> to create an admin user for you. Use a strong username and password of your choice.</p>
</li>
<li>exit the shell and authenticate as admin user: <p><strong><i>
mongo -u 'your-username' -p --authenticationDatabase admin</i></strong><p><p>It will prompt for your password, enter correct one.
</p>
</li>
<li>Create a cluster admin: Use the <strong>clusterAdmin</strong> role. This grants access to replication operations such as configuring replica set.
<p>run <strong><p><i>db.createUser({user: “adminCluster”, pwd: “adminCluster”, 
roles: [{role: “clusterAdmin”, db: “admin"}]})</i></p></strong>. Use a unique username and a strong password for this.
</li>
<li>Exit the shell and authenticate as the cluster admin to add more replica members. <p><strong><i>mongo -u 'your-cluster-admin-username' -p --authenticationDatabase admin</i></strong></p>When it prompts for password, enter your cluster admin password.</li>
<li>Add more cluster members by running <p><strong><i>rs.add( { host: "ipaddress/hostname-of-the-instance-you-want-to-add-as-member:27017" } )</i></strong></p> </li>
<li>Add an arbiter to your replica set: <p><strong><i>rs.addArb(‘ipaddress/hostname-of-the-instance-you-want-to-make-as-arbiter:27017’)</i></strong></p>
</ul>

<strong>Sidenotes:</strong>
You can create additional db users for your clients(backend applications, etc) to connect to. To do that, authenticate as admin and create a db user with the appropriate role you want.

In adding a new member to the cluster,
copy the <strong>keyfile</strong> you generated to the new member’s server. uncomment security in the <strong><i>/etc/mongod.conf</i></strong> file and add <strong><i>keyFile: 'file location'</i></strong>
uncomment <strong>replication</strong> and add <strong><i>replSetName</i></strong> with the replica set’s name you want to add it to.
save file and start mongod instance.
Go to the primary of the replica set and add this new member to the replica set using rs.add( { host: "ipaddress/hostname-of-the-instance-you-want-to-add-as-member:27017" } )