Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Zen2] Add low-level bootstrap implementation #34345

Merged

Conversation

DaveCTurner
Copy link
Contributor

Today we inject the initial configuration of the cluster (i.e. the set of
voting nodes) at startup. In reality we must support injecting the initial
configuration after startup too. This commit adds low-level support for doing
so as safely as possible.

Today we inject the initial configuration of the cluster (i.e. the set of
voting nodes) at startup. In reality we must support injecting the initial
configuration after startup too. This commit adds low-level support for doing
so as safely as possible.
@DaveCTurner DaveCTurner added >enhancement v7.0.0 :Distributed Coordination/Cluster Coordination Cluster formation and cluster state publication, including cluster membership and fault detection. labels Oct 8, 2018
@DaveCTurner DaveCTurner requested a review from ywelsch October 8, 2018 07:34
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-distributed

@ywelsch ywelsch mentioned this pull request Oct 8, 2018
61 tasks
@DaveCTurner
Copy link
Contributor Author

@elasticmachine test this please

Copy link
Contributor

@ywelsch ywelsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left some minor comments and questions. Looks very good already.

if (currentState.getLastAcceptedConfiguration().isEmpty() == false) {
throw new CoordinationStateRejectedException("Cannot set initial configuration: configuration has already been set");
}
assert currentState.term() == 0 : currentState;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this duplicating the checks in CoordinationState.setInitialState?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, except that these checks happen earlier.

foundPeerIds.add(getLocalNode().getId());
peerFinder.getFoundPeers().forEach(peer -> foundPeerIds.add(peer.getId()));
if (votingConfiguration.hasQuorum(foundPeerIds) == false) {
throw new CoordinationStateRejectedException("Cannot set initial configuration: no quorum found yet");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe expand the message a bit to not enough nodes discovered yet so that they would form a quorum in the initial configuration + add the foundPeers to the message (not only the ids, but the full nodes).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I pushed 5c47f55.

throw new CoordinationStateRejectedException("Cannot set initial configuration: no quorum found yet");
}

logger.debug("setting initial configuration to {}", votingConfiguration);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can log this at info level. This is a rare event, and worth an entry in the logs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I pushed dbb2b1a

cluster.getAnyNode().applyInitialConfiguration();
cluster.stabilise(defaultMillis(
// the first election should succeed
ELECTION_INITIAL_TIMEOUT_SETTING) // TODO this wait is unnecessary, we could trigger the election immediately
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does the first election succeed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case only one node has a nonempty configuration, so it's the only one that can pass through prevoting and win the election, so there's no election collisions. I expanded the comment in dcbacd8.

assertThat("setting initial configuration may fail with blackholed nodes", blackholedNodes, empty());
runFor(defaultMillis(DISCOVERY_FIND_PEERS_INTERVAL_SETTING) * 2, "discovery prior to setting initial configuration");
final ClusterNode bootstrapNode = getAnyNode();
bootstrapNode.applyInitialConfiguration();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bootstrap API will use networking an have this thing arrive in different times on the node. Should we already simulate a short network delay here? (i.e. schedule as a task)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer not to, so we can use this to assert a tighter bound on the speed of bootstrapping. In most runs this doesn't happen (bootstrapping has already occurred at a random time in runRandomly()).

Copy link
Contributor Author

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I addressed your comments.

if (currentState.getLastAcceptedConfiguration().isEmpty() == false) {
throw new CoordinationStateRejectedException("Cannot set initial configuration: configuration has already been set");
}
assert currentState.term() == 0 : currentState;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, except that these checks happen earlier.

assertThat("setting initial configuration may fail with blackholed nodes", blackholedNodes, empty());
runFor(defaultMillis(DISCOVERY_FIND_PEERS_INTERVAL_SETTING) * 2, "discovery prior to setting initial configuration");
final ClusterNode bootstrapNode = getAnyNode();
bootstrapNode.applyInitialConfiguration();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer not to, so we can use this to assert a tighter bound on the speed of bootstrapping. In most runs this doesn't happen (bootstrapping has already occurred at a random time in runRandomly()).

cluster.getAnyNode().applyInitialConfiguration();
cluster.stabilise(defaultMillis(
// the first election should succeed
ELECTION_INITIAL_TIMEOUT_SETTING) // TODO this wait is unnecessary, we could trigger the election immediately
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case only one node has a nonempty configuration, so it's the only one that can pass through prevoting and win the election, so there's no election collisions. I expanded the comment in dcbacd8.

foundPeerIds.add(getLocalNode().getId());
peerFinder.getFoundPeers().forEach(peer -> foundPeerIds.add(peer.getId()));
if (votingConfiguration.hasQuorum(foundPeerIds) == false) {
throw new CoordinationStateRejectedException("Cannot set initial configuration: no quorum found yet");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I pushed 5c47f55.

throw new CoordinationStateRejectedException("Cannot set initial configuration: no quorum found yet");
}

logger.debug("setting initial configuration to {}", votingConfiguration);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I pushed dbb2b1a

Copy link
Contributor

@ywelsch ywelsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@DaveCTurner
Copy link
Contributor Author

Build failed due to maven flakiness? @elasticmachine test this please.

@DaveCTurner DaveCTurner merged commit 52a3a19 into elastic:zen2 Oct 8, 2018
@DaveCTurner DaveCTurner deleted the 2018-10-07-low-level-bootstrapping branch October 8, 2018 14:56
@jimczi jimczi added v7.0.0-beta1 and removed v7.0.0 labels Feb 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Distributed Coordination/Cluster Coordination Cluster formation and cluster state publication, including cluster membership and fault detection. >enhancement v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants