DB/MongoDB

From Ever changing code
< DB
Jump to navigation Jump to search

Mongo client

mongocli

mongocli is a client for connecting to MongoDB versions 5 and above.

kubectl -n mongo run --image=ubuntu:20.04 ubuntu-1 --rm -it -- bash
# Install generic tools
DEBIAN_FRONTEND=noninteractive apt install -yq dnsutils iproute2 iputils-ping iputils-tracepath net-tools netcat procps curl wget
# Install mongocli
apt-get install gnupg -yy
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add -
touch /etc/apt/sources.list.d/mongodb-org-5.0.list
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" > /etc/apt/sources.list.d/mongodb-org-5.0.list
apt-get update
apt-get install -y mongocli
mongocli <...>

# Install mongo shell - version 4.x
wget https://downloads.mongodb.com/compass/mongodb-mongosh_1.3.1_amd64.deb
dpkg -i mongodb-mongosh_1.3.1_amd64.deb
mongosh <...>

Connect

MongoDB version 4

MONGODB_USERNAME=root
MONGODB_PASSWORD=password1

mongosh mongodb://${MONGODB_USERNAME}:${MONGODB_PASSWORD}@mongodb.mynamespace:27017/mydatabase?replicaSet=rs0
Connecting to:		mongodb://<credentials>@mongodb.mynamespace:27017/mydatabase?replicaSet=rs0&appName=mongosh+1.3.1
Using MongoDB:		4.4.6
Using Mongosh:		1.3.1
rs0 [primary] mydatabase> 

# Connect via kubectl exec
kubectl -n mongo exec -it mongodb-0 -- mongo -u $MONGODB_USERNAME -p $MONGODB_PASSWORD --eval "rs.conf()"


MongoDB version 5

mongocli <...>

Operational MongoDb queries

rs.conf()                    # show current replica set config
rs.status()                  # show current replica set status
printjson(db.serverStatus()) # server status

rs0 [primary] hollywood> show databases;
mydatabase  90.7 MB

rs0 [primary] hollywood> show 
show databases    show dbs          show collections  show tables
show profile      show users        show roles        show log
show logs

# Simple queries
db.users.findOne()
db.users.find().limit(10)
db.users.find({"name.family": "Smith"}).count()

## Indexes on a collection
db.user.getIndexes()

Passwords management

All write operation like a password change must be run on a PRIMARY cluster member. Each database in Mongo cluster has its own set of users.

# Login using keyfile
mongo -u __system -p "$(tr -d '\011-\015\040' < path-to-keyfile)" --authenticationDatabase local
mongo -u __system -p "$(echo "$MONGODB_REPLICA_SET_KEY" | tr -d '\011-\015\040')" --authenticationDatabase local

# List databases as each database has it's own users
show databases;
use admin;
show users;    # list users
db.getUsers(); # list users
{
        "_id" : "admin.root",
        "userId" : UUID("aaaabbbb-bbbb-bbbb-bbbb-aaaabbbbaaa"),
        "user" : "root",
        "db" : "admin",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ],
        "mechanisms" : [ "SCRAM-SHA-1",  "SCRAM-SHA-256" ]
}

# Create a user
db.createUser({user:"admin",pwd:"password",roles:[{role:"root",db:"admin"}]});

# Update a password
db.changeUserPassword("admin", "password1");

# Verify
db.auth("admin", "password1");
db.runCommand({connectionStatus : 1});

Failover PRIMARY

We want to failover the PRIMARY mongodb-0.mongodb-headless.mongo:27017 node to mongodb-1.mongodb-headless.mongo:27017


Note: The failover must be run on the PRIMARY otherwise we get error "errmsg" : "New config is rejected :: caused by :: replSetReconfig should only be run on a writable PRIMARY. Current state SECONDARY;",.


# Print the RS (replication set) configuration
kubectl -n mongo exec -it mongodb-0 -- mongo -u root -p $PASSWORD --eval "rs.conf()"
rs0:PRIMARY> rs.conf()
{
	"_id" : "rs0",
	"version" : 201111,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "mongodb-0.mongodb-headless.mongo:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0.5,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "mongodb-arbiter-0.mongodb-arbiter-headless.mongo:27017",
			"arbiterOnly" : true,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "mongodb-1.mongodb-headless.mongo:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0.5,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 3,
			"host" : "mongodb-2.mongodb-headless.mongo:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0.5,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatIntervalMillis" : 2000,
		"heartbeatTimeoutSecs" : 10,
		"electionTimeoutMillis" : 10000,
		"catchUpTimeoutMillis" : -1,
		"catchUpTakeoverDelayMillis" : 30000,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		},
		"replicaSetId" : ObjectId("111111111122222222223333")
	}
}


Update RS configuration by changing votes or priories. The below commands update mongodb-1 priority from 0.5 to 1. The newly triggered election process does not impact the service.

# Execute into any of cluster nodes
kubectl -n mongo exec -it mongodb-0 -- mongo -u root -p $PASSWORD --eval "rs.conf()"
rs0:PRIMARY> cfg = rs.conf();
rs0:PRIMARY> cfg.members[2].priority = 1; # mongodb-1.mongodb-headless.mongo:27017
rs0:PRIMARY> cfg.members[2].votes    = 1;
rs0:PRIMARY> rs.reconfig(cfg);            # save the configuration
rs0:PRIMARY> rs.status();                 # verify, the reconfiguration take around 8-12 seconds

ReplicaSet Voting