0

When connection to a MongoDB replica set, I'm able to read from the secondaries, but afterwards, when writing using the same connection, I receive the following error:

pymongo.errors.ServerSelectionTimeoutError: No primary available for writes

Python 3.4.3 Pymongo 3.2.2

My connection:

var_host = 'XXX.XXX.XXX.XXX' # Public IP
var_port = 27017
var_username = 'username'
var_password = 'password'
mongo_uri = 'mongodb://%s:%s@%s:%s' % (username, password, host, port)
client_db = MongoClient(mongo_uri,
                 replicaSet='rs0',
                 readPreference='secondaryPreferred')

IMPORTANT: When removing both 'replicaSet' and 'readPrefence' fields, the connection works.

In the server:

rs0:PRIMARY> rs.status()
{"set" : "rs0",
 "date" : ISODate("2016-11-23T13:09:55.699Z"),
 "myState" : 1,
 "term" : NumberLong(4),
 "heartbeatIntervalMillis" : NumberLong(2000),
 "members" : [
    {
        "_id" : 0,
        "name" : "mongodb0:27017",
        "health" : 1,
        "state" : 1,
        "stateStr" : "PRIMARY",
        "uptime" : 64491,
        "optime" : {
            "ts" : Timestamp(1479906595, 21),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2016-11-23T13:09:55Z"),
        "electionTime" : Timestamp(1479844637, 1),
        "electionDate" : ISODate("2016-11-22T19:57:17Z"),
        "configVersion" : 424888,
        "self" : true
    },
    {
        "_id" : 1,
        "name" : "mongodb2:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 61631,
        "optime" : {
            "ts" : Timestamp(1479906593, 31),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2016-11-23T13:09:53Z"),
        "lastHeartbeat" : ISODate("2016-11-23T13:09:53.776Z"),
        "lastHeartbeatRecv" : ISODate("2016-11-23T13:09:53.758Z"),
        "pingMs" : NumberLong(0),
        "syncingTo" : "XXXXXXXX:27017",
        "configVersion" : 424888
    },
    {
        "_id" : 2,
        "name" : "mongodb3:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 61264,
        "optime" : {
            "ts" : Timestamp(1479906593, 31),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2016-11-23T13:09:53Z"),
        "lastHeartbeat" : ISODate("2016-11-23T13:09:53.776Z"),
        "lastHeartbeatRecv" : ISODate("2016-11-23T13:09:55.493Z"),
        "pingMs" : NumberLong(0),
        "syncingTo" : "XXX:27017",
        "configVersion" : 424888
    }
   ],
   "ok" : 1}

db.isMaster()

mongodb0

rs0:PRIMARY> db.isMaster()
{
"hosts" : [
    "mongodb0:27017"
],
"passives" : [
    "10.150.151.141:27017",
    "10.150.151.155:27017"
],
"setName" : "rs0",
"setVersion" : 424888,
"ismaster" : true,
"secondary" : false,
"primary" : "mongodb0:27017",
"me" : "mongodb0:27017",
"electionId" : ObjectId("7fffffff0000000000000004"),
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2016-11-23T15:12:37.988Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1
}

mongodb1

rs0:SECONDARY> db.isMaster()
{
"hosts" : [
    "mongodb0:27017"
],
"passives" : [
    "10.150.151.141:27017",
    "10.150.151.155:27017"
],
"setName" : "rs0",
"setVersion" : 424888,
"ismaster" : false,
"secondary" : true,
"primary" : "mongodb0:27017",
"passive" : true,
"me" : "10.150.151.141:27017",
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2016-11-23T15:24:32.134Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1

mongodb2

 rs0:SECONDARY> db.isMaster()
 {
 "hosts" : [
    "mongodb0:27017"
 ],
 "passives" : [
    "10.150.151.141:27017",
    "10.150.151.155:27017"
 ],
"setName" : "rs0",
 "setVersion" : 424888,
"ismaster" : false,
"secondary" : true,
"primary" : "mongodb0:27017",
"passive" : true,
"me" : "10.150.151.155:27017",
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2016-11-23T15:21:54.971Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1
}
Nadav
  • 574
  • 10
  • 24

1 Answers1

1

I hypothesize that:

  1. Your driver can connect to your secondary's public IP at either 10.150.151.141:27017 or 10.150.151.155:27017 or both.
  2. Your connection string points to one of the above public IPs for secondaries, or your connection string points to the public IP of the primary.
  3. The replica set uses internal IPs in its configuration which are not accessible to your client machine: it cannot connect to "mongodb0", "mongodb1", or "mongodb2".

You need to reconfigure your replica set using public IPs. If you're curious why this is so, it's explained in the Server Discovery and Monitoring Spec. But the gist is this: whatever is listed for members' hostnames in rs.conf() must be public hostnames accessible to your client machine.

A. Jesse Jiryu Davis
  • 23,641
  • 4
  • 57
  • 70