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

cluster: set feature_table version during bootstrap #8225

Merged
merged 5 commits into from
Jan 19, 2023

Conversation

jcsp
Copy link
Contributor

@jcsp jcsp commented Jan 13, 2023

cluster: set feature_table version during bootstrap

In some circumstances, a cluster can have two nodes up+bootstrapped,
with an active controller raft group, but a third founding node
trying to join the cluster by requesting an ID (because this node
reported in earlier, but had trouble following through with the
bootstrap process).

Because handing out node IDs is behind a feature gate, this
would fail, and the cluster logical version would not advance
because there was a node in the members_table who had not
reported its logical version.

Avoid this class of issues by including logical version in
the controller bootstrap event, so that as soon as there is
a bootstrap message in the log, we are certain to have activated
all the features that a node might need to proceed.

Fixes #8203

Backports Required

  • none - not a bug fix
  • none - issue does not exist in previous branches
  • none - papercut/not impactful enough to backport
  • v22.3.x
  • v22.2.x
  • v22.1.x

UX Changes

None

Release Notes

Bug Fixes

  • An issue is fixed that could prevent clusters forming successfully when network disruptions happened during initial startup of the founding nodes.

Comment on lines 156 to 162
co_await _feature_table.invoke_on_all(
[v = cmd.value.founding_version](features::feature_table& ft) {
ft.set_active_version(v);
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 need to avoid doing this if the version is lower than the current active version, e.g. if we've already loaded a feature table snapshot and are now replaying the controller log that was started on an older version.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, you're right. I think we can be even stricter, and just only set the active version if the current active version is invalid_version: this should only be happening when we have a totally default-constructed feature table.

@jcsp jcsp force-pushed the issue-8203 branch 2 times, most recently from d7e1be2 to 4368bf8 Compare January 13, 2023 19:35
@jcsp
Copy link
Contributor Author

jcsp commented Jan 13, 2023

This caused a failure in test_feature_table_snapshots

@jcsp jcsp force-pushed the issue-8203 branch 2 times, most recently from 5d71e97 to a3de4b1 Compare January 16, 2023 22:52
The "normal" set_active_version method increments the version but does
not activate features (though it may make them available).  This is
because activating features on upgrade is optional, and that optionality
is respected at time of writing to the controller log, not replaying it.

The reason for making auto-activation optional is to enable cautious
upgrades, but during cluster bootstrap this motivation goes away, so
we will unconditionally switch on all the available features when we
see the bootstrap message's cluster version in the controller log.  That
is what this function does, as well as calling through to set_active_version.
This enables nodes reading the record to fast-forward their
feature table to this version, without waiting for the feature_manager
logic to see all nodes' versions and activate that way.

Usually this is superfluous, when a founding triplet of nodes
will be up promptly, but in some cases we might run with just
two nodes for some time, where these two nodes would otherwise
wait for the third to report its version before advancing
the feature table version.
It will use this for setting the cluster logical version
proactively when it sees one in a bootstrap message.
In some circumstances, a cluster can have two nodes up+bootstrapped,
with an active controller raft group, but a third founding node
trying to join the cluster by requesting an ID (because this node
reported in earlier, but had trouble following through with the
bootstrap process).

Because handing out node IDs is behind a feature gate, this
would fail, and the cluster logical version would not advance
because there was a node in the members_table who had not
reported its logical version.

Avoid this class of issues by including logical version in
the controller bootstrap event, so that as soon as there is
a bootstrap message in the log, we are certain to have activated
all the features that a node might need to proceed.

Fixes redpanda-data#8203
@jcsp
Copy link
Contributor Author

jcsp commented Jan 17, 2023

This one snowballed a bit...

I realized that bootstrap_backend also needs to write a snapshot, because once it has applied the latest version, there is no subsequent feature_manager-driven update that would prompt a snapshot.

While looking at this, I was also reminded that we go through this awkward phase pre-cluster-join where we have no logical cluster version. I've added a commit that fast-forwards the cluster version prior to joining the cluster. This is kind of orthogonal to the issue originally fixed in this PR, but made sense while I had my mind on it.

One thing I haven't done here is to make that node join totally safe by refusing to let newer-version nodes join the cluster (because they would have set their own feature_table to a higher one than the cluster is using). Currently we validate the version of joining nodes, but only to refuse to let too-old nodes join. Maybe some discussion needed on how to make this check, or whether we should instead try to tolerate newer nodes and teach them to rewind their feature table when they join an older version cluster.

@jcsp
Copy link
Contributor Author

jcsp commented Jan 17, 2023

The early population of cluster version prior to node join was getting hairy, so I split it off in #8282

@jcsp jcsp marked this pull request as ready for review January 17, 2023 23:09
@jcsp jcsp requested a review from andrwng January 17, 2023 23:09
Copy link
Contributor

@andrwng andrwng left a comment

Choose a reason for hiding this comment

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

LGTM, though I agree for the story to be complete we need #8282, which I also think makes sense since a brand new node should expect to only be able to join a cluster of the same version.

@jcsp
Copy link
Contributor Author

jcsp commented Jan 18, 2023

@jcsp
Copy link
Contributor Author

jcsp commented Jan 18, 2023

/ci-repeat 5

@jcsp
Copy link
Contributor Author

jcsp commented Jan 19, 2023

@jcsp jcsp merged commit 9e6ede0 into redpanda-data:dev Jan 19, 2023
@jcsp jcsp deleted the issue-8203 branch January 19, 2023 11:46
@jcsp
Copy link
Contributor Author

jcsp commented Jan 19, 2023

/backport v22.3.x

@vbotbuildovich
Copy link
Collaborator

Failed to run cherry-pick command. I executed the below command:

git cherry-pick -x 98ba9430855e1d8b0db09b9b1d18cdc16fe3b1e1 9d9539c911d80560b0622e72dc468164523f8420 a4500c8409984da8f5e42f10222f5546c0ed2a59 54120c9e1f982a36963749ea15799eaa9b43c11c 57c70f3e496a4eb7299c1ca844bf3c2552118429

Workflow run logs.

@jcsp
Copy link
Contributor Author

jcsp commented Jan 20, 2023

#8340

andrwng added a commit that referenced this pull request Jan 20, 2023
[v22.3.x] Backport #8225 (cluster: set feature_table version during bootstrap)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cluster fails to fully form when console is attempting to connect to an rpc port
3 participants