[SERVER-20965] rs.initiate() with no parameters can choose a poor hostname Created: 16/Oct/15  Updated: 31/Jan/20  Resolved: 31/Jan/20

Status: Closed
Project: Core Server
Component/s: Replication
Affects Version/s: 3.0.7
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Tom Snee Assignee: Evin Roesle
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-4784 replSetInitiate without arguments bre... Closed
Operating System: ALL
Steps To Reproduce:

Follow the steps outlined in https://docs.mongodb.org/master/tutorial/deploy-replica-set-with-auth/. Examine the configuration object returned by rs.conf().

Expected: members[0].host is "mongodb0.example.net:27017"

Actual: members[0].host is "mongodb0:27017"

Participants:

 Description   

Calling rs.initiate() (i.e. without a configuration object) will cause MongoDB to create its own replicaSet configuration. Unfortunately, for "host" it chooses the computer name without the domain name. Of course this is only a problem when working with computers across different domains, which is probably why no one has noticed it before now.

Workaround: call rs.initiate with a configuration object like this:

    {
        _id: "rs0",
        members: [{
            _id: 0,
            host: "host.domain.tld:port"
        }]
    }



 Comments   
Comment by Evin Roesle [ 31/Jan/20 ]

Closing this ticket as Won't Fix. If you are experiencing this issue without a way to remediate, please reopen this ticket.

Comment by Andy Schwerin [ 16/Oct/15 ]

I suppose so. I would want this back ported to the supported releases in that case, so we could update the tutorials.

Comment by Eric Milkie [ 16/Oct/15 ]

True. Since the logic for 1.1 is already built in to the replSetInitiate command when presented with no config, we could simply change the command itself to take an array as the first parameter and then we wouldn't have to duplicate the logic in the shell.

Comment by Andy Schwerin [ 16/Oct/15 ]

We have to do 1.1 to at least one node in order to figure out the name of the replica set. We could do it against the node represented by "db". I think that gets us down to 5 and 6, yeah.

Comment by Eric Milkie [ 16/Oct/15 ]

If we skipped steps and just did steps 5 and 6, would the replSetInitiate command catch and report most of the errors mentioned in the previous steps? Is the advantage of doing this in the shell that we can report better error messages?

Comment by Andy Schwerin [ 16/Oct/15 ]

My proposal could probably be implemented entirely in the shell. The procedure would be approximately as follows:

  1. for each host named in the array
    1. Run getCmdLineOpts and extract the node's belief about the replica set name from parsed.replication.replSet or parsed.replication.replSetName
    2. Run isMaster and confirm that "isreplicaset" is set to "true", which indicates an uninitialized replica set member. Otherwise, error out.
    3. Run _isSelf on each node.
  2. If the proposed members don't all agree on the set name, error out.
  3. If any of the nodes report the same _isSelf.id value, error out.
  4. If there is a valid "db" global variable in the shell, run _isSelf against it; if it isn't the same as one of the reported nodes' _isSelf.id, error out (optional)
  5. Construct a replica set config document using the data gathered
  6. Run replSetInitiate against "db" or, if there is no"db", against the first node in the list.
Comment by Andy Schwerin [ 16/Oct/15 ]

What if we changed rs.initiate() to take a list of hosts to constitute the replica set? This way, you could run the following single command in the shell to initiate your replica set and add all of the nodes at once, without having to hand-construct the config document. E.g., you could run

rs.initiate(["host1:port1", "host2:port2", "host3:port3"])

instead of

rs.initiate()  // !!! What host will the server choose?
rs.add("host2:port2")
rs.add("host3:port3")

Obviously, we'd then need to update the tutorials and documentation appropriately.

We could, in principle, also change the implementation of rs.initiate() in the shell to use the connection string supplied to the shell if no arguments were provided, instead of expecting the server to figure it out on its own. That might cause a lot of users to end up with replica sets configured for localhost, by accident, though, so I'm not a huge fan.

Generated at Thu Feb 08 03:55:49 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.