Skip to content

Commit a8c3699

Browse files
Set initial_cluster_manager_nodes only on cluster_manager nodes; Add opensearch-discovery scope only on cluster_manager nodes
1 parent 4c69fd1 commit a8c3699

4 files changed

Lines changed: 78 additions & 38 deletions

File tree

rust/operator-binary/src/controller/build/node_config.rs

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ impl NodeConfig {
258258
/// The environment variables should only contain node-specific configuration options.
259259
/// Cluster-wide options should be added to the configuration file.
260260
pub fn environment_variables(&self) -> EnvVarSet {
261-
EnvVarSet::new()
261+
let mut env_vars = EnvVarSet::new()
262262
// Set the OpenSearch node name to the Pod name.
263263
// The node name is used e.g. for INITIAL_CLUSTER_MANAGER_NODES.
264264
.with_field_path(
@@ -269,10 +269,6 @@ impl NodeConfig {
269269
&EnvVarName::from_str_unsafe(CONFIG_OPTION_DISCOVERY_SEED_HOSTS),
270270
&self.discovery_service_name,
271271
)
272-
.with_value(
273-
&EnvVarName::from_str_unsafe(CONFIG_OPTION_INITIAL_CLUSTER_MANAGER_NODES),
274-
self.initial_cluster_manager_nodes(),
275-
)
276272
.with_value(
277273
&EnvVarName::from_str_unsafe(CONFIG_OPTION_NODE_ROLES),
278274
self.role_group_config
@@ -284,8 +280,16 @@ impl NodeConfig {
284280
// Node roles cannot contain commas, therefore creating a comma-separated list
285281
// is safe.
286282
.join(","),
287-
)
288-
.merge(self.role_group_config.env_overrides.clone())
283+
);
284+
285+
if let Some(initial_cluster_manager_nodes) = self.initial_cluster_manager_nodes() {
286+
env_vars = env_vars.with_value(
287+
&EnvVarName::from_str_unsafe(CONFIG_OPTION_INITIAL_CLUSTER_MANAGER_NODES),
288+
initial_cluster_manager_nodes,
289+
);
290+
}
291+
292+
env_vars.merge(self.role_group_config.env_overrides.clone())
289293
}
290294

291295
fn to_yaml(kv: serde_json::Map<String, Value>) -> String {
@@ -311,33 +315,70 @@ impl NodeConfig {
311315
}
312316
}
313317

314-
/// Configuration for `cluster.initial_cluster_manager_nodes` which replaces
315-
/// `cluster.initial_master_nodes`, see
316-
/// <https://github.com/opensearch-project/OpenSearch/blob/3.0.0/server/src/main/java/org/opensearch/cluster/coordination/ClusterBootstrapService.java#L79-L93>.
318+
/// Configuration for `cluster.initial_cluster_manager_nodes`
319+
///
320+
/// Returns the node names of the initial cluster-manager nodes if
321+
/// * this is a multi-node cluster and
322+
/// * this node has the cluster-manager node role.
323+
///
324+
/// Please read the following sections for an explanation of these restrictions.
325+
///
326+
/// This configuration setting replaces the setting `cluster.initial_master_nodes`, see
327+
/// <https://github.com/opensearch-project/OpenSearch/blob/3.1.0/server/src/main/java/org/opensearch/cluster/coordination/ClusterBootstrapService.java#L79-L93>.
317328
///
318-
/// According to
319-
/// <https://docs.opensearch.org/docs/3.0/install-and-configure/configuring-opensearch/discovery-gateway-settings/>,
320-
/// it contains "a list of cluster-manager-eligible nodes used to bootstrap the cluster."
329+
/// This setting is required on nodes with the cluster-manager node role on a multi-node
330+
/// cluster. Otherwise the bootstrapping of the cluster fails and all pods report:
331+
/// > Wait for cluster to be available ...
321332
///
322-
/// However, the documentation for Elasticsearch is more detailed and contains the following
323-
/// notes (see <https://www.elastic.co/guide/en/elasticsearch/reference/9.0/modules-discovery-settings.html>):
333+
/// This setting must not be set on a single-node cluster, because otherwise the following
334+
/// error is thrown:
335+
/// > setting [cluster.initial_cluster_manager_nodes] is not allowed when [discovery.type] is set to [single-node]
336+
///
337+
/// see <https://github.com/opensearch-project/OpenSearch/blob/3.1.0/server/src/main/java/org/opensearch/cluster/coordination/ClusterBootstrapService.java#L126-L136>
338+
///
339+
/// This setting does not seem to have an effect on nodes without the cluster-manager node
340+
/// role. However, as it is recommended (see the Elasticsearch documentation below) to not set
341+
/// it on master-ineligible nodes, it is not set.
342+
///
343+
/// This setting seems to be ignored when the cluster has already formed. It is recommended in
344+
/// the Elasticsearch documentation to remove it once the cluster has formed, but as it is hard
345+
/// to determine if the bootstrapping was successfully completed, this setting is still set.
346+
/// Adding a new cluster-manager node and updating this setting also seems to be okay.
347+
///
348+
/// # OpenSearch documentation
349+
///
350+
/// > This setting is required when bootstrapping a cluster for the first time and should
351+
/// > contain the node names (as defined by `node.name`) of the initial cluster-manager-eligible
352+
/// > nodes. This list should be empty for nodes joining an existing cluster.
353+
///
354+
/// see <https://docs.opensearch.org/3.3/install-and-configure/configuring-opensearch/discovery-gateway-settings/#static-discovery-settings>
355+
///
356+
/// # Elasticsearch documentation
357+
///
358+
/// The documentation for Elasticsearch is more detailed and contains the following
359+
/// notes:
324360
/// * Remove this setting once the cluster has formed, and never set it again for this cluster.
325361
/// * Do not configure this setting on master-ineligible nodes.
326362
/// * Do not configure this setting on nodes joining an existing cluster.
327363
/// * Do not configure this setting on nodes which are restarting.
328364
/// * Do not configure this setting when performing a full-cluster restart.
329365
///
330-
/// The OpenSearch Helm chart only sets master nodes but does not handle the other cases (see
331-
/// <https://github.com/opensearch-project/helm-charts/blob/opensearch-3.0.0/charts/opensearch/templates/statefulset.yaml#L414-L415>),
332-
/// so they are also ignored here for the moment.
333-
fn initial_cluster_manager_nodes(&self) -> String {
334-
if !self.cluster.is_single_node()
335-
&& self
366+
/// see <https://www.elastic.co/docs/reference/elasticsearch/configuration-reference/discovery-cluster-formation-settings>
367+
///
368+
/// # Implementation in the OpenSearch Helm chart
369+
///
370+
/// The OpenSearch Helm chart sets this setting on master nodes on multi-node clusters, see
371+
/// see </home/sigi/projects/stackable/workspace/opensearch-operator/target/doc/stackable_opensearch_operator/index.html>.
372+
fn initial_cluster_manager_nodes(&self) -> Option<String> {
373+
if self.cluster.is_single_node()
374+
|| !self
336375
.role_group_config
337376
.config
338377
.node_roles
339378
.contains(&v1alpha1::NodeRole::ClusterManager)
340379
{
380+
None
381+
} else {
341382
let cluster_manager_configs = self
342383
.cluster
343384
.role_group_configs_filtered_by_node_role(&v1alpha1::NodeRole::ClusterManager);
@@ -360,11 +401,7 @@ impl NodeConfig {
360401
);
361402
}
362403
// Pod names cannot contain commas, therefore creating a comma-separated list is safe.
363-
pod_names.join(",")
364-
} else {
365-
// This setting is not allowed on single node cluster, see
366-
// <https://github.com/opensearch-project/OpenSearch/blob/3.0.0/server/src/main/java/org/opensearch/cluster/coordination/ClusterBootstrapService.java#L126-L136>
367-
String::new()
404+
Some(pod_names.join(","))
368405
}
369406
}
370407

@@ -509,7 +546,7 @@ mod tests {
509546
cluster,
510547
role_group_name,
511548
role_group_config,
512-
ServiceName::from_str_unsafe("my-opensearch-cluster-manager"),
549+
ServiceName::from_str_unsafe("my-opensearch-cluster-discovery"),
513550
)
514551
}
515552

@@ -615,7 +652,7 @@ mod tests {
615652
)
616653
.with_value(
617654
&EnvVarName::from_str_unsafe("discovery.seed_hosts"),
618-
"my-opensearch-cluster-manager",
655+
"my-opensearch-cluster-discovery",
619656
)
620657
.with_field_path(
621658
&EnvVarName::from_str_unsafe("node.name"),
@@ -664,11 +701,11 @@ mod tests {
664701
});
665702

666703
assert_eq!(
667-
"".to_owned(),
704+
None,
668705
node_config_single_node.initial_cluster_manager_nodes()
669706
);
670707
assert_eq!(
671-
"my-opensearch-cluster-nodes-default-0,my-opensearch-cluster-nodes-default-1,my-opensearch-cluster-nodes-default-2".to_owned(),
708+
Some("my-opensearch-cluster-nodes-default-0,my-opensearch-cluster-nodes-default-1,my-opensearch-cluster-nodes-default-2".to_owned()),
672709
node_config_multiple_nodes.initial_cluster_manager_nodes()
673710
);
674711
}

rust/operator-binary/src/controller/build/role_group_builder.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ impl<'a> RoleGroupBuilder<'a> {
232232
/// Builds the [`PodTemplateSpec`] for the role-group [`StatefulSet`]
233233
fn build_pod_template(&self) -> PodTemplateSpec {
234234
let mut node_role_labels = Labels::new();
235-
let service_scopes = vec![self.node_config.discovery_service_name.clone()];
236235

237236
for node_role in self.role_group_config.config.node_roles.iter() {
238237
node_role_labels.insert(Self::build_node_role_label(node_role));
@@ -323,6 +322,15 @@ impl<'a> RoleGroupBuilder<'a> {
323322
];
324323

325324
if let Some(tls_http_secret_class_name) = &self.cluster.tls_config.server_secret_class {
325+
let mut service_scopes = vec![];
326+
if self
327+
.role_group_config
328+
.config
329+
.node_roles
330+
.contains(&v1alpha1::NodeRole::ClusterManager)
331+
{
332+
service_scopes.push(self.node_config.discovery_service_name.clone());
333+
}
326334
volumes.push(self.build_tls_volume(
327335
&TLS_SERVER_VOLUME_NAME,
328336
tls_http_secret_class_name,
@@ -1129,10 +1137,6 @@ mod tests {
11291137
"-c"
11301138
],
11311139
"env": [
1132-
{
1133-
"name": "cluster.initial_cluster_manager_nodes",
1134-
"value": ""
1135-
},
11361140
{
11371141
"name": "discovery.seed_hosts",
11381142
"value": "my-opensearch-cluster"

rust/operator-binary/src/framework/macros/attributed_string_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use strum::{EnumDiscriminants, IntoStaticStr};
33

44
/// Maximum length of label values
55
///
6-
/// Duplicates the private constant [`stackable-operator::kvp::label::value::LABEL_VALUE_MAX_LEN`]
6+
/// Duplicates the private constant [`stackable_operator::kvp::LABEL_VALUE_MAX_LEN`]
77
pub const MAX_LABEL_VALUE_LENGTH: usize = 63;
88

99
#[derive(Debug, EnumDiscriminants, Snafu)]

tests/templates/kuttl/smoke/10-assert.yaml.j2

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,6 @@ spec:
446446
value: "true"
447447
- name: OPENSEARCH_HOME
448448
value: {{ test_scenario['values']['opensearch_home'] }}
449-
- name: cluster.initial_cluster_manager_nodes
450449
- name: discovery.seed_hosts
451450
value: opensearch-discovery
452451
- name: node.name
@@ -614,7 +613,7 @@ spec:
614613
secrets.stackable.tech/backend.autotls.cert.lifetime: 1d
615614
secrets.stackable.tech/class: tls
616615
secrets.stackable.tech/format: tls-pem
617-
secrets.stackable.tech/scope: service=opensearch-discovery,listener-volume=listener,pod
616+
secrets.stackable.tech/scope: listener-volume=listener,pod
618617
spec:
619618
accessModes:
620619
- ReadWriteOnce

0 commit comments

Comments
 (0)