Skip to content

Commit 3262133

Browse files
HDDS-14618. Support including only specified containers in Container Balancer (#9839)
1 parent c8b6340 commit 3262133

15 files changed

Lines changed: 115 additions & 15 deletions

File tree

hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerConfiguration.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ public final class ContainerBalancerConfiguration {
9191
"to exclude from balancing. For example \"1, 4, 5\" or \"1,4,5\".")
9292
private String excludeContainers = "";
9393

94+
@Config(key = "hdds.container.balancer.include.containers", type = ConfigType.STRING, defaultValue =
95+
"", tags = {ConfigTag.BALANCER}, description = "List of container IDs " +
96+
"to include in balancing. Only these containers will be included in balancing. " +
97+
"For example \"1, 4, 5\" or \"1,4,5\".")
98+
private String includeContainers = "";
99+
94100
@Config(key = "hdds.container.balancer.move.timeout", type = ConfigType.TIME, defaultValue = "65m",
95101
tags = {ConfigTag.BALANCER}, description =
96102
"The amount of time to allow a single container to move " +
@@ -311,6 +317,17 @@ public Set<ContainerID> getExcludeContainers() {
311317
}).collect(Collectors.toSet());
312318
}
313319

320+
public Set<ContainerID> getIncludeContainers() {
321+
if (includeContainers.isEmpty()) {
322+
return new HashSet<>();
323+
}
324+
return Arrays.stream(includeContainers.split(","))
325+
.map(s -> {
326+
s = s.trim();
327+
return ContainerID.valueOf(Long.parseLong(s));
328+
}).collect(Collectors.toSet());
329+
}
330+
314331
/**
315332
* Sets containers to exclude from balancing.
316333
* @param excludeContainers String of {@link ContainerID} to exclude. For
@@ -320,6 +337,16 @@ public void setExcludeContainers(String excludeContainers) {
320337
this.excludeContainers = excludeContainers;
321338
}
322339

340+
/**
341+
* Sets containers to include in balancing. When non-empty, only these
342+
* containers will be considered for balancing.
343+
* @param includeContainers String of {@link ContainerID} to include. For
344+
* example, "1, 4, 5" or "1,4,5".
345+
*/
346+
public void setIncludeContainers(String includeContainers) {
347+
this.includeContainers = includeContainers;
348+
}
349+
323350
public Duration getMoveTimeout() {
324351
return Duration.ofMillis(moveTimeout);
325352
}
@@ -422,6 +449,7 @@ public String toString() {
422449
"%-50s %s%n" +
423450
"%-50s %s%n" +
424451
"%-50s %s%n" +
452+
"%-50s %s%n" +
425453
"%-50s %s%n", "Key", "Value", "Threshold",
426454
threshold, "Max Datanodes to Involve per Iteration(percent)",
427455
maxDatanodesPercentageToInvolvePerIteration,
@@ -443,6 +471,8 @@ public String toString() {
443471
networkTopologyEnable,
444472
"Whether to Trigger Refresh Datanode Usage Info",
445473
triggerDuEnable,
474+
"Container IDs to Include in Balancing",
475+
includeContainers.isEmpty() ? "None" : includeContainers,
446476
"Container IDs to Exclude from Balancing",
447477
excludeContainers.equals("") ? "None" : excludeContainers,
448478
"Datanodes Specified to be Balanced",
@@ -463,6 +493,7 @@ public ContainerBalancerConfigurationProto.Builder toProtobufBuilder() {
463493
.setSizeLeavingSourceMax(maxSizeLeavingSource)
464494
.setIterations(iterations)
465495
.setExcludeContainers(excludeContainers)
496+
.setIncludeContainers(includeContainers)
466497
.setMoveTimeout(moveTimeout)
467498
.setBalancingIterationInterval(balancingInterval)
468499
.setIncludeDatanodes(includeNodes)
@@ -497,6 +528,9 @@ static ContainerBalancerConfiguration fromProtobuf(
497528
if (proto.hasIterations()) {
498529
config.setIterations(proto.getIterations());
499530
}
531+
if (proto.hasIncludeContainers()) {
532+
config.setIncludeContainers(proto.getIncludeContainers());
533+
}
500534
if (proto.hasExcludeContainers()) {
501535
config.setExcludeContainers(proto.getExcludeContainers());
502536
}

hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ StartContainerBalancerResponseProto startContainerBalancer(
376376
Optional<Boolean> networkTopologyEnable,
377377
Optional<String> includeNodes,
378378
Optional<String> excludeNodes,
379-
Optional<String> excludeContainers) throws IOException;
379+
Optional<String> excludeContainers,
380+
Optional<String> includeContainers) throws IOException;
380381

381382
/**
382383
* Stop ContainerBalancer.

hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ StartContainerBalancerResponseProto startContainerBalancer(
442442
Optional<Boolean> networkTopologyEnable,
443443
Optional<String> includeNodes,
444444
Optional<String> excludeNodes,
445-
Optional<String> excludeContainers) throws IOException;
445+
Optional<String> excludeContainers,
446+
Optional<String> includeContainers) throws IOException;
446447

447448
/**
448449
* Stop ContainerBalancer.

hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,8 @@ public StartContainerBalancerResponseProto startContainerBalancer(
966966
Optional<Boolean> networkTopologyEnable,
967967
Optional<String> includeNodes,
968968
Optional<String> excludeNodes,
969-
Optional<String> excludeContainers) throws IOException {
969+
Optional<String> excludeContainers,
970+
Optional<String> includeContainers) throws IOException {
970971
StartContainerBalancerRequestProto.Builder builder =
971972
StartContainerBalancerRequestProto.newBuilder();
972973
builder.setTraceID(TracingUtil.exportCurrentSpan());
@@ -1057,6 +1058,11 @@ public StartContainerBalancerResponseProto startContainerBalancer(
10571058
builder.setExcludeContainers(ec);
10581059
}
10591060

1061+
if (includeContainers.isPresent()) {
1062+
String ic = includeContainers.get();
1063+
builder.setIncludeContainers(ic);
1064+
}
1065+
10601066
StartContainerBalancerRequestProto request = builder.build();
10611067
return submitRequest(Type.StartContainerBalancer,
10621068
builder1 -> builder1.setStartContainerBalancerRequest(request))

hadoop-hdds/interface-admin/src/main/proto/ScmAdminProtocol.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ message StartContainerBalancerRequestProto {
604604
optional string includeNodes = 14;
605605
optional string excludeNodes = 15;
606606
optional string excludeContainers = 16;
607+
optional string includeContainers = 17;
607608
}
608609

609610
message StartContainerBalancerResponseProto {

hadoop-hdds/interface-client/src/main/proto/hdds.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ message ContainerBalancerConfigurationProto {
503503
required bool shouldRun = 18;
504504
optional int32 nextIterationIndex = 19;
505505
optional int64 moveReplicationTimeout = 20;
506+
optional string includeContainers = 21;
506507
}
507508

508509
message TransferLeadershipRequestProto {

hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerSelectionCriteria.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class ContainerBalancerSelectionCriteria {
5454
private ContainerManager containerManager;
5555
private Map<ContainerID, DatanodeDetails> containerToSourceMap;
5656
private Set<ContainerID> excludeContainers;
57+
private Set<ContainerID> includeContainers;
5758
private Set<ContainerID> excludeContainersDueToFailure;
5859
private FindSourceStrategy findSourceStrategy;
5960
private Map<DatanodeDetails, NavigableSet<ContainerID>> setMap;
@@ -72,6 +73,7 @@ public ContainerBalancerSelectionCriteria(
7273
this.containerToSourceMap = containerToSourceMap;
7374
excludeContainersDueToFailure = new HashSet<>();
7475
excludeContainers = balancerConfiguration.getExcludeContainers();
76+
includeContainers = balancerConfiguration.getIncludeContainers();
7577
this.findSourceStrategy = findSourceStrategy;
7678
this.setMap = new HashMap<>();
7779
}
@@ -158,6 +160,10 @@ private Comparator<ContainerID> orderContainersByUsedBytes() {
158160
public boolean shouldBeExcluded(ContainerID containerID,
159161
DatanodeDetails node, long sizeMovedAlready) {
160162
ContainerInfo container;
163+
//If includeContainers is specified, exclude containers not in the include list
164+
if (!includeContainers.isEmpty() && !includeContainers.contains(containerID)) {
165+
return true;
166+
}
161167
try {
162168
container = containerManager.getContainer(containerID);
163169
} catch (ContainerNotFoundException e) {
@@ -263,6 +269,9 @@ private NavigableSet<ContainerID> getCandidateContainers(DatanodeDetails node) {
263269
new TreeSet<>(orderContainersByUsedBytes().reversed());
264270
try {
265271
Set<ContainerID> idSet = nodeManager.getContainers(node);
272+
if (includeContainers != null && !includeContainers.isEmpty()) {
273+
idSet.retainAll(includeContainers);
274+
}
266275
if (excludeContainers != null) {
267276
idSet.removeAll(excludeContainers);
268277
}

hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocolServerSideTranslatorPB.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,7 @@ public StartContainerBalancerResponseProto startContainerBalancer(
11461146
Optional<String> includeNodes = Optional.empty();
11471147
Optional<String> excludeNodes = Optional.empty();
11481148
Optional<String> excludeContainers = Optional.empty();
1149+
Optional<String> includeContainers = Optional.empty();
11491150

11501151
if (request.hasThreshold()) {
11511152
threshold = Optional.of(request.getThreshold());
@@ -1210,12 +1211,16 @@ public StartContainerBalancerResponseProto startContainerBalancer(
12101211
excludeContainers = Optional.of(request.getExcludeContainers());
12111212
}
12121213

1214+
if (request.hasIncludeContainers()) {
1215+
includeContainers = Optional.of(request.getIncludeContainers());
1216+
}
1217+
12131218
return impl.startContainerBalancer(threshold, iterations,
12141219
maxDatanodesPercentageToInvolvePerIteration,
12151220
maxSizeToMovePerIterationInGB, maxSizeEnteringTargetInGB,
12161221
maxSizeLeavingSourceInGB, balancingInterval, moveTimeout,
12171222
moveReplicationTimeout, networkTopologyEnable, includeNodes,
1218-
excludeNodes, excludeContainers);
1223+
excludeNodes, excludeContainers, includeContainers);
12191224
}
12201225

12211226
public StopContainerBalancerResponseProto stopContainerBalancer(

hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,8 @@ public StartContainerBalancerResponseProto startContainerBalancer(
11611161
Optional<Boolean> networkTopologyEnable,
11621162
Optional<String> includeNodes,
11631163
Optional<String> excludeNodes,
1164-
Optional<String> excludeContainers) throws IOException {
1164+
Optional<String> excludeContainers,
1165+
Optional<String> includeContainers) throws IOException {
11651166
Map<String, String> auditMap = Maps.newHashMap();
11661167
try {
11671168
getScm().checkAdminAccess(getRemoteUser(), false);
@@ -1277,6 +1278,12 @@ public StartContainerBalancerResponseProto startContainerBalancer(
12771278
cbc.setExcludeContainers(ec);
12781279
}
12791280

1281+
if (includeContainers.isPresent()) {
1282+
String ic = includeContainers.get();
1283+
auditMap.put("includeContainers", (ic));
1284+
cbc.setIncludeContainers(ic);
1285+
}
1286+
12801287
ContainerBalancer containerBalancer = scm.getContainerBalancer();
12811288
containerBalancer.startBalancer(cbc);
12821289

hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancerDatanodeNodeLimit.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,23 @@ public void balancerShouldNotSelectConfiguredExcludeContainers(@Nonnull MockedSC
459459
}
460460
}
461461

462+
@ParameterizedTest(name = "MockedSCM #{index}: {0}")
463+
@MethodSource("createMockedSCMs")
464+
public void balancerShouldOnlySelectConfiguredIncludeContainers(@Nonnull MockedSCM mockedSCM) {
465+
ContainerBalancerConfiguration config = new ContainerBalancerConfigBuilder(mockedSCM.getNodeCount()).build();
466+
config.setIncludeContainers("1, 4, 5");
467+
468+
ContainerBalancerTask task = mockedSCM.startBalancerTask(config);
469+
470+
Set<ContainerID> includeContainers = config.getIncludeContainers();
471+
assertThat(task.getContainerToSourceMap()).isNotEmpty();
472+
for (ContainerID container : task.getContainerToSourceMap().keySet()) {
473+
assertThat(includeContainers)
474+
.as("Container %s should be in the include list", container)
475+
.contains(container);
476+
}
477+
}
478+
462479
@ParameterizedTest(name = "MockedSCM #{index}: {0}")
463480
@MethodSource("createMockedSCMs")
464481
public void checkIterationResult(@Nonnull MockedSCM mockedSCM) {

0 commit comments

Comments
 (0)