MongoDB sharded cluster topology

Today, I’m going to share with you a bash script that gives you a quick overview of the topology of your MongoDB cluster.

It will give you:

  • The list and status of your mongos
  • The list and status of your config server
  • The list and status of every replica set members present in your cluster (including secondary members and arbiters), plus:
    • The date of the last role change between primary and secondary
    • The apply lag between primary and all secondary members
    • The oplog window
  • The balancer status

You can download the script on my GitHut repository “MyDBAWorld”.

Prerequisites

  • JQ (If you’re not familiar with JQ, check out my previous article about parsing JSON with JQ)
  • A MongoDB sharded cluster
  • A user on each local shard and on the cluster with, at least, the following privileges:
    • Read on “admin” database
    • Read on “config” database
    • “clusterMonitor” role

Because MongoDB does not provide any mechanisms to store encrypted password as Oracle do with wallets, I recommend you to not use a user with too much privileges (sadly, passwords will be stored in the script…).

The script has been tested on MongoDB 3.4 and 3.6 on Debian 8 (jessie) and Red Hat Enterprise Linux Server 7.3 (Maipo). Since there are no major changes in later versions of MongoDB with the commands / collections used by the script, this should work.

Configuration

You need to fill seven variables at the top of the script:

  • CLUSTERADMINUSR: the cluster user you want to use
  • CLUSTERADMINPWD: the password for the cluster user
  • CLUSTERAUTHDB: the authentication database for that user
  • LOCALADMINUSR: the local user you want to use (it must be present on all members of your replica set)
  • LOCALADMINPWD: the password for the local user (it must be the same on all members of your replica set)
  • LOCALAUTHDB: the authentication database for that user
  • FIRSTMONGOS: the hostname and port of one of your mongos (router). The format must be: “hostname:port”

For example:

CLUSTERADMINUSR="cluster_admin"
CLUSTERADMINPWD="cluster_password"
CLUSTERAUTHDB="admin"
LOCALADMINUSR="local_admin"
LOCALADMINPWD="local_password"
LOCALAUTHDB="admin"
FIRSTMONGOS="mongodocker1:27017"

Once done, you can execute the script as usual.

Sample output

Here is a sample output of the script executed against my MongoDB cluster composed of 6 shards, 3 config server and 3 mongos. Each shard is composed of 1 primary, 1 secondary and 1 arbiter, except shard “rs01” on which I have 1 primary and 2 secondary members.

Copy/paste does not preserve the colors, but “UP” will be written in green, “DOWN” in red and “TIMEOUT” in yellow to allow to see quickly if something is wrong.

#### Config DB list ####
mongodocker1:27019 : SECONDARY : UP
mongodocker2:27019 : PRIMARY : UP
mongodocker3:27019 : SECONDARY : UP
Balancer enabled : true

#### Mongos list ####
mongodocker1:27017 : UP
mongodocker2:27017 : UP
mongodocker3:27017 : UP

#### Shards list ####
[Shard : rs05]
mongodocker2:27021 : ARBITER : UP
mongodocker5:27018 : SECONDARY : UP
mongodocker6:27020 : PRIMARY : UP

--Last switch: 06/12/2018 15:37:18
--Apply lag:
mongodocker5:27018 is 0 second(s) behind primary mongodocker6:27020
--Oplog window: 108 days, 23 Hours, 20 Minutes, 27 Seconds

[Shard : rs03]
mongodocker6:27021 : ARBITER : UP
mongodocker3:27018 : PRIMARY : UP
mongodocker4:27020 : SECONDARY : UP

--Last switch: 06/12/2018 15:10:31
--Apply lag:
mongodocker4:27020 is 0 second(s) behind primary mongodocker3:27018
--Oplog window: 108 days, 23 Hours, 23 Minutes, 57 Seconds

[Shard : rs06]
mongodocker4:27021 : ARBITER : UP
mongodocker5:27020 : SECONDARY : UP
mongodocker6:27018 : PRIMARY : UP

--Last switch: 07/12/2018 04:26:05
--Apply lag:
mongodocker5:27020 is 0 second(s) behind primary mongodocker6:27018
--Oplog window: 108 days, 23 Hours, 18 Minutes, 36 Seconds

[Shard : rs04]
mongodocker5:27021 : ARBITER : UP
mongodocker1:27018 : SECONDARY : UP
mongodocker2:27020 : PRIMARY : UP

--Last switch: 06/12/2018 15:37:04
--Apply lag:
mongodocker1:27018 is 0 second(s) behind primary mongodocker2:27020
--Oplog window: 108 days, 23 Hours, 22 Minutes, 9 Seconds

[Shard : rs02]
mongodocker1:27021 : ARBITER : UP
mongodocker2:27018 : PRIMARY : UP
mongodocker3:27020 : SECONDARY : UP

--Last switch: 06/12/2018 15:37:18
--Apply lag:
mongodocker3:27020 is 0 second(s) behind primary mongodocker2:27018
--Oplog window: 108 days, 23 Hours, 26 Minutes, 16 Seconds

[Shard : rs01]
mongodocker1:27020 : PRIMARY : UP
mongodocker3:27021 : SECONDARY : UP
mongodocker4:27018 : SECONDARY : UP

--Last switch: 06/12/2018 15:37:19
--Apply lag:
mongodocker4:27018 is 0 second(s) behind primary mongodocker1:27020
mongodocker3:27021 is 0 second(s) behind primary mongodocker1:27020
--Oplog window: 108 days, 23 Hours, 29 Minutes, 2 Seconds

The date format is “DD/MM/YYYY HH:MI:SS”. If you want US date format, you can replace the line

LASTSWITCH=$(RunOnMongo "${PRIMARY}" "var d=db.runCommand('isMaster').electionId.getTimestamp();var yyyy = d.getFullYear();var mm = (d.getMonth() + 101).toString().slice(-2);var dd = (d.getDate() + 100).toString().slice(-2);var hh = ('0'+d.getHours()).slice(-2);var mi = ('0'+d.getMinutes()).slice(-2);var ss = ('0'+d.getSeconds()).slice(-2);print(dd + '/' + mm+'/'+yyyy+' '+hh+':'+mi+':'+ss);" "2")

with

LASTSWITCH=$(RunOnMongo "${PRIMARY}" "var d=db.runCommand('isMaster').electionId.getTimestamp();var yyyy = d.getFullYear();var mm = (d.getMonth() + 101).toString().slice(-2);var dd = (d.getDate() + 100).toString().slice(-2);var hh = ('0'+d.getHours()).slice(-2);var mi = ('0'+d.getMinutes()).slice(-2);var ss = ('0'+d.getSeconds()).slice(-2);print(mm + '/' + dd+'/'+yyyy+' '+hh+':'+mi+':'+ss);" "2")

I hope you find this script useful!

Leave a Reply

Your email address will not be published. Required fields are marked *