Leos Literak
Leos Literak

Reputation: 9484

Cannot connect Mongo replica over SSH tunnel

I have created a SSH tunnel from my laptop to linux server where one Mongo node is running. I am able to connect the actual node:

mongo "mongodb://localhost:22222/bud"

but I cannot use the connection because the replica parameter is not set (this is regardless of the tunnel, it happens on server too):

rs_bud:SECONDARY> db.items.find({'info.author.id':'leos'},{'info':1}).sort({ 'info.date': -1 }).limit(3);
Error: error: {
        "topologyVersion" : {
                "processId" : ObjectId("61c7088a199c68867b798434"),
                "counter" : NumberLong(4)
        },
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotPrimaryNoSecondaryOk",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1641239861, 1),
 

But when I use the full URL I cannot connect:

mongo "mongodb://localhost:22222/bud?replicaSet=rs_bud"
MongoDB shell version v5.0.5
connecting to: mongodb://localhost:22222/bud?compressors=disabled&gssapiServiceName=mongodb&replicaSet=rs_bud
{"t":{"$date":"2022-01-03T20:03:27.106Z"},"s":"I",  "c":"NETWORK",  "id":4333208, "ctx":"ReplicaSetMonitor-TaskExecutor","msg":"RSM host selection timeout","attr":{"replicaSet":"rs_bud","error":"FailedToSatisfyReadPreference: Could not find host match
ing read preference { mode: \"nearest\" } for set rs_bud"}}
Error: Could not find host matching read preference { mode: "nearest" } for set rs_bud, rs_bud/localhost:22222 :
connect@src/mongo/shell/mongo.js:372:17
@(connect):2:6
exception: connect failed
exiting with code 1

The same error occured when the tunnel was not running. Changing the read preference to primary or secondary does not helped. How can I access my replica remotely?

Upvotes: 0

Views: 1501

Answers (1)

Joe
Joe

Reputation: 28356

When connecting to a replica set, the host:port pairs in the connection string are a seedlist.

The driver/client will attempt to connect to each host in the seedlist in turn until it gets a connection.

It then runs the isMaster or hello command to determine which node is primary, and to get a list of all replica set members.

Then it drops the original connection, and attempts to connect to each replica set member using the host and port information retrieved.

The host information returned by the hello command will be the host:port listed in rs.conf(), i.e. the hostnames used to initiate the replica set.

In this usage the driver will only be able to successfully connect using localhost and the local port where the SSH tunnel is listening.

When you pass the replica set name in the connection string, it will connect initially using the locahost/port in the connection string, discover the host:port of all members, and then attempt to connect to each member.

In order to connect to a replica set over SSH tunnel, you would need to have the local machine resolve all of the member hostnames listed in rs.conf() to 127.0.0.1, and open an SSH tunnel for each of those members, using the port number listed in rs.conf() as the local port.

Upvotes: 4

Related Questions