Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support specifying externalTrafficPolicy in Services created by listener-operator #773

Merged
merged 14 commits into from
May 21, 2024
Merged
5 changes: 5 additions & 0 deletions crates/stackable-operator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

- Support specifying externalTrafficPolicy in Services created by listener-operator ([#773]).
- BREAKING: Rename `commons::listener::ServiceType` to `commons::listener::KubernetesServiceType` ([#773]).

[#773]: https://github.com/stackabletech/operator-rs/pull/773

## [0.67.1] - 2024-05-08

### Added
Expand Down
3 changes: 3 additions & 0 deletions crates/stackable-operator/src/cluster_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
client::{Client, GetApi},
commons::{
cluster_operation::ClusterOperation,
listener::Listener,
resources::{
ComputeResource, ResourceRequirementsExt, ResourceRequirementsType,
LIMIT_REQUEST_RATIO_CPU, LIMIT_REQUEST_RATIO_MEMORY,
Expand Down Expand Up @@ -203,6 +204,7 @@ impl ClusterResource for Service {}
impl ClusterResource for ServiceAccount {}
impl ClusterResource for RoleBinding {}
impl ClusterResource for PodDisruptionBudget {}
impl ClusterResource for Listener {}

impl ClusterResource for Job {
fn pod_spec(&self) -> Option<&PodSpec> {
Expand Down Expand Up @@ -612,6 +614,7 @@ impl ClusterResources {
self.delete_orphaned_resources_of_kind::<ServiceAccount>(client),
self.delete_orphaned_resources_of_kind::<RoleBinding>(client),
self.delete_orphaned_resources_of_kind::<PodDisruptionBudget>(client),
self.delete_orphaned_resources_of_kind::<Listener>(client),
)?;

Ok(())
Expand Down
46 changes: 41 additions & 5 deletions crates/stackable-operator/src/commons/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

use std::collections::BTreeMap;

use derivative::Derivative;
use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand All @@ -50,24 +51,45 @@ use crate::builder::pod::volume::ListenerOperatorVolumeSourceBuilder;
)]
#[serde(rename_all = "camelCase")]
pub struct ListenerClassSpec {
pub service_type: ServiceType,
pub service_type: KubernetesServiceType,

/// Annotations that should be added to the Service object.
#[serde(default)]
pub service_annotations: BTreeMap<String, String>,
}

/// The method used to access the services.
#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema, PartialEq, Eq)]
pub enum ServiceType {
//
// Please note that this represents a Kubernetes type, so the name of the enum variant needs to exactly match the
// Kubernetes service type.
#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema, PartialEq, Eq, strum::Display)]
pub enum KubernetesServiceType {
sbernauer marked this conversation as resolved.
Show resolved Hide resolved
/// Reserve a port on each node.
NodePort,

/// Provision a dedicated load balancer.
LoadBalancer,

/// Assigns an IP address from a pool of IP addresses that your cluster has reserved for that purpose.
ClusterIP,
}

/// Service Internal Traffic Policy enables internal traffic restrictions to only route internal traffic to endpoints
/// within the node the traffic originated from. The "internal" traffic here refers to traffic originated from Pods in
/// the current cluster. This can help to reduce costs and improve performance.
/// See [Kubernetes docs](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/).
//
// Please note that this represents a Kubernetes type, so the name of the enum variant needs to exactly match the
// Kubernetes traffic policy.
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq, strum::Display)]
pub enum KubernetesTrafficPolicy {
/// Obscures the client source IP and may cause a second hop to another node, but allows Kubernetes to spread the load between all nodes.
Cluster,

/// Preserves the client source IP and avoid a second hop for LoadBalancer and NodePort type Services, but makes clients responsible for spreading the load.
Local,
}

/// Exposes a set of pods to the outside world.
///
/// Essentially a Stackable extension of a Kubernetes Service. Compared to a Service, a Listener changes three things:
Expand All @@ -78,8 +100,9 @@ pub enum ServiceType {
///
/// Learn more in the [Listener documentation](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listener).
#[derive(
CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default, PartialEq, Eq,
CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq, Derivative,
)]
#[derivative(Default)]
#[kube(
group = "listeners.stackable.tech",
version = "v1alpha1",
Expand All @@ -100,14 +123,27 @@ pub struct ListenerSpec {
pub ports: Option<Vec<ListenerPort>>,

/// Whether incoming traffic should also be directed to Pods that are not `Ready`.
#[schemars(default = "Self::default_publish_not_ready_addresses")]
#[serde(default = "ListenerSpec::default_publish_not_ready_addresses")]
pub publish_not_ready_addresses: Option<bool>,

/// `externalTrafficPolicy` that should be set on the [`Service`] object.
///
/// The default is `Local` (in contrast to `Cluster`), as we aim to direct traffic to a node running the workload
/// and we should keep testing that as the primary configuration. Cluster is a fallback option for providers that
/// break Local mode (IONOS so far).
#[derivative(Default(value = "ListenerSpec::default_service_external_traffic_policy()"))]
#[serde(default = "ListenerSpec::default_service_external_traffic_policy")]
pub service_external_traffic_policy: KubernetesTrafficPolicy,
}

impl ListenerSpec {
const fn default_publish_not_ready_addresses() -> Option<bool> {
Some(true)
}

const fn default_service_external_traffic_policy() -> KubernetesTrafficPolicy {
KubernetesTrafficPolicy::Local
}
}

#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)]
Expand Down
Loading