diff --git a/CHANGELOG.md b/CHANGELOG.md index 008f9a3..2a15a54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Removed + +- BREAKING: Removed the deprecated pod enrichment controller ([#321]). + ### Added - Aggregate emitted Kubernetes events on the CustomResources ([#318]). @@ -13,6 +17,7 @@ All notable changes to this project will be documented in this file. - Append a dot (`.`) to the default cluster domain to reduce DNS requests ([#318]). [#318]: https://github.com/stackabletech/commons-operator/pull/318 +[#321]: https://github.com/stackabletech/commons-operator/pull/321 ## [24.11.0] - 2024-11-18 diff --git a/docs/modules/commons-operator/pages/index.adoc b/docs/modules/commons-operator/pages/index.adoc index 9e14f63..585407f 100644 --- a/docs/modules/commons-operator/pages/index.adoc +++ b/docs/modules/commons-operator/pages/index.adoc @@ -1,5 +1,5 @@ = Stackable Commons Operator -:description: Learn about shared objects (AuthenticationClass, S3Bucket and S3Connection) and shared functionality (Pod enrichting, restarting) on the Stackable Data Platform. +:description: Learn about shared objects (AuthenticationClass, S3Bucket and S3Connection) and shared functionality (restarting) on the Stackable Data Platform. :github: https://github.com/stackabletech/commons-operator/ :crd: {crd-docs-base-url}/commons-operator/{crd-docs-version}/ @@ -23,4 +23,4 @@ You can also find the full CRD refererence documentation for all objects linked == Shared functionality The commons operator implements functionality that is shared by all other Stackable operators. -For example, it xref:pod-enrichment.adoc[adds additional information to Pods] which would otherwise have to be inferred and takes care of xref:restarter.adoc[restarting] Pods when necessary, for example to reload configuration settings in products that don't support hot reloading. +For example, it takes care of xref:restarter.adoc[restarting] Pods when necessary, for example to reload configuration settings in products that don't support hot reloading. diff --git a/docs/modules/commons-operator/pages/pod-enrichment.adoc b/docs/modules/commons-operator/pages/pod-enrichment.adoc deleted file mode 100644 index 4097798..0000000 --- a/docs/modules/commons-operator/pages/pod-enrichment.adoc +++ /dev/null @@ -1,19 +0,0 @@ -= Pod enricher -:description: Use Labels to instruct the Stackable Commons Operator to enrich Pods with Kubernetes node addresses - -WARNING: The pod enricher is deprecated as of the Stackable Data Platform 24.11, and will be removed in the next release. For more information, see https://github.com/stackabletech/commons-operator/issues/292[issue #292]. - -The Stackable Commons Operator automatically adds commonly used information to Pod objects, which would otherwise have to be inferred by traversing the Kubernetes object graph. - -== Usage - -To enable the pod enricher for a Pod, set the label `enrichment.stackable.tech/enabled` to `true`. - -== Which information is added to the Pod? - -Annotation:: `enrichment.stackable.tech/node-address` - -The hostname or IP address of the Node that the Pod is scheduled to run on. -Compared to `Pod.status.nodeIP`, this can also (but doesn't have to) be a hostname, and prefers externally routable addresses. - -This is intended to be used for components that need to register an accessible address (such as Kafka brokers, or HDFS DataNodes). diff --git a/docs/modules/commons-operator/pages/usage.adoc b/docs/modules/commons-operator/pages/usage.adoc index e8884d6..9243a55 100644 --- a/docs/modules/commons-operator/pages/usage.adoc +++ b/docs/modules/commons-operator/pages/usage.adoc @@ -8,7 +8,3 @@ The commons-operator is used for multiple purposes: |xref:restarter.adoc[] |A controller that watches Pod objects and their controllers and restarts them when required. - -|xref:pod-enrichment.adoc[] -|A controller that adds commonly used information to Pod objects. -|=== diff --git a/docs/modules/commons-operator/partials/nav.adoc b/docs/modules/commons-operator/partials/nav.adoc index 39e1a19..e642781 100644 --- a/docs/modules/commons-operator/partials/nav.adoc +++ b/docs/modules/commons-operator/partials/nav.adoc @@ -2,7 +2,6 @@ * xref:commons-operator:usage.adoc[] * Concepts ** xref:commons-operator:restarter.adoc[] -** xref:commons-operator:pod-enrichment.adoc[] * xref:commons-operator:reference/index.adoc[] ** xref:commons-operator:reference/crds.adoc[] *** {crd-docs}/authentication.stackable.tech/authenticationclass/v1alpha1/[AuthenticationClass {external-link-icon}^] diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index dc000aa..b8ffbba 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -1,4 +1,3 @@ -mod pod_enrichment_controller; mod restart_controller; use built_info::PKG_VERSION; @@ -61,18 +60,8 @@ async fn main() -> anyhow::Result<()> { let sts_restart_controller = restart_controller::statefulset::start(&client, &watch_namespace); let pod_restart_controller = restart_controller::pod::start(&client, &watch_namespace); - let pod_enrichment_controller = - pod_enrichment_controller::start(&client, &watch_namespace); - pin_mut!( - sts_restart_controller, - pod_restart_controller, - pod_enrichment_controller - ); - futures::future::select( - futures::future::select(sts_restart_controller, pod_restart_controller), - pod_enrichment_controller, - ) - .await; + pin_mut!(sts_restart_controller, pod_restart_controller); + futures::future::select(sts_restart_controller, pod_restart_controller).await; } } diff --git a/rust/operator-binary/src/pod_enrichment_controller.rs b/rust/operator-binary/src/pod_enrichment_controller.rs deleted file mode 100644 index c274eec..0000000 --- a/rust/operator-binary/src/pod_enrichment_controller.rs +++ /dev/null @@ -1,193 +0,0 @@ -// Deprecated for removal, see https://github.com/stackabletech/commons-operator/issues/292 - -use std::{collections::BTreeMap, str::FromStr, sync::Arc, time::Duration}; - -use futures::StreamExt; -use snafu::{ResultExt, Snafu}; -use stackable_operator::{ - k8s_openapi::api::core::v1::{Node, Pod}, - kube::{ - core::{error_boundary, DeserializeGuard, ObjectMeta}, - runtime::{ - controller, - events::{Recorder, Reporter}, - reflector::ObjectRef, - watcher, Controller, - }, - Resource, - }, - logging::controller::{report_controller_reconciled, ReconcilerError}, - namespace::WatchNamespace, -}; -use strum::{EnumDiscriminants, IntoStaticStr}; - -const FULL_CONTROLLER_NAME: &str = "pod.enrichment.commons.stackable.tech"; -const FIELD_MANAGER_SCOPE: &str = "enrichment.stackable.tech/pod"; -const ANNOTATION_NODE_ADDRESS: &str = "enrichment.stackable.tech/node-address"; - -struct Ctx { - client: stackable_operator::client::Client, -} - -#[derive(Snafu, Debug, EnumDiscriminants)] -#[strum_discriminants(derive(IntoStaticStr))] -pub enum Error { - #[snafu(display("Pod object is invalid"))] - InvalidPod { - source: error_boundary::InvalidObject, - }, - - #[snafu(display("failed to get {node} for Pod"))] - GetNode { - source: stackable_operator::client::Error, - node: ObjectRef, - }, - - #[snafu(display("failed to update Pod"))] - UpdatePod { - source: stackable_operator::client::Error, - }, -} - -impl ReconcilerError for Error { - fn category(&self) -> &'static str { - ErrorDiscriminants::from(self).into() - } - - fn secondary_object(&self) -> Option> { - match self { - Error::InvalidPod { source: _ } => None, - Error::GetNode { node, .. } => Some(node.clone().erase()), - Error::UpdatePod { source: _ } => None, - } - } -} - -pub async fn start(client: &stackable_operator::client::Client, watch_namespace: &WatchNamespace) { - let event_recorder = Arc::new(Recorder::new( - client.as_kube_client(), - Reporter { - controller: FULL_CONTROLLER_NAME.to_string(), - instance: None, - }, - )); - let controller = Controller::new( - watch_namespace.get_api::>(client), - watcher::Config::default().labels("enrichment.stackable.tech/enabled=true"), - ); - let pods = controller.store(); - controller - .watches( - client.get_all_api::>(), - watcher::Config::default(), - move |node| { - pods.state() - .into_iter() - .filter(move |pod| { - let Ok(pod) = &pod.0 else { - return false; - }; - pod.spec.as_ref().and_then(|s| s.node_name.as_deref()) - == node.meta().name.as_deref() - }) - .map(|pod| ObjectRef::from_obj(&*pod)) - }, - ) - .run( - reconcile, - error_policy, - Arc::new(Ctx { - client: client.clone(), - }), - ) - // We can let the reporting happen in the background - .for_each_concurrent( - 16, // concurrency limit - |result| { - // The event_recorder needs to be shared across all invocations, so that - // events are correctly aggregated - let event_recorder = event_recorder.clone(); - async move { - report_controller_reconciled(&event_recorder, FULL_CONTROLLER_NAME, &result) - .await; - } - }, - ) - .await; -} - -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, strum::EnumString)] -pub enum NodeAddressType { - ExternalIP, - InternalIP, -} - -async fn reconcile( - pod: Arc>, - ctx: Arc, -) -> Result { - tracing::info!("Starting reconcile"); - let pod = pod - .0 - .as_ref() - .map_err(error_boundary::InvalidObject::clone) - .context(InvalidPodSnafu)?; - - let node_name = pod.spec.as_ref().and_then(|s| s.node_name.as_deref()); - let node = if let Some(node_name) = node_name { - ctx.client - .get::(node_name, &()) - .await - .with_context(|_| GetNodeSnafu { - node: ObjectRef::new(node_name), - })? - } else { - // this condition is normal enough during pod setup that we don't want to cause a bunch of - // error messages... - tracing::debug!("Pod has not yet been scheduled to a Node"); - return Ok(controller::Action::await_change()); - }; - - let mut annotations = BTreeMap::new(); - - let node_addr = node - .status - .iter() - .flat_map(|s| &s.addresses) - .flatten() - .filter_map(|addr| Some((NodeAddressType::from_str(&addr.type_).ok()?, &addr.address))) - .min_by_key(|(ty, _)| *ty) - .map(|(_, addr)| addr); - if let Some(node_addr) = node_addr { - annotations.insert(ANNOTATION_NODE_ADDRESS.to_string(), node_addr.clone()); - } - - let patch = Pod { - metadata: ObjectMeta { - name: pod.metadata.name.clone(), - namespace: pod.metadata.namespace.clone(), - uid: pod.metadata.uid.clone(), - annotations: Some(annotations), - ..ObjectMeta::default() - }, - ..Pod::default() - }; - ctx.client - .apply_patch(FIELD_MANAGER_SCOPE, &patch, &patch) - .await - .context(UpdatePodSnafu)?; - Ok(controller::Action::await_change()) -} - -fn error_policy( - _obj: Arc>, - error: &Error, - _ctx: Arc, -) -> controller::Action { - match error { - // root object is invalid, will be requeued when modified anyway - Error::InvalidPod { .. } => controller::Action::await_change(), - - _ => controller::Action::requeue(Duration::from_secs(5)), - } -}