Skip to content

Commit f4c3059

Browse files
feat: Publish fully-qualified domain names of the OpenSearch nodes (#100)
1 parent 2f57dec commit f4c3059

File tree

8 files changed

+153
-15
lines changed

8 files changed

+153
-15
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ All notable changes to this project will be documented in this file.
1212
- Support objectOverrides using `.spec.objectOverrides`.
1313
See [objectOverrides concepts page](https://docs.stackable.tech/home/nightly/concepts/overrides/#object-overrides) for details ([#93]).
1414
- Enable the [restart-controller](https://docs.stackable.tech/home/nightly/commons-operator/restarter/), so that the Pods are automatically restarted on config changes ([#97]).
15+
- Configure OpenSearch to publish the fully-qualified domain names of the nodes instead of the IP
16+
addresses, so that TLS certificates can be verified ([#100]).
1517

1618
### Changed
1719

@@ -23,6 +25,7 @@ All notable changes to this project will be documented in this file.
2325
[#91]: https://github.com/stackabletech/opensearch-operator/pull/91
2426
[#93]: https://github.com/stackabletech/opensearch-operator/pull/93
2527
[#97]: https://github.com/stackabletech/opensearch-operator/pull/97
28+
[#100]: https://github.com/stackabletech/opensearch-operator/pull/100
2629

2730
## [25.11.0] - 2025-11-07
2831

rust/operator-binary/src/controller.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use build::build;
1010
use snafu::{ResultExt, Snafu};
1111
use stackable_operator::{
1212
cluster_resources::ClusterResourceApplyStrategy,
13-
commons::{affinity::StackableAffinity, product_image_selection::ResolvedProductImage},
13+
commons::{
14+
affinity::StackableAffinity, networking::DomainName,
15+
product_image_selection::ResolvedProductImage,
16+
},
1417
crd::listener::v1alpha1::Listener,
1518
k8s_openapi::api::{
1619
apps::v1::StatefulSet,
@@ -56,6 +59,7 @@ pub struct ContextNames {
5659
pub product_name: ProductName,
5760
pub operator_name: OperatorName,
5861
pub controller_name: ControllerName,
62+
pub cluster_domain_name: DomainName,
5963
}
6064

6165
/// The controller context
@@ -66,19 +70,22 @@ pub struct Context {
6670

6771
impl Context {
6872
pub fn new(client: stackable_operator::client::Client, operator_name: OperatorName) -> Self {
73+
let cluster_domain_name = client.kubernetes_cluster_info.cluster_domain.clone();
74+
6975
Context {
7076
client,
71-
names: Self::context_names(operator_name),
77+
names: Self::context_names(operator_name, cluster_domain_name),
7278
}
7379
}
7480

75-
fn context_names(operator_name: OperatorName) -> ContextNames {
81+
fn context_names(operator_name: OperatorName, cluster_domain_name: DomainName) -> ContextNames {
7682
ContextNames {
7783
product_name: ProductName::from_str("opensearch")
7884
.expect("should be a valid product name"),
7985
operator_name,
8086
controller_name: ControllerName::from_str("opensearchcluster")
8187
.expect("should be a valid controller name"),
88+
cluster_domain_name,
8289
}
8390
}
8491

@@ -379,7 +386,10 @@ mod tests {
379386
};
380387

381388
use stackable_operator::{
382-
commons::{affinity::StackableAffinity, product_image_selection::ResolvedProductImage},
389+
commons::{
390+
affinity::StackableAffinity, networking::DomainName,
391+
product_image_selection::ResolvedProductImage,
392+
},
383393
k8s_openapi::api::core::v1::PodTemplateSpec,
384394
kvp::LabelValue,
385395
product_logging::spec::AutomaticContainerLogConfig,
@@ -406,7 +416,10 @@ mod tests {
406416
#[test]
407417
fn test_context_names() {
408418
// Test that the function does not panic
409-
Context::context_names(OperatorName::from_str_unsafe("my-operator"));
419+
Context::context_names(
420+
OperatorName::from_str_unsafe("my-operator"),
421+
DomainName::from_str("cluster.local").expect("should be a valid domain name"),
422+
);
410423
}
411424

412425
#[test]

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ mod tests {
6262
};
6363

6464
use stackable_operator::{
65-
commons::{affinity::StackableAffinity, product_image_selection::ResolvedProductImage},
65+
commons::{
66+
affinity::StackableAffinity, networking::DomainName,
67+
product_image_selection::ResolvedProductImage,
68+
},
6669
k8s_openapi::api::core::v1::PodTemplateSpec,
6770
kube::Resource,
6871
kvp::LabelValue,
@@ -158,6 +161,8 @@ mod tests {
158161
product_name: ProductName::from_str_unsafe("opensearch"),
159162
operator_name: OperatorName::from_str_unsafe("opensearch.stackable.tech"),
160163
controller_name: ControllerName::from_str_unsafe("opensearchcluster"),
164+
cluster_domain_name: DomainName::from_str("cluster.local")
165+
.expect("should be a valid domain name"),
161166
}
162167
}
163168

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

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
use std::str::FromStr;
44

55
use serde_json::{Value, json};
6-
use stackable_operator::builder::pod::container::FieldPathEnvVar;
6+
use stackable_operator::{
7+
builder::pod::container::FieldPathEnvVar, commons::networking::DomainName,
8+
};
79

810
use super::ValidatedCluster;
911
use crate::{
@@ -32,6 +34,11 @@ pub const CONFIG_OPTION_DISCOVERY_SEED_HOSTS: &str = "discovery.seed_hosts";
3234
/// Type: string
3335
pub const CONFIG_OPTION_DISCOVERY_TYPE: &str = "discovery.type";
3436

37+
/// Specifies an address or addresses that an OpenSearch node publishes to other nodes for HTTP
38+
/// communication.
39+
/// Type: (comma-separated) list of strings
40+
pub const CONFIG_OPTION_HTTP_PUBLISH_HOST: &str = "http.publish_host";
41+
3542
/// A list of cluster-manager-eligible nodes used to bootstrap the cluster.
3643
/// Type: (comma-separated) list of strings
3744
pub const CONFIG_OPTION_INITIAL_CLUSTER_MANAGER_NODES: &str =
@@ -41,6 +48,11 @@ pub const CONFIG_OPTION_INITIAL_CLUSTER_MANAGER_NODES: &str =
4148
/// Type: string
4249
pub const CONFIG_OPTION_NETWORK_HOST: &str = "network.host";
4350

51+
/// Specifies an address or addresses that an OpenSearch node publishes to other nodes in the
52+
/// cluster so that they can connect to it.
53+
/// Type: (comma-separated) list of strings
54+
pub const CONFIG_OPTION_NETWORK_PUBLISH_HOST: &str = "network.publish_host";
55+
4456
/// The custom node attribute "role-group"
4557
/// Type: string
4658
pub const CONFIG_OPTION_NODE_ATTR_ROLE_GROUP: &str = "node.attr.role-group";
@@ -97,6 +109,11 @@ pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH: &str =
97109
pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH: &str =
98110
"plugins.security.ssl.transport.pemtrustedcas_filepath";
99111

112+
/// Specifies an address or addresses that an OpenSearch node publishes to other nodes for
113+
/// transport communication.
114+
/// Type: (comma-separated) list of strings
115+
pub const CONFIG_OPTION_TRANSPORT_PUBLISH_HOST: &str = "transport.publish_host";
116+
100117
const DEFAULT_OPENSEARCH_HOME: &str = "/stackable/opensearch";
101118

102119
/// Configuration of an OpenSearch node based on the cluster and role-group configuration
@@ -105,6 +122,8 @@ pub struct NodeConfig {
105122
role_group_name: RoleGroupName,
106123
role_group_config: OpenSearchRoleGroupConfig,
107124
pub discovery_service_name: ServiceName,
125+
cluster_domain_name: DomainName,
126+
headless_service_name: ServiceName,
108127
}
109128

110129
// Most functions are public because their configuration values could also be used in environment
@@ -115,12 +134,16 @@ impl NodeConfig {
115134
role_group_name: RoleGroupName,
116135
role_group_config: OpenSearchRoleGroupConfig,
117136
discovery_service_name: ServiceName,
137+
cluster_domain_name: DomainName,
138+
headless_service_name: ServiceName,
118139
) -> Self {
119140
Self {
120141
cluster,
121142
role_group_name,
122143
role_group_config,
123144
discovery_service_name,
145+
cluster_domain_name,
146+
headless_service_name,
124147
}
125148
}
126149

@@ -258,13 +281,36 @@ impl NodeConfig {
258281
/// The environment variables should only contain node-specific configuration options.
259282
/// Cluster-wide options should be added to the configuration file.
260283
pub fn environment_variables(&self) -> EnvVarSet {
284+
let fqdn = format!(
285+
"$(_POD_NAME).{}.{}.svc.{}",
286+
self.headless_service_name, self.cluster.namespace, self.cluster_domain_name
287+
);
288+
261289
EnvVarSet::new()
290+
.with_field_path(
291+
// Prefix with an underscore, so that it occurs before the other environment
292+
// variables which depend on it.
293+
&EnvVarName::from_str_unsafe("_POD_NAME"),
294+
FieldPathEnvVar::Name,
295+
)
262296
// Set the OpenSearch node name to the Pod name.
263297
// The node name is used e.g. for INITIAL_CLUSTER_MANAGER_NODES.
264298
.with_field_path(
265299
&EnvVarName::from_str_unsafe(CONFIG_OPTION_NODE_NAME),
266300
FieldPathEnvVar::Name,
267301
)
302+
.with_value(
303+
&EnvVarName::from_str_unsafe(CONFIG_OPTION_NETWORK_PUBLISH_HOST),
304+
&fqdn,
305+
)
306+
.with_value(
307+
&EnvVarName::from_str_unsafe(CONFIG_OPTION_TRANSPORT_PUBLISH_HOST),
308+
&fqdn,
309+
)
310+
.with_value(
311+
&EnvVarName::from_str_unsafe(CONFIG_OPTION_HTTP_PUBLISH_HOST),
312+
&fqdn,
313+
)
268314
.with_value(
269315
&EnvVarName::from_str_unsafe(CONFIG_OPTION_DISCOVERY_SEED_HOSTS),
270316
&self.discovery_service_name,
@@ -510,6 +556,8 @@ mod tests {
510556
role_group_name,
511557
role_group_config,
512558
ServiceName::from_str_unsafe("my-opensearch-cluster-manager"),
559+
DomainName::from_str("cluster.local").expect("should be a valid domain name"),
560+
ServiceName::from_str_unsafe("my-opensearch-cluster-default-headless"),
513561
)
514562
}
515563

@@ -609,6 +657,10 @@ mod tests {
609657
assert_eq!(
610658
EnvVarSet::new()
611659
.with_value(&EnvVarName::from_str_unsafe("TEST"), "value")
660+
.with_field_path(
661+
&EnvVarName::from_str_unsafe("_POD_NAME"),
662+
FieldPathEnvVar::Name
663+
)
612664
.with_value(
613665
&EnvVarName::from_str_unsafe("cluster.initial_cluster_manager_nodes"),
614666
"my-opensearch-cluster-nodes-default-0,my-opensearch-cluster-nodes-default-1",
@@ -617,13 +669,25 @@ mod tests {
617669
&EnvVarName::from_str_unsafe("discovery.seed_hosts"),
618670
"my-opensearch-cluster-manager",
619671
)
672+
.with_value(
673+
&EnvVarName::from_str_unsafe("http.publish_host"),
674+
"$(_POD_NAME).my-opensearch-cluster-default-headless.default.svc.cluster.local",
675+
)
676+
.with_value(
677+
&EnvVarName::from_str_unsafe("network.publish_host"),
678+
"$(_POD_NAME).my-opensearch-cluster-default-headless.default.svc.cluster.local",
679+
)
620680
.with_field_path(
621681
&EnvVarName::from_str_unsafe("node.name"),
622682
FieldPathEnvVar::Name
623683
)
624684
.with_value(
625685
&EnvVarName::from_str_unsafe("node.roles"),
626686
"cluster_manager,data,ingest,remote_cluster_client"
687+
)
688+
.with_value(
689+
&EnvVarName::from_str_unsafe("transport.publish_host"),
690+
"$(_POD_NAME).my-opensearch-cluster-default-headless.default.svc.cluster.local",
627691
),
628692
node_config.environment_variables()
629693
);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ mod tests {
223223
use stackable_operator::{
224224
commons::{
225225
affinity::StackableAffinity,
226+
networking::DomainName,
226227
product_image_selection::{ProductImage, ResolvedProductImage},
227228
resources::Resources,
228229
},
@@ -259,6 +260,8 @@ mod tests {
259260
product_name: ProductName::from_str_unsafe("opensearch"),
260261
operator_name: OperatorName::from_str_unsafe("opensearch.stackable.tech"),
261262
controller_name: ControllerName::from_str_unsafe("opensearchcluster"),
263+
cluster_domain_name: DomainName::from_str("cluster.local")
264+
.expect("should be a valid domain name"),
262265
}
263266
}
264267

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

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ impl<'a> RoleGroupBuilder<'a> {
116116
context_names: &'a ContextNames,
117117
discovery_service_name: ServiceName,
118118
) -> RoleGroupBuilder<'a> {
119+
let resource_names = ResourceNames {
120+
cluster_name: cluster.name.clone(),
121+
role_name: ValidatedCluster::role_name(),
122+
role_group_name: role_group_name.clone(),
123+
};
119124
RoleGroupBuilder {
120125
service_account_name,
121126
cluster: cluster.clone(),
@@ -124,15 +129,13 @@ impl<'a> RoleGroupBuilder<'a> {
124129
role_group_name.clone(),
125130
role_group_config.clone(),
126131
discovery_service_name,
132+
context_names.cluster_domain_name.clone(),
133+
resource_names.headless_service_name(),
127134
),
128135
role_group_name: role_group_name.clone(),
129136
role_group_config,
130137
context_names,
131-
resource_names: ResourceNames {
132-
cluster_name: cluster.name.clone(),
133-
role_name: ValidatedCluster::role_name(),
134-
role_group_name,
135-
},
138+
resource_names,
136139
}
137140
}
138141

@@ -810,8 +813,8 @@ mod tests {
810813
use serde_json::json;
811814
use stackable_operator::{
812815
commons::{
813-
affinity::StackableAffinity, product_image_selection::ResolvedProductImage,
814-
resources::Resources,
816+
affinity::StackableAffinity, networking::DomainName,
817+
product_image_selection::ResolvedProductImage, resources::Resources,
815818
},
816819
k8s_openapi::api::core::v1::PodTemplateSpec,
817820
kvp::LabelValue,
@@ -864,6 +867,8 @@ mod tests {
864867
product_name: ProductName::from_str_unsafe("opensearch"),
865868
operator_name: OperatorName::from_str_unsafe("opensearch.stackable.tech"),
866869
controller_name: ControllerName::from_str_unsafe("opensearchcluster"),
870+
cluster_domain_name: DomainName::from_str("cluster.local")
871+
.expect("should be a valid domain name"),
867872
}
868873
}
869874

@@ -1132,6 +1137,14 @@ mod tests {
11321137
"-c"
11331138
],
11341139
"env": [
1140+
{
1141+
"name": "_POD_NAME",
1142+
"valueFrom": {
1143+
"fieldRef": {
1144+
"fieldPath": "metadata.name"
1145+
}
1146+
}
1147+
},
11351148
{
11361149
"name": "cluster.initial_cluster_manager_nodes",
11371150
"value": ""
@@ -1140,6 +1153,14 @@ mod tests {
11401153
"name": "discovery.seed_hosts",
11411154
"value": "my-opensearch-cluster"
11421155
},
1156+
{
1157+
"name": "http.publish_host",
1158+
"value": "$(_POD_NAME).my-opensearch-cluster-nodes-default-headless.default.svc.cluster.local"
1159+
},
1160+
{
1161+
"name": "network.publish_host",
1162+
"value": "$(_POD_NAME).my-opensearch-cluster-nodes-default-headless.default.svc.cluster.local"
1163+
},
11431164
{
11441165
"name": "node.name",
11451166
"valueFrom": {
@@ -1151,7 +1172,11 @@ mod tests {
11511172
{
11521173
"name": "node.roles",
11531174
"value": "cluster_manager,data,ingest,remote_cluster_client"
1154-
}
1175+
},
1176+
{
1177+
"name": "transport.publish_host",
1178+
"value": "$(_POD_NAME).my-opensearch-cluster-nodes-default-headless.default.svc.cluster.local"
1179+
},
11551180
],
11561181
"image": "oci.stackable.tech/sdp/opensearch:3.1.0-stackable0.0.0-dev",
11571182
"imagePullPolicy": "Always",

rust/operator-binary/src/controller/validate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ mod tests {
263263
commons::{
264264
affinity::StackableAffinity,
265265
cluster_operation::ClusterOperation,
266+
networking::DomainName,
266267
product_image_selection::ResolvedProductImage,
267268
resources::{CpuLimits, MemoryLimits, PvcConfig, Resources},
268269
},
@@ -689,6 +690,8 @@ mod tests {
689690
product_name: ProductName::from_str_unsafe("opensearch"),
690691
operator_name: OperatorName::from_str_unsafe("opensearch.stackable.tech"),
691692
controller_name: ControllerName::from_str_unsafe("opensearchcluster"),
693+
cluster_domain_name: DomainName::from_str("cluster.local")
694+
.expect("should be a valid domain name"),
692695
}
693696
}
694697

0 commit comments

Comments
 (0)