-
Notifications
You must be signed in to change notification settings - Fork 14.7k
KAFKA-19719: --no-initial-controllers should not assume kraft.version=1 #20551
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
Changes from all commits
dcc3668
e0ad6c0
1720ad7
a905fc8
e671a39
ae21d0e
8917f9d
9864633
951b874
c99a253
c087a97
8c0271b
cf4a00e
f8926de
6e23ed8
d1e3b65
14fabc4
989796a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,8 +149,9 @@ object StorageTool extends Logging { | |
}) | ||
val initialControllers = namespace.getString("initial_controllers") | ||
val isStandalone = namespace.getBoolean("standalone") | ||
if (!config.quorumConfig.voters().isEmpty && | ||
(Option(initialControllers).isDefined || isStandalone)) { | ||
val staticVotersEmpty = config.quorumConfig.voters().isEmpty | ||
formatter.setHasDynamicQuorum(staticVotersEmpty) | ||
if (!staticVotersEmpty && (Option(initialControllers).isDefined || isStandalone)) { | ||
throw new TerseFailure("You cannot specify " + | ||
QuorumConfig.QUORUM_VOTERS_CONFIG + " and format the node " + | ||
"with --initial-controllers or --standalone. " + | ||
|
@@ -163,16 +164,13 @@ object StorageTool extends Logging { | |
if (isStandalone) { | ||
formatter.setInitialControllers(createStandaloneDynamicVoters(config)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you look at the dynamic quorum arguments, you cannot specify multiple at the same time:
|
||
} | ||
if (namespace.getBoolean("no_initial_controllers")) { | ||
formatter.setNoInitialControllersFlag(true) | ||
} else { | ||
if (config.processRoles.contains(ProcessRole.ControllerRole)) { | ||
if (config.quorumConfig.voters().isEmpty && formatter.initialVoters().isEmpty) { | ||
if (!namespace.getBoolean("no_initial_controllers") && | ||
config.processRoles.contains(ProcessRole.ControllerRole) && | ||
staticVotersEmpty && | ||
formatter.initialVoters().isEmpty) { | ||
throw new TerseFailure("Because " + QuorumConfig.QUORUM_VOTERS_CONFIG + | ||
" is not set on this controller, you must specify one of the following: " + | ||
"--standalone, --initial-controllers, or --no-initial-controllers."); | ||
} | ||
} | ||
} | ||
Option(namespace.getList("add_scram")). | ||
foreach(scramArgs => formatter.setScramArguments(scramArgs.asInstanceOf[util.List[String]])) | ||
|
@@ -342,18 +340,21 @@ object StorageTool extends Logging { | |
|
||
val reconfigurableQuorumOptions = formatParser.addMutuallyExclusiveGroup() | ||
reconfigurableQuorumOptions.addArgument("--standalone", "-s") | ||
.help("Used to initialize a controller as a single-node dynamic quorum.") | ||
.help("Used to initialize a controller as a single-node dynamic quorum. When setting this flag, " + | ||
"the controller.quorum.voters config must not be set, and controller.quorum.bootstrap.servers is set instead.") | ||
.action(storeTrue()) | ||
|
||
reconfigurableQuorumOptions.addArgument("--no-initial-controllers", "-N") | ||
.help("Used to initialize a server without a dynamic quorum topology.") | ||
.help("Used to initialize a server without specifying a dynamic quorum. When setting this flag, " + | ||
"the controller.quorum.voters config should not be set, and controller.quorum.bootstrap.servers is set instead.") | ||
.action(storeTrue()) | ||
|
||
reconfigurableQuorumOptions.addArgument("--initial-controllers", "-I") | ||
.help("Used to initialize a server with a specific dynamic quorum topology. The argument " + | ||
.help("Used to initialize a server with the specified dynamic quorum. The argument " + | ||
"is a comma-separated list of id@hostname:port:directory. The same values must be used to " + | ||
"format all nodes. For example:\n0@example.com:8082:JEXY6aqzQY-32P5TStzaFg,1@example.com:8083:" + | ||
"MvDxzVmcRsaTz33bUuRU6A,2@example.com:8084:07R5amHmR32VDA6jHkGbTA\n") | ||
"MvDxzVmcRsaTz33bUuRU6A,2@example.com:8084:07R5amHmR32VDA6jHkGbTA\n. When setting this flag, " + | ||
"the controller.quorum.voters config must not be set, and controller.quorum.bootstrap.servers is set instead.") | ||
.action(store()) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,9 +84,8 @@ public void testCreateAndDestroyReconfigurableCluster() throws Exception { | |
new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(1). | ||
setFeature(KRaftVersion.FEATURE_NAME, KRaftVersion.KRAFT_VERSION_1.featureLevel()). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the method |
||
build() | ||
).build()) { | ||
).setStandalone(true).build()) { | ||
cluster.format(); | ||
cluster.startup(); | ||
try (Admin admin = Admin.create(cluster.clientProperties())) { | ||
|
@@ -108,13 +107,23 @@ static Map<Integer, Uuid> findVoterDirs(Admin admin) throws Exception { | |
|
||
@Test | ||
public void testRemoveController() throws Exception { | ||
try (KafkaClusterTestKit cluster = new KafkaClusterTestKit.Builder( | ||
new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(3). | ||
setFeature(KRaftVersion.FEATURE_NAME, KRaftVersion.KRAFT_VERSION_1.featureLevel()). | ||
build() | ||
).build()) { | ||
final var nodes = new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(3). | ||
build(); | ||
|
||
final Map<Integer, Uuid> initialVoters = new HashMap<>(); | ||
for (final var controllerNode : nodes.controllerNodes().values()) { | ||
initialVoters.put( | ||
controllerNode.id(), | ||
controllerNode.metadataDirectoryId() | ||
); | ||
} | ||
|
||
try (KafkaClusterTestKit cluster = new KafkaClusterTestKit.Builder(nodes). | ||
setInitialVoterSet(initialVoters). | ||
build() | ||
) { | ||
cluster.format(); | ||
cluster.startup(); | ||
try (Admin admin = Admin.create(cluster.clientProperties())) { | ||
|
@@ -133,12 +142,22 @@ public void testRemoveController() throws Exception { | |
|
||
@Test | ||
public void testRemoveAndAddSameController() throws Exception { | ||
try (KafkaClusterTestKit cluster = new KafkaClusterTestKit.Builder( | ||
new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(4). | ||
setFeature(KRaftVersion.FEATURE_NAME, KRaftVersion.KRAFT_VERSION_1.featureLevel()). | ||
build()).build() | ||
final var nodes = new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(4). | ||
build(); | ||
|
||
final Map<Integer, Uuid> initialVoters = new HashMap<>(); | ||
for (final var controllerNode : nodes.controllerNodes().values()) { | ||
initialVoters.put( | ||
controllerNode.id(), | ||
controllerNode.metadataDirectoryId() | ||
); | ||
} | ||
|
||
try (KafkaClusterTestKit cluster = new KafkaClusterTestKit.Builder(nodes). | ||
setInitialVoterSet(initialVoters). | ||
build() | ||
) { | ||
cluster.format(); | ||
cluster.startup(); | ||
|
@@ -173,7 +192,6 @@ public void testControllersAutoJoinStandaloneVoter() throws Exception { | |
final var nodes = new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(3). | ||
setFeature(KRaftVersion.FEATURE_NAME, KRaftVersion.KRAFT_VERSION_1.featureLevel()). | ||
build(); | ||
try (KafkaClusterTestKit cluster = new KafkaClusterTestKit.Builder(nodes). | ||
setConfigProp(QuorumConfig.QUORUM_AUTO_JOIN_ENABLE_CONFIG, true). | ||
|
@@ -199,7 +217,6 @@ public void testNewVoterAutoRemovesAndAdds() throws Exception { | |
final var nodes = new TestKitNodes.Builder(). | ||
setNumBrokerNodes(1). | ||
setNumControllerNodes(3). | ||
setFeature(KRaftVersion.FEATURE_NAME, KRaftVersion.KRAFT_VERSION_1.featureLevel()). | ||
build(); | ||
|
||
// Configure the initial voters with one voter having a different directory ID. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still feel it is weird that users configure
controller.quorum.voters
with--no-initial-controllers
, but you are right that we should keep the compatibility.Should we add another warning to remind users that
--no-initial-controllers
should not be used with static voters even though it is no-op?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can add it to the flag's help output.