From 9e5be1af0147aa3dcaa52d60538c002522e047f7 Mon Sep 17 00:00:00 2001 From: Lee Hinman Date: Tue, 8 Dec 2020 16:56:12 -0700 Subject: [PATCH] [7.x] Create AllocationDeciders in the main method of the ILM step (#65037) (8ac30f9a) (#66069) Backports the following commits to 7.x: Create AllocationDeciders in the main method of the ILM step (#65037) (8ac30f9) --- .../decider/FilterAllocationDecider.java | 2 +- .../xpack/core/ilm/AllocationRoutedStep.java | 9 ++-- .../core/ilm/SetSingleNodeAllocateStep.java | 24 +++++----- .../core/ilm/AllocationRoutedStepTests.java | 36 +++++++++++++++ .../ilm/SetSingleNodeAllocateStepTests.java | 45 +++++++++++++++++++ 5 files changed, 99 insertions(+), 17 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/FilterAllocationDecider.java b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/FilterAllocationDecider.java index 9aff987d88c5..4dfb0d18314e 100644 --- a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/FilterAllocationDecider.java +++ b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/FilterAllocationDecider.java @@ -77,7 +77,7 @@ public class FilterAllocationDecider extends AllocationDecider { public static final Setting.AffixSetting CLUSTER_ROUTING_INCLUDE_GROUP_SETTING = Setting.prefixKeySetting(CLUSTER_ROUTING_INCLUDE_GROUP_PREFIX + ".", key -> Setting.simpleString(key, value -> IP_VALIDATOR.accept(key, value), Property.Dynamic, Property.NodeScope)); - public static final Setting.AffixSettingCLUSTER_ROUTING_EXCLUDE_GROUP_SETTING = + public static final Setting.AffixSetting CLUSTER_ROUTING_EXCLUDE_GROUP_SETTING = Setting.prefixKeySetting(CLUSTER_ROUTING_EXCLUDE_GROUP_PREFIX + ".", key -> Setting.simpleString(key, value -> IP_VALIDATOR.accept(key, value), Property.Dynamic, Property.NodeScope)); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStep.java index 461932dcacbf..347de3705b90 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStep.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStep.java @@ -35,9 +35,6 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { private static final Logger logger = LogManager.getLogger(AllocationRoutedStep.class); - private static final AllocationDeciders ALLOCATION_DECIDERS = new AllocationDeciders(Collections.singletonList( - new FilterAllocationDecider(Settings.EMPTY, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)))); - AllocationRoutedStep(StepKey key, StepKey nextStepKey) { super(key, nextStepKey); } @@ -55,7 +52,11 @@ public Result isConditionMet(Index index, ClusterState clusterState) { getKey().getAction(), index.getName()); return new Result(false, waitingForActiveShardsAllocationInfo(idxMeta.getNumberOfReplicas())); } - int allocationPendingAllShards = getPendingAllocations(index, ALLOCATION_DECIDERS, clusterState); + + AllocationDeciders allocationDeciders = new AllocationDeciders(Collections.singletonList( + new FilterAllocationDecider(clusterState.getMetadata().settings(), + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)))); + int allocationPendingAllShards = getPendingAllocations(index, allocationDeciders, clusterState); if (allocationPendingAllShards > 0) { logger.debug("{} lifecycle action [{}] waiting for [{}] shards to be allocated to nodes matching the given filters", diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStep.java index a5fc50a2f290..c719478b21bf 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStep.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStep.java @@ -57,16 +57,6 @@ public class SetSingleNodeAllocateStep extends AsyncActionStep { ALL_CLUSTER_SETTINGS = allSettings; } - // These allocation deciders were chosen because these are the conditions that can prevent - // allocation long-term, and that we can inspect in advance. Most other allocation deciders - // will either only delay relocation (e.g. ThrottlingAllocationDecider), or don't work very - // well when reallocating potentially many shards at once (e.g. DiskThresholdDecider) - private static final AllocationDeciders ALLOCATION_DECIDERS = new AllocationDeciders(Arrays.asList( - new FilterAllocationDecider(Settings.EMPTY, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)), - new DataTierAllocationDecider(new ClusterSettings(Settings.EMPTY, ALL_CLUSTER_SETTINGS)), - new NodeVersionAllocationDecider() - )); - public SetSingleNodeAllocateStep(StepKey key, StepKey nextStepKey, Client client) { super(key, nextStepKey, client); } @@ -78,8 +68,18 @@ public boolean isRetryable() { @Override public void performAction(IndexMetadata indexMetadata, ClusterState clusterState, ClusterStateObserver observer, Listener listener) { + // These allocation deciders were chosen because these are the conditions that can prevent + // allocation long-term, and that we can inspect in advance. Most other allocation deciders + // will either only delay relocation (e.g. ThrottlingAllocationDecider), or don't work very + // well when reallocating potentially many shards at once (e.g. DiskThresholdDecider) + AllocationDeciders allocationDeciders = new AllocationDeciders(Arrays.asList( + new FilterAllocationDecider(clusterState.getMetadata().settings(), + new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)), + new DataTierAllocationDecider(new ClusterSettings(Settings.EMPTY, ALL_CLUSTER_SETTINGS)), + new NodeVersionAllocationDecider() + )); final RoutingNodes routingNodes = clusterState.getRoutingNodes(); - RoutingAllocation allocation = new RoutingAllocation(ALLOCATION_DECIDERS, routingNodes, clusterState, null, + RoutingAllocation allocation = new RoutingAllocation(allocationDeciders, routingNodes, clusterState, null, null, System.nanoTime()); List validNodeIds = new ArrayList<>(); String indexName = indexMetadata.getIndex().getName(); @@ -92,7 +92,7 @@ public void performAction(IndexMetadata indexMetadata, ClusterState clusterState for (RoutingNode node : routingNodes) { boolean canAllocateOneCopyOfEachShard = routingsByShardId.values().stream() // For each shard .allMatch(shardRoutings -> shardRoutings.stream() // Can we allocate at least one shard copy to this node? - .map(shardRouting -> ALLOCATION_DECIDERS.canAllocate(shardRouting, node, allocation).type()) + .map(shardRouting -> allocationDeciders.canAllocate(shardRouting, node, allocation).type()) .anyMatch(Decision.Type.YES::equals)); if (canAllocateOneCopyOfEachShard) { validNodeIds.add(node.node().getId()); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStepTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStepTests.java index 87198f9266d6..cb5cd1887b28 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStepTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/AllocationRoutedStepTests.java @@ -121,6 +121,42 @@ public void testRequireConditionMetOnlyOneCopyAllocated() { new ClusterStateWaitStep.Result(false, allShardsActiveAllocationInfo(0, 1))); } + public void testClusterExcludeFiltersConditionMetOnlyOneCopyAllocated() { + Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20)); + Settings.Builder existingSettings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id) + .put(IndexMetadata.SETTING_INDEX_UUID, index.getUUID()); + + boolean primaryOnNode1 = randomBoolean(); + IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index) + .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", primaryOnNode1, ShardRoutingState.STARTED)) + .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node2", primaryOnNode1 == false, + ShardRoutingState.STARTED)); + + AllocationRoutedStep step = new AllocationRoutedStep(randomStepKey(), randomStepKey()); + IndexMetadata indexMetadata = IndexMetadata.builder(index.getName()).settings(existingSettings).numberOfShards(1) + .numberOfReplicas(1).build(); + ImmutableOpenMap.Builder indices = ImmutableOpenMap.builder().fPut(index.getName(), + indexMetadata); + + Settings clusterSettings = Settings.builder() + .put("cluster.routing.allocation.exclude._id", "node1") + .build(); + Settings.Builder nodeSettingsBuilder = Settings.builder(); + ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE) + .metadata(Metadata.builder().indices(indices.build()).transientSettings(clusterSettings)) + .nodes(DiscoveryNodes.builder() + .add(DiscoveryNode.createLocal(nodeSettingsBuilder.build(), new TransportAddress(TransportAddress.META_ADDRESS, 9200), + "node1")) + .add(DiscoveryNode.createLocal(nodeSettingsBuilder.build(), new TransportAddress(TransportAddress.META_ADDRESS, 9201), + "node2"))) + .routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build(); + Result actualResult = step.isConditionMet(index, clusterState); + + Result expectedResult = new ClusterStateWaitStep.Result(false, allShardsActiveAllocationInfo(1, 1)); + assertEquals(expectedResult.isComplete(), actualResult.isComplete()); + assertEquals(expectedResult.getInfomationContext(), actualResult.getInfomationContext()); + } + public void testExcludeConditionMetOnlyOneCopyAllocated() { Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20)); Map excludes = Collections.singletonMap(IndexMetadata.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + "foo", "bar"); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStepTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStepTests.java index dedbfcab7342..6478c9b4517d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStepTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStepTests.java @@ -175,6 +175,51 @@ public void testPerformActionAttrsSomeNodesValid() throws IOException { assertNodeSelected(indexMetadata, index, validNodeIds, nodes); } + public void testPerformActionWithClusterExcludeFilters() throws IOException { + Settings.Builder indexSettings = settings(Version.CURRENT); + IndexMetadata indexMetadata = IndexMetadata.builder(randomAlphaOfLength(10)).settings(indexSettings) + .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 1)).build(); + Index index = indexMetadata.getIndex(); + + DiscoveryNodes.Builder nodes = DiscoveryNodes.builder(); + String nodeId = "node_id_0"; + int nodePort = 9300; + Builder nodeSettingsBuilder = Settings.builder(); + nodes.add(DiscoveryNode.createLocal(nodeSettingsBuilder.build(), new TransportAddress(TransportAddress.META_ADDRESS, nodePort), + nodeId)); + + Settings clusterSettings = Settings.builder() + .put("cluster.routing.allocation.exclude._id", "node_id_0") + .build(); + ImmutableOpenMap.Builder indices = ImmutableOpenMap.builder().fPut(index.getName(), + indexMetadata); + IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index) + .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node_id_0", true, ShardRoutingState.STARTED)); + ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE) + .metadata(Metadata.builder().indices(indices.build()).transientSettings(clusterSettings)) + .nodes(nodes).routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build(); + + SetSingleNodeAllocateStep step = createRandomInstance(); + SetOnce actionCompleted = new SetOnce<>(); + step.performAction(indexMetadata, clusterState, null, new Listener() { + + @Override + public void onResponse(boolean complete) { + throw new AssertionError("Unexpected method call"); + } + + @Override + public void onFailure(Exception e) { + actionCompleted.set(e); + } + }); + + Exception failure = actionCompleted.get(); + assertThat(failure, instanceOf(NoNodeAvailableException.class)); + + Mockito.verifyZeroInteractions(client); + } + public void testPerformActionAttrsNoNodesValid() { final int numNodes = randomIntBetween(1, 20); String[] validAttr = new String[] { "box_type", "valid" };