Skip to content

Commit efe71fd

Browse files
author
Pablo Alcantar Morales
authored
Uses ClusterSettings instead of Node Settings in HealthMetadataService (#96843) (#96870)
When building the first version of `HealthMetadata` object, we were using the `Settings` object, which has the Node's settings, what does not seem to be propagated to the Node, hence we always used the default values of the settings. This made that every time a new master was selected, the initial `HealthMetadata` was built with the default values instead of the settings configured by the customer.
1 parent c7eeb9d commit efe71fd

File tree

4 files changed

+92
-41
lines changed

4 files changed

+92
-41
lines changed

docs/changelog/96843.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 96843
2+
summary: Uses `ClusterSettings` instead of Node `Settings` in `HealthMetadataService`
3+
area: Health
4+
type: bug
5+
issues:
6+
- 96219

server/src/internalClusterTest/java/org/elasticsearch/health/HealthMetadataServiceIT.java

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
1212
import org.elasticsearch.cluster.node.DiscoveryNodeRole;
13-
import org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings;
1413
import org.elasticsearch.common.settings.Settings;
1514
import org.elasticsearch.common.unit.ByteSizeValue;
1615
import org.elasticsearch.health.metadata.HealthMetadata;
@@ -22,12 +21,15 @@
2221
import java.util.Map;
2322
import java.util.Set;
2423

24+
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_MAX_HEADROOM_SETTING;
25+
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_WATERMARK_SETTING;
2526
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_MAX_HEADROOM_SETTING;
2627
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING;
2728
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING;
2829
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING;
2930
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_MAX_HEADROOM_SETTING;
3031
import static org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING;
32+
import static org.elasticsearch.common.settings.Settings.EMPTY;
3133
import static org.elasticsearch.indices.ShardLimitValidator.SETTING_CLUSTER_MAX_SHARDS_PER_NODE;
3234
import static org.elasticsearch.indices.ShardLimitValidator.SETTING_CLUSTER_MAX_SHARDS_PER_NODE_FROZEN;
3335
import static org.elasticsearch.test.NodeRoles.onlyRoles;
@@ -52,11 +54,10 @@ public void testEachMasterPublishesTheirThresholds() throws Exception {
5254
for (int i = 0; i < numberOfNodes; i++) {
5355
ByteSizeValue randomBytes = ByteSizeValue.ofBytes(randomLongBetween(6, 19));
5456
String customWatermark = percentageMode ? randomIntBetween(86, 94) + "%" : randomBytes.toString();
55-
ByteSizeValue customMaxHeadroom = percentageMode ? randomBytes : ByteSizeValue.MINUS_ONE;
5657
var customShardLimits = new HealthMetadata.ShardLimits(randomIntBetween(1, 1000), randomIntBetween(1001, 2000));
57-
String nodeName = startNode(internalCluster, customWatermark, customMaxHeadroom.toString(), customShardLimits);
58+
String nodeName = startNode(internalCluster, customWatermark, randomBytes.toString(), customShardLimits);
5859
watermarkByNode.put(nodeName, customWatermark);
59-
maxHeadroomByNode.put(nodeName, customMaxHeadroom);
60+
maxHeadroomByNode.put(nodeName, randomBytes);
6061
shardLimitsPerNode.put(nodeName, customShardLimits);
6162
}
6263
ensureStableCluster(numberOfNodes);
@@ -66,7 +67,16 @@ public void testEachMasterPublishesTheirThresholds() throws Exception {
6667
var healthMetadata = HealthMetadata.getFromClusterState(internalCluster.clusterService().state());
6768
var diskMetadata = healthMetadata.getDiskMetadata();
6869
assertThat(diskMetadata.describeHighWatermark(), equalTo(watermarkByNode.get(electedMaster)));
69-
assertThat(diskMetadata.highMaxHeadroom(), equalTo(maxHeadroomByNode.get(electedMaster)));
70+
// The value of the setting `cluster.routing.allocation.disk.watermark.high.max_headroom` depends upon the existence of
71+
// `cluster.routing.allocation.disk.watermark.high`. Check {@link CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING}
72+
assertThat(
73+
diskMetadata.highMaxHeadroom(),
74+
equalTo(
75+
percentageMode
76+
? maxHeadroomByNode.get(electedMaster)
77+
: CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.getDefault(EMPTY)
78+
)
79+
);
7080

7181
var shardLimitsMetadata = healthMetadata.getShardLimitsMetadata();
7282
assertEquals(shardLimitsMetadata, shardLimitsPerNode.get(electedMaster));
@@ -80,7 +90,18 @@ public void testEachMasterPublishesTheirThresholds() throws Exception {
8090
var healthMetadata = HealthMetadata.getFromClusterState(internalCluster.clusterService().state());
8191
var diskMetadata = healthMetadata.getDiskMetadata();
8292
assertThat(diskMetadata.describeHighWatermark(), equalTo(watermarkByNode.get(electedMaster)));
83-
assertThat(diskMetadata.highMaxHeadroom(), equalTo(maxHeadroomByNode.get(electedMaster)));
93+
94+
// The value of the setting `cluster.routing.allocation.disk.watermark.high.max_headroom` depends upon the existence of
95+
// `cluster.routing.allocation.disk.watermark.high`.
96+
// Check {@link DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING}
97+
assertThat(
98+
diskMetadata.highMaxHeadroom(),
99+
equalTo(
100+
percentageMode
101+
? maxHeadroomByNode.get(electedMaster)
102+
: CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.getDefault(EMPTY)
103+
)
104+
);
84105

85106
var shardLimitsMetadata = healthMetadata.getShardLimitsMetadata();
86107
assertEquals(shardLimitsMetadata, shardLimitsPerNode.get(electedMaster));
@@ -93,7 +114,7 @@ public void testWatermarkSettingUpdate() throws Exception {
93114
int numberOfNodes = 3;
94115
ByteSizeValue randomBytes = ByteSizeValue.ofBytes(randomLongBetween(6, 19));
95116
String initialWatermark = percentageMode ? randomIntBetween(86, 94) + "%" : randomBytes.toString();
96-
ByteSizeValue initialMaxHeadroom = percentageMode ? randomBytes : ByteSizeValue.MINUS_ONE;
117+
ByteSizeValue initialMaxHeadroom = randomBytes;
97118
HealthMetadata.ShardLimits initialShardLimits = new HealthMetadata.ShardLimits(
98119
randomIntBetween(1, 1000),
99120
randomIntBetween(1001, 2000)
@@ -107,7 +128,7 @@ public void testWatermarkSettingUpdate() throws Exception {
107128
ByteSizeValue updatedLowMaxHeadroom = percentageMode ? randomBytes : ByteSizeValue.MINUS_ONE;
108129
randomBytes = ByteSizeValue.ofBytes(randomLongBetween(50, 100));
109130
String updatedHighWatermark = percentageMode ? randomIntBetween(60, 90) + "%" : randomBytes.toString();
110-
ByteSizeValue updatedHighMaxHeadroom = percentageMode ? randomBytes : ByteSizeValue.MINUS_ONE;
131+
ByteSizeValue updatedHighMaxHeadroom = randomBytes;
111132
randomBytes = ByteSizeValue.ofBytes(randomLongBetween(5, 10));
112133
String updatedFloodStageWatermark = percentageMode ? randomIntBetween(91, 95) + "%" : randomBytes.toString();
113134
ByteSizeValue updatedFloodStageMaxHeadroom = percentageMode ? randomBytes : ByteSizeValue.MINUS_ONE;
@@ -121,7 +142,16 @@ public void testWatermarkSettingUpdate() throws Exception {
121142
var healthMetadata = HealthMetadata.getFromClusterState(internalCluster.clusterService().state());
122143
var diskMetadata = healthMetadata.getDiskMetadata();
123144
assertThat(diskMetadata.describeHighWatermark(), equalTo(initialWatermark));
124-
assertThat(diskMetadata.highMaxHeadroom(), equalTo(initialMaxHeadroom));
145+
146+
// The value of the setting `cluster.routing.allocation.disk.watermark.high.max_headroom` depends upon the existence of
147+
// `cluster.routing.allocation.disk.watermark.high`.
148+
// Check {@link DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING}
149+
assertThat(
150+
diskMetadata.highMaxHeadroom(),
151+
equalTo(
152+
percentageMode ? initialMaxHeadroom : CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.getDefault(EMPTY)
153+
)
154+
);
125155

126156
var shardLimitsMetadata = healthMetadata.getShardLimitsMetadata();
127157
assertEquals(shardLimitsMetadata, initialShardLimits);
@@ -147,9 +177,31 @@ public void testWatermarkSettingUpdate() throws Exception {
147177
var healthMetadata = HealthMetadata.getFromClusterState(internalCluster.clusterService().state());
148178
var diskMetadata = healthMetadata.getDiskMetadata();
149179
assertThat(diskMetadata.describeHighWatermark(), equalTo(updatedHighWatermark));
150-
assertThat(diskMetadata.highMaxHeadroom(), equalTo(updatedHighMaxHeadroom));
180+
181+
// The value of the setting `cluster.routing.allocation.disk.watermark.high.max_headroom` depends upon the existence of
182+
// `cluster.routing.allocation.disk.watermark.high`.
183+
// Check {@link DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING}
184+
assertThat(
185+
diskMetadata.highMaxHeadroom(),
186+
equalTo(
187+
percentageMode
188+
? updatedHighMaxHeadroom
189+
: CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.getDefault(EMPTY)
190+
)
191+
);
151192
assertThat(diskMetadata.describeFloodStageWatermark(), equalTo(updatedFloodStageWatermark));
152-
assertThat(diskMetadata.floodStageMaxHeadroom(), equalTo(updatedFloodStageMaxHeadroom));
193+
194+
// The value of the setting `cluster.routing.allocation.disk.watermark.flood_stage.max_headroom` depends upon the existence
195+
// of `cluster.routing.allocation.disk.watermark.flood_stage`.
196+
// Check{@link DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_MAX_HEADROOM_SETTING}
197+
assertThat(
198+
diskMetadata.floodStageMaxHeadroom(),
199+
equalTo(
200+
percentageMode
201+
? updatedFloodStageMaxHeadroom
202+
: CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_MAX_HEADROOM_SETTING.getDefault(EMPTY)
203+
)
204+
);
153205

154206
var shardLimitsMetadata = healthMetadata.getShardLimitsMetadata();
155207
assertEquals(shardLimitsMetadata, updatedShardLimits);
@@ -175,21 +227,17 @@ private String startNode(
175227

176228
private Settings createWatermarkSettings(String highWatermark, String highMaxHeadroom) {
177229
// We define both thresholds to avoid inconsistencies over the type of the thresholds
178-
Settings.Builder settings = Settings.builder()
230+
var settings = Settings.builder()
179231
.put(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_WATERMARK_SETTING.getKey(), percentageMode ? "85%" : "20b")
180232
.put(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.getKey(), highWatermark)
181233
.put(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.getKey(), percentageMode ? "95%" : "1b")
182-
.put(
183-
DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_WATERMARK_SETTING.getKey(),
184-
percentageMode ? "95%" : "5b"
185-
);
234+
.put(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_WATERMARK_SETTING.getKey(), percentageMode ? "95%" : "5b");
235+
186236
if (percentageMode) {
187-
settings = settings.put(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_MAX_HEADROOM_SETTING.getKey(), "20b")
237+
settings.put(CLUSTER_ROUTING_ALLOCATION_LOW_DISK_MAX_HEADROOM_SETTING.getKey(), "20b")
188238
.put(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_MAX_HEADROOM_SETTING.getKey(), "1b")
189-
.put(DiskThresholdSettings.CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_MAX_HEADROOM_SETTING.getKey(), "5b");
190-
if (highMaxHeadroom.equals("-1") == false) {
191-
settings = settings.put(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.getKey(), highMaxHeadroom);
192-
}
239+
.put(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_MAX_HEADROOM_SETTING.getKey(), "5b")
240+
.put(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.getKey(), highMaxHeadroom);
193241
}
194242
return settings.build();
195243
}

server/src/main/java/org/elasticsearch/health/metadata/HealthMetadataService.java

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.elasticsearch.common.Priority;
2525
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
2626
import org.elasticsearch.common.settings.ClusterSettings;
27-
import org.elasticsearch.common.settings.Settings;
2827
import org.elasticsearch.core.Nullable;
2928
import org.elasticsearch.core.Tuple;
3029

@@ -50,7 +49,6 @@ public class HealthMetadataService {
5049

5150
private final ClusterService clusterService;
5251
private final ClusterStateListener clusterStateListener;
53-
private final Settings settings;
5452
private final MasterServiceTaskQueue<UpsertHealthMetadataTask> taskQueue;
5553
private volatile boolean enabled;
5654

@@ -61,20 +59,19 @@ public class HealthMetadataService {
6159
// us from checking the cluster state before the cluster state is initialized
6260
private volatile boolean isMaster = false;
6361

64-
private HealthMetadataService(ClusterService clusterService, Settings settings) {
62+
private HealthMetadataService(ClusterService clusterService) {
6563
this.clusterService = clusterService;
66-
this.settings = settings;
6764
this.clusterStateListener = this::updateOnClusterStateChange;
68-
this.enabled = ENABLED_SETTING.get(settings);
65+
this.enabled = clusterService.getClusterSettings().get(ENABLED_SETTING);
6966
this.taskQueue = clusterService.createTaskQueue(
7067
"health metadata service",
7168
Priority.NORMAL,
7269
new UpsertHealthMetadataTask.Executor()
7370
);
7471
}
7572

76-
public static HealthMetadataService create(ClusterService clusterService, Settings settings) {
77-
HealthMetadataService healthMetadataService = new HealthMetadataService(clusterService, settings);
73+
public static HealthMetadataService create(ClusterService clusterService) {
74+
HealthMetadataService healthMetadataService = new HealthMetadataService(clusterService);
7875
healthMetadataService.registerListeners();
7976
return healthMetadataService;
8077
}
@@ -84,7 +81,7 @@ private void registerListeners() {
8481
this.clusterService.addListener(clusterStateListener);
8582
}
8683

87-
ClusterSettings clusterSettings = clusterService.getClusterSettings();
84+
var clusterSettings = clusterService.getClusterSettings();
8885
Stream.of(
8986
CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING,
9087
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING,
@@ -159,7 +156,7 @@ private void updateOnSettingsUpdated(UpsertHealthMetadataTask task) {
159156
}
160157

161158
private void resetHealthMetadata(String source) {
162-
taskQueue.submitTask(source, new InsertHealthMetadata(settings), null);
159+
taskQueue.submitTask(source, new InsertHealthMetadata(clusterService.getClusterSettings()), null);
163160
}
164161

165162
public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
@@ -290,26 +287,26 @@ private HealthMetadata.ShardLimits shardLimitsMetadataFrom(HealthMetadata.ShardL
290287
*/
291288
static class InsertHealthMetadata extends UpsertHealthMetadataTask {
292289

293-
private final Settings settings;
290+
private final ClusterSettings settings;
294291

295-
InsertHealthMetadata(Settings settings) {
292+
InsertHealthMetadata(ClusterSettings settings) {
296293
this.settings = settings;
297294
}
298295

299296
@Override
300297
HealthMetadata doExecute(HealthMetadata initialHealthMetadata) {
301298
return new HealthMetadata(
302299
new HealthMetadata.Disk(
303-
CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING.get(settings),
304-
CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING.get(settings),
305-
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING.get(settings),
306-
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_MAX_HEADROOM_SETTING.get(settings),
307-
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_WATERMARK_SETTING.get(settings),
308-
CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_MAX_HEADROOM_SETTING.get(settings)
300+
settings.get(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_WATERMARK_SETTING),
301+
settings.get(CLUSTER_ROUTING_ALLOCATION_HIGH_DISK_MAX_HEADROOM_SETTING),
302+
settings.get(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_WATERMARK_SETTING),
303+
settings.get(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_MAX_HEADROOM_SETTING),
304+
settings.get(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_WATERMARK_SETTING),
305+
settings.get(CLUSTER_ROUTING_ALLOCATION_DISK_FLOOD_STAGE_FROZEN_MAX_HEADROOM_SETTING)
309306
),
310307
new HealthMetadata.ShardLimits(
311-
SETTING_CLUSTER_MAX_SHARDS_PER_NODE.get(settings),
312-
SETTING_CLUSTER_MAX_SHARDS_PER_NODE_FROZEN.get(settings)
308+
settings.get(SETTING_CLUSTER_MAX_SHARDS_PER_NODE),
309+
settings.get(SETTING_CLUSTER_MAX_SHARDS_PER_NODE_FROZEN)
313310
)
314311
);
315312
}

server/src/main/java/org/elasticsearch/node/Node.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ protected Node(
10091009
threadPool,
10101010
systemIndices
10111011
);
1012-
HealthMetadataService healthMetadataService = HealthMetadataService.create(clusterService, settings);
1012+
HealthMetadataService healthMetadataService = HealthMetadataService.create(clusterService);
10131013
LocalHealthMonitor localHealthMonitor = LocalHealthMonitor.create(settings, clusterService, nodeService, threadPool, client);
10141014
HealthInfoCache nodeHealthOverview = HealthInfoCache.create(clusterService);
10151015
HealthApiStats healthApiStats = new HealthApiStats();

0 commit comments

Comments
 (0)