Skip to content

Commit be1a568

Browse files
authored
[7.x] Fix SetSingleNodeAllocateStep for data tier deployments (#64679) (#64726)
Backports the following commits to 7.x: Fix SetSingleNodeAllocateStep for data tier deployments (#64679)
1 parent 30934f0 commit be1a568

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/SetSingleNodeAllocateStep.java

+15
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,19 @@
2424
import org.elasticsearch.cluster.routing.allocation.decider.NodeVersionAllocationDecider;
2525
import org.elasticsearch.common.Randomness;
2626
import org.elasticsearch.common.settings.ClusterSettings;
27+
import org.elasticsearch.common.settings.Setting;
2728
import org.elasticsearch.common.settings.Settings;
2829
import org.elasticsearch.index.IndexNotFoundException;
2930
import org.elasticsearch.index.shard.ShardId;
31+
import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider;
3032

3133
import java.util.ArrayList;
3234
import java.util.Arrays;
35+
import java.util.HashSet;
3336
import java.util.List;
3437
import java.util.Map;
3538
import java.util.Optional;
39+
import java.util.Set;
3640
import java.util.stream.Collectors;
3741

3842
/**
@@ -43,12 +47,23 @@ public class SetSingleNodeAllocateStep extends AsyncActionStep {
4347
private static final Logger logger = LogManager.getLogger(SetSingleNodeAllocateStep.class);
4448
public static final String NAME = "set-single-node-allocation";
4549

50+
private static final Set<Setting<?>> ALL_CLUSTER_SETTINGS;
51+
52+
static {
53+
Set<Setting<?>> allSettings = new HashSet<>(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
54+
allSettings.add(DataTierAllocationDecider.CLUSTER_ROUTING_REQUIRE_SETTING);
55+
allSettings.add(DataTierAllocationDecider.CLUSTER_ROUTING_INCLUDE_SETTING);
56+
allSettings.add(DataTierAllocationDecider.CLUSTER_ROUTING_EXCLUDE_SETTING);
57+
ALL_CLUSTER_SETTINGS = allSettings;
58+
}
59+
4660
// These allocation deciders were chosen because these are the conditions that can prevent
4761
// allocation long-term, and that we can inspect in advance. Most other allocation deciders
4862
// will either only delay relocation (e.g. ThrottlingAllocationDecider), or don't work very
4963
// well when reallocating potentially many shards at once (e.g. DiskThresholdDecider)
5064
private static final AllocationDeciders ALLOCATION_DECIDERS = new AllocationDeciders(Arrays.asList(
5165
new FilterAllocationDecider(Settings.EMPTY, new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)),
66+
new DataTierAllocationDecider(new ClusterSettings(Settings.EMPTY, ALL_CLUSTER_SETTINGS)),
5267
new NodeVersionAllocationDecider()
5368
));
5469

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.ilm;
8+
9+
import org.elasticsearch.action.admin.indices.alias.Alias;
10+
import org.elasticsearch.action.admin.indices.template.put.PutComposableIndexTemplateAction;
11+
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
12+
import org.elasticsearch.cluster.metadata.IndexMetadata;
13+
import org.elasticsearch.cluster.metadata.Template;
14+
import org.elasticsearch.common.Strings;
15+
import org.elasticsearch.common.settings.Settings;
16+
import org.elasticsearch.common.unit.TimeValue;
17+
import org.elasticsearch.index.mapper.MapperService;
18+
import org.elasticsearch.plugins.Plugin;
19+
import org.elasticsearch.test.ESIntegTestCase;
20+
import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider;
21+
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
22+
import org.elasticsearch.xpack.core.XPackSettings;
23+
import org.elasticsearch.xpack.core.ilm.ExplainLifecycleRequest;
24+
import org.elasticsearch.xpack.core.ilm.ExplainLifecycleResponse;
25+
import org.elasticsearch.xpack.core.ilm.IndexLifecycleExplainResponse;
26+
import org.elasticsearch.xpack.core.ilm.LifecyclePolicy;
27+
import org.elasticsearch.xpack.core.ilm.LifecycleSettings;
28+
import org.elasticsearch.xpack.core.ilm.Phase;
29+
import org.elasticsearch.xpack.core.ilm.RolloverAction;
30+
import org.elasticsearch.xpack.core.ilm.ShrinkAction;
31+
import org.elasticsearch.xpack.core.ilm.action.ExplainLifecycleAction;
32+
import org.elasticsearch.xpack.core.ilm.action.PutLifecycleAction;
33+
34+
import java.util.Arrays;
35+
import java.util.Collection;
36+
import java.util.Collections;
37+
import java.util.HashMap;
38+
import java.util.Map;
39+
import java.util.concurrent.TimeUnit;
40+
41+
import static org.hamcrest.Matchers.equalTo;
42+
43+
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 0, numClientNodes = 0)
44+
public class ILMMultiNodeIT extends ESIntegTestCase {
45+
private static final String index = "myindex";
46+
47+
@Override
48+
protected Collection<Class<? extends Plugin>> nodePlugins() {
49+
return Arrays.asList(LocalStateCompositeXPackPlugin.class, IndexLifecycle.class);
50+
}
51+
52+
@Override
53+
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
54+
return nodePlugins();
55+
}
56+
57+
@Override
58+
protected Settings nodeSettings(int nodeOrdinal) {
59+
Settings.Builder settings = Settings.builder().put(super.nodeSettings(nodeOrdinal));
60+
settings.put(XPackSettings.MACHINE_LEARNING_ENABLED.getKey(), false);
61+
settings.put(XPackSettings.SECURITY_ENABLED.getKey(), false);
62+
settings.put(XPackSettings.WATCHER_ENABLED.getKey(), false);
63+
settings.put(XPackSettings.GRAPH_ENABLED.getKey(), false);
64+
settings.put(LifecycleSettings.LIFECYCLE_POLL_INTERVAL, "1s");
65+
66+
// This is necessary to prevent ILM and SLM installing a lifecycle policy, these tests assume a blank slate
67+
settings.put(LifecycleSettings.LIFECYCLE_HISTORY_INDEX_ENABLED, false);
68+
settings.put(LifecycleSettings.SLM_HISTORY_INDEX_ENABLED_SETTING.getKey(), false);
69+
return settings.build();
70+
}
71+
72+
@Override
73+
protected boolean ignoreExternalCluster() {
74+
return true;
75+
}
76+
77+
@Override
78+
protected Settings transportClientSettings() {
79+
Settings.Builder settings = Settings.builder().put(super.transportClientSettings());
80+
settings.put(XPackSettings.MACHINE_LEARNING_ENABLED.getKey(), false);
81+
settings.put(XPackSettings.SECURITY_ENABLED.getKey(), false);
82+
settings.put(XPackSettings.WATCHER_ENABLED.getKey(), false);
83+
settings.put(XPackSettings.GRAPH_ENABLED.getKey(), false);
84+
return settings.build();
85+
}
86+
87+
public void testShrinkOnTiers() throws Exception {
88+
startHotOnlyNode();
89+
startWarmOnlyNode();
90+
ensureGreen();
91+
92+
RolloverAction rolloverAction = new RolloverAction(null, null, 1L);
93+
Phase hotPhase = new Phase("hot", TimeValue.ZERO, Collections.singletonMap(rolloverAction.getWriteableName(), rolloverAction));
94+
ShrinkAction shrinkAction = new ShrinkAction(1);
95+
Phase warmPhase = new Phase("warm", TimeValue.ZERO, Collections.singletonMap(shrinkAction.getWriteableName(), shrinkAction));
96+
Map<String, Phase> phases = new HashMap<>();
97+
phases.put(hotPhase.getName(), hotPhase);
98+
phases.put(warmPhase.getName(), warmPhase);
99+
LifecyclePolicy lifecyclePolicy = new LifecyclePolicy("shrink-policy", phases);
100+
client().execute(PutLifecycleAction.INSTANCE, new PutLifecycleAction.Request(lifecyclePolicy)).get();
101+
102+
Template t = new Template(Settings.builder()
103+
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 2)
104+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
105+
.put(LifecycleSettings.LIFECYCLE_NAME, "shrink-policy")
106+
.put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, "shrink-alias")
107+
.put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, "data_hot")
108+
.build(), null, null);
109+
110+
ComposableIndexTemplate template = new ComposableIndexTemplate(
111+
Collections.singletonList(index + "*"),
112+
t,
113+
null,
114+
null,
115+
null,
116+
null
117+
);
118+
client().execute(
119+
PutComposableIndexTemplateAction.INSTANCE,
120+
new PutComposableIndexTemplateAction.Request("template").indexTemplate(template)
121+
).actionGet();
122+
client().admin().indices().prepareCreate(index + "-000001")
123+
.addAlias(new Alias("shrink-alias").writeIndex(true)).get();
124+
client().prepareIndex(index + "-000001", MapperService.SINGLE_MAPPING_NAME)
125+
.setCreate(true).setId("1").setSource("@timestamp", "2020-09-09").get();
126+
127+
assertBusy(() -> {
128+
String name = "shrink-" + index + "-000001";
129+
ExplainLifecycleResponse explain =
130+
client().execute(ExplainLifecycleAction.INSTANCE, new ExplainLifecycleRequest().indices("*")).get();
131+
logger.info("--> explain: {}", Strings.toString(explain));
132+
133+
IndexLifecycleExplainResponse indexResp = explain.getIndexResponses().get(name);
134+
assertNotNull(indexResp);
135+
assertThat(indexResp.getPhase(), equalTo("warm"));
136+
assertThat(indexResp.getStep(), equalTo("complete"));
137+
}, 60, TimeUnit.SECONDS);
138+
}
139+
140+
public void startHotOnlyNode() {
141+
Settings nodeSettings = Settings.builder().putList("node.roles", Arrays.asList("master", "data_hot", "ingest")).build();
142+
internalCluster().startNode(nodeSettings);
143+
}
144+
145+
public void startWarmOnlyNode() {
146+
Settings nodeSettings = Settings.builder().putList("node.roles", Arrays.asList("master", "data_warm", "ingest")).build();
147+
internalCluster().startNode(nodeSettings);
148+
}
149+
}

0 commit comments

Comments
 (0)