Add user-defined cluster metadata (#33325)
Adds a place for users to store cluster-wide data they wish to associate with the cluster via the Cluster Settings API. This is strictly for user-defined data, Elasticsearch makes no other other use of these settings.
This commit is contained in:
parent
48790b0aad
commit
cfd3fa72ed
|
@ -22,6 +22,27 @@ user with access to the <<cluster-update-settings,cluster-update-settings>>
|
||||||
API can make the cluster read-write again.
|
API can make the cluster read-write again.
|
||||||
|
|
||||||
|
|
||||||
|
[[user-defined-data]]
|
||||||
|
==== User Defined Cluster Metadata
|
||||||
|
|
||||||
|
User-defined metadata can be stored and retrieved using the Cluster Settings API.
|
||||||
|
This can be used to store arbitrary, infrequently-changing data about the cluster
|
||||||
|
without the need to create an index to store it. This data may be stored using
|
||||||
|
any key prefixed with `cluster.metadata.`. For example, to store the email
|
||||||
|
address of the administrator of a cluster under the key `cluster.metadata.administrator`,
|
||||||
|
issue this request:
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
-------------------------------
|
||||||
|
PUT /_cluster/settings
|
||||||
|
{
|
||||||
|
"persistent": {
|
||||||
|
"cluster.metadata.administrator": "sysadmin@example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-------------------------------
|
||||||
|
// CONSOLE
|
||||||
|
|
||||||
[[cluster-max-tombstones]]
|
[[cluster-max-tombstones]]
|
||||||
==== Index Tombstones
|
==== Index Tombstones
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,9 @@ public class ClusterService extends AbstractLifecycleComponent {
|
||||||
Setting.positiveTimeSetting("cluster.service.slow_task_logging_threshold", TimeValue.timeValueSeconds(30),
|
Setting.positiveTimeSetting("cluster.service.slow_task_logging_threshold", TimeValue.timeValueSeconds(30),
|
||||||
Property.Dynamic, Property.NodeScope);
|
Property.Dynamic, Property.NodeScope);
|
||||||
|
|
||||||
|
public static final org.elasticsearch.common.settings.Setting.AffixSetting<String> USER_DEFINED_META_DATA =
|
||||||
|
Setting.prefixKeySetting("cluster.metadata.", (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope));
|
||||||
|
|
||||||
private final ClusterName clusterName;
|
private final ClusterName clusterName;
|
||||||
|
|
||||||
private final OperationRouting operationRouting;
|
private final OperationRouting operationRouting;
|
||||||
|
@ -67,6 +70,8 @@ public class ClusterService extends AbstractLifecycleComponent {
|
||||||
this.clusterName = ClusterName.CLUSTER_NAME_SETTING.get(settings);
|
this.clusterName = ClusterName.CLUSTER_NAME_SETTING.get(settings);
|
||||||
this.clusterSettings.addSettingsUpdateConsumer(CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING,
|
this.clusterSettings.addSettingsUpdateConsumer(CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING,
|
||||||
this::setSlowTaskLoggingThreshold);
|
this::setSlowTaskLoggingThreshold);
|
||||||
|
// Add a no-op update consumer so changes are logged
|
||||||
|
this.clusterSettings.addAffixUpdateConsumer(USER_DEFINED_META_DATA, (first, second) -> {}, (first, second) -> {});
|
||||||
this.clusterApplierService = new ClusterApplierService(settings, clusterSettings, threadPool);
|
this.clusterApplierService = new ClusterApplierService(settings, clusterSettings, threadPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,7 @@ public final class ClusterSettings extends AbstractScopedSettings {
|
||||||
HierarchyCircuitBreakerService.ACCOUNTING_CIRCUIT_BREAKER_OVERHEAD_SETTING,
|
HierarchyCircuitBreakerService.ACCOUNTING_CIRCUIT_BREAKER_OVERHEAD_SETTING,
|
||||||
IndexModule.NODE_STORE_ALLOW_MMAPFS,
|
IndexModule.NODE_STORE_ALLOW_MMAPFS,
|
||||||
ClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING,
|
ClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING,
|
||||||
|
ClusterService.USER_DEFINED_META_DATA,
|
||||||
SearchService.DEFAULT_SEARCH_TIMEOUT_SETTING,
|
SearchService.DEFAULT_SEARCH_TIMEOUT_SETTING,
|
||||||
SearchService.DEFAULT_ALLOW_PARTIAL_SEARCH_RESULTS,
|
SearchService.DEFAULT_ALLOW_PARTIAL_SEARCH_RESULTS,
|
||||||
ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES_SETTING,
|
ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES_SETTING,
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.elasticsearch.cluster.settings;
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequestBuilder;
|
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequestBuilder;
|
||||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
|
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
|
||||||
|
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
|
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
|
||||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||||
|
@ -380,4 +381,34 @@ public class ClusterSettingsIT extends ESIntegTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testUserMetadata() {
|
||||||
|
String key = "cluster.metadata." + randomAlphaOfLengthBetween(5, 20);
|
||||||
|
String value = randomRealisticUnicodeOfCodepointLengthBetween(5, 50);
|
||||||
|
String updatedValue = randomRealisticUnicodeOfCodepointLengthBetween(5, 50);
|
||||||
|
logger.info("Attempting to store [{}]: [{}], then update to [{}]", key, value, updatedValue);
|
||||||
|
|
||||||
|
final Settings settings = Settings.builder().put(key, value).build();
|
||||||
|
final Settings updatedSettings = Settings.builder().put(key, updatedValue).build();
|
||||||
|
if (randomBoolean()) {
|
||||||
|
logger.info("Using persistent settings");
|
||||||
|
|
||||||
|
client().admin().cluster().prepareUpdateSettings().setPersistentSettings(settings).execute().actionGet();
|
||||||
|
ClusterStateResponse state = client().admin().cluster().prepareState().execute().actionGet();
|
||||||
|
assertEquals(value, state.getState().getMetaData().persistentSettings().get(key));
|
||||||
|
|
||||||
|
client().admin().cluster().prepareUpdateSettings().setPersistentSettings(updatedSettings).execute().actionGet();
|
||||||
|
ClusterStateResponse updatedState = client().admin().cluster().prepareState().execute().actionGet();
|
||||||
|
assertEquals(updatedValue, updatedState.getState().getMetaData().persistentSettings().get(key));
|
||||||
|
} else {
|
||||||
|
logger.info("Using transient settings");
|
||||||
|
client().admin().cluster().prepareUpdateSettings().setTransientSettings(settings).execute().actionGet();
|
||||||
|
ClusterStateResponse state = client().admin().cluster().prepareState().execute().actionGet();
|
||||||
|
assertEquals(value, state.getState().getMetaData().transientSettings().get(key));
|
||||||
|
|
||||||
|
client().admin().cluster().prepareUpdateSettings().setTransientSettings(updatedSettings).execute().actionGet();
|
||||||
|
ClusterStateResponse updatedState = client().admin().cluster().prepareState().execute().actionGet();
|
||||||
|
assertEquals(updatedValue, updatedState.getState().getMetaData().transientSettings().get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue