Skip to content

Commit bdb4e8b

Browse files
authored
Use address type (IP vs DNS) configured by ListenerClass (#233)
* Make preferred NodePort address type configurable * Respect preferred address type for LoadBalancer and ClusterIP services too * Changelog * Docs * Test both DNS and IP address types * Add node_primary_address tests, simplified from @sbernauer's * Split node_primary_addresses into a separate module * Split the rest of utils * Reword changelog a bit * The op-rs PR was merged
1 parent 6240929 commit bdb4e8b

File tree

19 files changed

+346
-104
lines changed

19 files changed

+346
-104
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Added
8+
9+
- `Listener.status.addresses` can now be configured to prefer either IP addresses or DNS hostnames ([#233]).
10+
711
### Changed
812

9-
- Listener.status.addresses for NodePort listeners now includes replicas that are currently unavailable ([#231]).
13+
- `Listener.status.addresses` for NodePort listeners now includes replicas that are currently unavailable ([#231]).
14+
- `Listener.status.addresses` now defaults to DNS hostnames for all service types (previously NodePort and ClusterIP would prefer IP addresses, [#233]).
1015

1116
### Fixed
1217

@@ -15,6 +20,7 @@ All notable changes to this project will be documented in this file.
1520
- Propagate `ListenerClass.spec.serviceAnnotations` to the created Services ([#234]).
1621

1722
[#231]: https://github.com/stackabletech/listener-operator/pull/231
23+
[#233]: https://github.com/stackabletech/listener-operator/pull/233
1824
[#234]: https://github.com/stackabletech/listener-operator/pull/234
1925

2026
## [24.7.0] - 2024-07-24

Cargo.lock

Lines changed: 17 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.nix

Lines changed: 56 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ prost = "0.13"
2121
prost-types = "0.13"
2222
serde = "1.0"
2323
snafu = "0.8"
24-
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.76.0" }
24+
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.78.0" }
2525
strum = { version = "0.26", features = ["derive"] }
2626
socket2 = { version = "0.5", features = ["all"] }
2727
tokio = { version = "1.40", features = ["full"] }
@@ -31,5 +31,6 @@ tonic-build = "0.12"
3131
tonic-reflection = "0.12"
3232
tracing = "0.1.40"
3333

34-
# [patch."https://github.com/stackabletech/operator-rs.git"]
35-
# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" }
34+
[patch."https://github.com/stackabletech/operator-rs.git"]
35+
# stackable-operator = { path = "../operator-rs/crates/stackable-operator" }
36+
stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" }

crate-hashes.json

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deploy/helm/listener-operator/crds/crds.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ spec:
2424
spec:
2525
description: Defines a policy for how [Listeners](https://docs.stackable.tech/home/nightly/listener-operator/listener) should be exposed. Read the [ListenerClass documentation](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass) for more information.
2626
properties:
27+
preferredAddressType:
28+
default: Hostname
29+
description: |-
30+
Whether addresses should prefer using the IP address (`IP`) or the hostname (`Hostname`).
31+
32+
The other type will be used if the preferred type is not available. By default `Hostname` is used.
33+
enum:
34+
- Hostname
35+
- IP
36+
type: string
2737
serviceAnnotations:
2838
additionalProperties:
2939
type: string

docs/modules/listener-operator/pages/listenerclass.adoc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ How exactly this is accomplished depends on the cloud provider in question, but
3030
include::example$listenerclass-internal-gke.yaml[]
3131
----
3232

33+
[#servicetype]
3334
== Service types
3435

3536
The service type is defined by `ListenerClass.spec.serviceType`.
@@ -62,6 +63,24 @@ Compared to xref:#servicetype-nodeport[], this service type allows Pods to be mo
6263
However, it requires https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer[a cloud controller manager that supports load balancers].
6364
Additionally, many cloud providers charge for load-balanced traffic.
6465

66+
[#addresstype]
67+
== Address types
68+
69+
The Stackable Listener Operator supports both IP addresses and DNS hostnames. The preferred address type for a given ListenerClass can be configured using the `ListenerClass.spec.preferredAddressType` field. If no `preferredAddressType` is specified then it defaults to xref:#addresstype-hostname[].
70+
71+
NOTE: If the preferred address type is not supported for a given environment then another type will be used.
72+
73+
[#addresstype-ip]
74+
=== IP
75+
76+
The IP address of a resource. The addresses will be less predictable (especially for xref:#servicetype-clusterip[] services),
77+
but does not require any special client configuration (beyond what the xref:#servicetype[] requires).
78+
79+
[#addresstype-hostname]
80+
=== Hostname
81+
82+
The DNS hostname of a resource. Clients must be able to resolve these addresses in order to connect, which may require special DNS configuration.
83+
6584
== Default ListenerClasses
6685

6786
The Stackable Data Platform assumes the existence of a few predefined ListenerClasses, and will use them by default as appropriate:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use stackable_operator::{
88
};
99
use tonic::{Request, Response, Status};
1010

11-
use crate::utils::error_full_message;
11+
use crate::utils::error::error_full_message;
1212

1313
use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext};
1414

rust/operator-binary/src/csi_server/node.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use snafu::{OptionExt, ResultExt, Snafu};
44
use stackable_operator::{
55
builder::meta::OwnerReferenceBuilder,
66
commons::listener::{
7-
Listener, ListenerIngress, ListenerPort, ListenerSpec, PodListener, PodListenerScope,
8-
PodListeners, PodListenersSpec,
7+
Listener, ListenerClass, ListenerIngress, ListenerPort, ListenerSpec, PodListener,
8+
PodListenerScope, PodListeners, PodListenersSpec,
99
},
1010
k8s_openapi::api::core::v1::{Node, PersistentVolume, PersistentVolumeClaim, Pod, Volume},
1111
kube::{
@@ -21,7 +21,7 @@ use crate::{
2121
listener_mounted_pod_label, listener_persistent_volume_label, ListenerMountedPodLabelError,
2222
ListenerPersistentVolumeLabelError,
2323
},
24-
utils::{error_full_message, node_primary_address},
24+
utils::{address::node_primary_addresses, error::error_full_message},
2525
};
2626

2727
use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext};
@@ -72,6 +72,9 @@ enum PublishVolumeError {
7272
listener: ObjectRef<Listener>,
7373
},
7474

75+
#[snafu(display("{listener} has no associated ListenerClass"))]
76+
ListenerHasNoClass { listener: ObjectRef<Listener> },
77+
7578
#[snafu(display("{pod} has not been scheduled to a node yet"))]
7679
PodHasNoNode { pod: ObjectRef<Pod> },
7780

@@ -131,6 +134,7 @@ impl From<PublishVolumeError> for Status {
131134
PublishVolumeError::PodHasNoNode { .. } => Status::unavailable(full_msg),
132135
PublishVolumeError::ListenerPvReference { .. } => Status::failed_precondition(full_msg),
133136
PublishVolumeError::ListenerPodSelector { .. } => Status::failed_precondition(full_msg),
137+
PublishVolumeError::ListenerHasNoClass { .. } => Status::failed_precondition(full_msg),
134138
PublishVolumeError::BuildListenerOwnerRef { .. } => Status::unavailable(full_msg),
135139
PublishVolumeError::ApplyListener { .. } => Status::unavailable(full_msg),
136140
PublishVolumeError::AddListenerLabelToPv { .. } => Status::unavailable(full_msg),
@@ -442,10 +446,25 @@ async fn local_listener_addresses_for_pod(
442446
.get::<Node>(node_name, &())
443447
.await
444448
.with_context(|_| GetObjectSnafu {
445-
obj: { ObjectRef::<Node>::new(node_name).erase() },
449+
obj: ObjectRef::<Node>::new(node_name).erase(),
450+
})?;
451+
let listener_class_name =
452+
listener
453+
.spec
454+
.class_name
455+
.as_deref()
456+
.with_context(|| ListenerHasNoClassSnafu {
457+
listener: ObjectRef::from_obj(listener),
458+
})?;
459+
let listener_class = client
460+
.get::<ListenerClass>(listener_class_name, &())
461+
.await
462+
.with_context(|_| GetObjectSnafu {
463+
obj: ObjectRef::<ListenerClass>::new(listener_class_name).erase(),
446464
})?;
447465

448-
Ok(node_primary_address(&node)
466+
Ok(node_primary_addresses(&node)
467+
.pick(listener_class.spec.preferred_address_type)
449468
.map(|(address, address_type)| ListenerIngress {
450469
// nodes: Some(vec![node_name.to_string()]),
451470
address: address.to_string(),

0 commit comments

Comments
 (0)