Video Transcript (English)
In this video, we’ll deploy a three-member replica set from our development environment. Then we’ll test the replica set by initiating an election and checking the replica set’s status.
As a reminder, when using MongoDB Atlas, replica sets will be created, secured, and managed for you. In this video, we’ll focus on “self-managed” infrastructure, so we’ll provide all the necessary steps to do this yourself.
To start, we've provisioned three separate Ubuntu servers.
We've also opened the firewall between the three servers so that they can communicate with each other.
The latest version of MongoDB has been installed on each of the three servers.
Note, you can also use Windows, Mac, or a different Linux distribution of your choice.
Each of the three servers has a DNS record that's associated with their respective non-local IPv4 address.
Before we deploy our replica set, we'll need to first secure our three servers. We'll do so by creating a shared password file, known as a key file, that each one of the servers willuse to authenticate with one another.
In a production system, we would prefer to use something like an x509 certificate instead of just a key file. But the key file will work for today's uses.
We'll first create a shared password key file on the mongod0 server under the /tmp folder.
To do so, we'll take advantage of the OpenSSL application.
As we can see in the command, I'm going to use OpenSSL to randomly generate a base64 key file, which I'll then store in the /tmp directory.
Once we've run the previous command to create our key file, we'll want to go ahead and copy that from our mongod0 server onto our other two servers.
Because we're on Linux, we can take advantage of the scp, or secure copy command, to do so.
First, we'll copy the key file from our mongod0 server over to our mongod1 server.
As we can see in our scp command, we're going to copy the key file from our local /tmp directory over to the mongod1 /tmp directory.
When I run this command, we can see the progress bar reaching 100% completion on the far right-hand side.
This lets us know that we have successfully copied this file over to the mongod1 server.
Next, we'll go ahead and do the same thing, but with the mongod2 server.
Again, running this command, we can see that our progress has reached 100% and that we've successfully copied the key file over to the mongod2 server as well.
Now that we've created the key file on each of our hosts, we'll need to create a common directory structure around that key file that's accessible to the mongod service.
We'll need to carry out the following steps on each one of the three servers.
We'll start with mongod0 and then move on to mongod1 and mongod2 in succession.
First, we'll create a new directory in the /etc directory named mongodb/pki. Because the /etc directory is under the root, you might need to use the sudo command in front of your make directory.
You won't get any feedback from this command, but you have created that new folder.
Next, we need to run a chmod to modify the permissions of that file so that our mongod service can appropriately load the information in it.
We need to run a chmod on the key file in order to set the permissions so that our service can appropriately load and change that file.
In this case, we'll use the chmod for 0400 on the key file in the /tmp directory.
After modifying the permissions of the key file, we need to move it into the /mongodb/pki folder that we created previously.
To do so, we'll take advantage of the move command.
Here, we're moving the key file from its location in the /tmp directory over to /etc/mongodb/pki.
Finally, we need to use chown, or the change owner command, to make the MongoDB user the owner of the key file that we just moved.
In this case, we can see that we're changing the owner of the /etc/mongodb/pki file to mongodb.
With that, we're completely done with mongod0.
We next need to replicate each one of these steps on our mongod1 and mongod2 servers as well.
Now that we finished moving that key file, let's go ahead and update the configuration file for the mongod process for each one of our servers.
We'll need to update the settings for replication, security, and a few network settings as well.
We're going to start on the mongod0 server and then move our way to mongod1 and mongod2.
The first thing we'll need to do is to access the file using vim.
In our case, we'll use vim.
But you can definitely use nano or emacs or whatever other terminal editor you'd like to use. Here, I'm going to do a sudo vim for the config file under the /etc folder.
Running this command, this will open vim on that config file.
As you can see, we've got quite a few different configuration settings that we can change, from network settings to security and a few others.
One of the most important things with respect to this file is to make sure that you don't have multiple copies of the same section of the config.
So for example, you only want to see one net section.
You don't want to see another one later on.
What we're going to do next is to define the name of our replica set in our replication settings.
This name is going to be used across all of our mongod instances in our replica set.
And again, we want to make sure that there's only one instance of replication in this config file.
I'll go ahead and scroll down to where that is in this file and change it to the appropriate settings.
You'll notice that replication is currently commented out in my config file.
I'll go ahead and uncomment that and fill out the rest of this configuration.
In this case, under replication, I'm setting the replica set name or replSetName here to mongodb-repl-example.
It's critical to make sure that you set the same name on each host in your replica set.
Now that I've changed the replication setting, let's move on to the security setting.
Again, I'm going to uncomment the security setting and change a few of the settings here.
In this case, you can see where I've set the key file to point to where we placed the key file earlier.
And I've also enabled the authorization to successfully run on the database.
Once you're done changing both of those settings, make sure to go ahead and save your file.
Finally, we'll need to change our network configuration.
In the net portion of the config, you can see that we've got a port that is currently set to 27017 and a bind IP set to 127.0.0.1, also known as the local host.
As a default, MongoDB only listens to the local host.
We'll want to make sure that we configure this to also include our name for our current replica set member.
So in the bind IP, we're going to also add the mongod0.replset.com So again, what we're doing here is changing the bind IP parameter to make sure that the DNS name corresponds to the server that we're currently on.
When we go to set the configuration settings for the net for mongod1 and mongod2, respectively, we'll also need to set the appropriate name for the bind IP for those hosts as well.
We've now finished making all the changes we need to the config for the mongod0.
Let's go ahead and save and exit vim here.
Now that we've updated the config for mongod0, again, we'll go ahead and do that for mongod1 and mongod2 as well.
On each one of these hosts, again, we'll need to update the config settings for the security, replication, and network settings.
I'm going to go ahead and move on to mongod1.
Again, for each one of the hosts, you do want to use the respective host name within the bind IP.
It's very important that you make sure to match the name of the host that you're currently on.
Now that I'm done with mongod1, I'll again do the same process for mongod2.
Now that I'm finally done with mongod2, again, double check your work as you are saving and closing out vim for each one of these.
Common mistakes with config files include capitalization errors, spacing errors.
Remember that this is a YAML file.
So indentation and the correct indentation does matter.
Now that you finished with all of your config files, we'll need to restart the mongod process in order for the configuration to take effect.
To do so, we'll restart the mongod process using the sudo systemctl command.
Again, we'll also do this on each one of our hosts.
Excellent.
We now have our configuration files and our security keys in place.
This means that our servers are secure.
Let's move on to connecting each of those servers.
Again, now that we've configured everything, we'll head back to the first server so that we can actually log in to the database.
And to make sure that the database is correctly running, I'll run a sudo system control status mongod.
This is a useful command.
We can see that the service is active and currently running.
To log into the database, I'll go ahead and use the mongosh or Mongo shell command.
This will start a prompt, in which I've now dropped into my Mongo shell.
Very similar to the rest of the terminal, I can use the combination of control and L, as in Lima, to clear the excess lines on the screen.
I'll go ahead and do that here.
I'll then switch to the admin database with a use admin.
In order to connect the elements of my replica set, I do need to make sure that I'm on the admin database.
I'm next going to issue an rs.initiate method.
rs.initiate takes advantage of the replica set object in the Mongo shell.
Here, we're using the initiate method.
This is going to initialize a new replica set.
Notice first, the ID in the replica set object.
We're going to need to make sure that we use exactly the same ID that we used in our configuration files previously.
This is why it's so important to make sure that you consistently spell the correct name in those configurations.
Further down, we'll find the members field.
The members field is an array of each one of the hosts in our replica set.
In the array of the members field, we'll find an array of sub-documents, each of which represents an individual member of our replica set.
We'll need to specify an ID for that replica set member as well as the host name at a minimum.
If you'd like to apply additional configuration on the initiation of your replica set, these are the documents that you'll use in order to accomplish that.
As an example, if I wanted to make a change, such as making mongod1 have a higher priority than the other replica set members or changing the default read or write concerns of the replica set, I can definitely do that here.
I'll go ahead and run this command.
With the feedback from the database, we do see that we get an ok: 1, meaning that we do get a successful creation of our replica set, although it does say that we have a direct connection to an other on the replica set.
If we hit Enter again, we will be able to see that we're now connected to a primary.
The reason it shows an other when you first start it up is that we do have to have an election after we begin spinning up the replica set.
So now that our replica set has been initiated, before moving on, we want to create our first database user.
In this example, we're going to use the db.createUser method.
In this case, you can see where the db.createUser command accepts a user document.
In this user document, we need to pass a username and a password.
Here, you can see we have the user, dba-admin, and the password, pba-pass.
Our new user also needs to have a role defined in order to give them authorization privileges on the database.
In this case, you can see where the user has been given the role of being a root user on the admin database.
Now that we've created our user, we can actually use that user as part of a connection string.
We'll go ahead and exit the Mongo shell and then log back in using our connection string.
First, I'll use the exit command here in the Mongo shell.
And just for the sake of clarity, I'll go ahead and clear lines again.
Then, using the Mongo shell command, I'll use a specific connection stream in order to connect to our database.
It should look somewhat familiar.
And the main thing that's changed is instead of connecting directly to one replica set member, we're actually connecting to the entire replica set.
So after the @ symbol, you'll see mongod0.replicaset.com, followed by mongod1 and mongod2, each separated by a comma.
This variant of the connection string allows us to connect to the entire replica set.
Running this will then allow me to connect directly to the replica set as well.
The Mongo shell driver will automatically figure out which one of our replica set members is the primary and connect to it appropriately.
Once we've connected, we can run rs.status to check on all of the members of the replica set at the same time.
rs.status returns a fairly large document.
But we specifically want to check out the members field.
This command, again, gives us quite a bit of information, including the number of voting members of the replica set, the operation time, and even election information if we need it.
The information in the members field allows us to see information on each one of the individual replica set members.
We can even see that currently, mongod0 is the primary of this replica set.
Although it is currently the primary, let's see if we can change that.
We can initiate an election using the rs.stepDown method on the primary.
Let's go ahead and run that, first clearing our lines here in our terminal.
Again, we do want to use an rs.stepDown.
After we press Enter, we'll need a few moments to allow the election process to complete.
The next time that we run an rs.status and scroll through our members field, we can see that it is now mongod1 that is the primary of the replica set.
Great job.
In this video, we demonstrated all of the steps in deploying a self-managed replica set.
First, we secured the three servers using a shared security key.
Then we initiated the replica set by using the rs.initiate command with the three-server host.
Finally, we started an election by using the rs.stepDown command.