@@ -45,7 +45,7 @@ use stackable_operator::{
4545 core:: { DeserializeGuard , error_boundary} ,
4646 runtime:: controller:: Action ,
4747 } ,
48- kvp:: { Label , LabelError , Labels , ObjectLabels } ,
48+ kvp:: { Annotations , Label , LabelError , Labels , ObjectLabels } ,
4949 logging:: controller:: ReconcilerError ,
5050 memory:: { BinaryMultiple , MemoryQuantity } ,
5151 product_config_utils:: { transform_all_roles_to_config, validate_all_roles_and_groups_config} ,
@@ -427,6 +427,14 @@ pub async fn reconcile_hbase(
427427
428428 let rg_service =
429429 build_rolegroup_service ( hbase, & hbase_role, & rolegroup, & resolved_product_image) ?;
430+
431+ let rg_metrics_service = build_rolegroup_metrics_service (
432+ hbase,
433+ & hbase_role,
434+ & rolegroup,
435+ & resolved_product_image,
436+ ) ?;
437+
430438 let rg_configmap = build_rolegroup_config_map (
431439 hbase,
432440 & client. kubernetes_cluster_info ,
@@ -452,6 +460,12 @@ pub async fn reconcile_hbase(
452460 . with_context ( |_| ApplyRoleGroupServiceSnafu {
453461 rolegroup : rolegroup. clone ( ) ,
454462 } ) ?;
463+ cluster_resources
464+ . add ( client, rg_metrics_service)
465+ . await
466+ . with_context ( |_| ApplyRoleGroupServiceSnafu {
467+ rolegroup : rolegroup. clone ( ) ,
468+ } ) ?;
455469 cluster_resources
456470 . add ( client, rg_configmap)
457471 . await
@@ -739,12 +753,9 @@ fn build_rolegroup_service(
739753 } )
740754 . collect ( ) ;
741755
742- let prometheus_label =
743- Label :: try_from ( ( "prometheus.io/scrape" , "true" ) ) . context ( BuildLabelSnafu ) ?;
744-
745756 let metadata = ObjectMetaBuilder :: new ( )
746757 . name_and_namespace ( hbase)
747- . name ( headless_service_name ( & rolegroup. object_name ( ) ) )
758+ . name ( rolegroup. rolegroup_headless_service_name ( ) )
748759 . ownerreference_from_resource ( hbase, None , Some ( true ) )
749760 . context ( ObjectMissingMetadataForOwnerRefSnafu ) ?
750761 . with_recommended_labels ( build_recommended_labels (
@@ -754,7 +765,6 @@ fn build_rolegroup_service(
754765 & rolegroup. role_group ,
755766 ) )
756767 . context ( ObjectMetaSnafu ) ?
757- . with_label ( prometheus_label)
758768 . build ( ) ;
759769
760770 let service_selector =
@@ -778,6 +788,82 @@ fn build_rolegroup_service(
778788 } )
779789}
780790
791+ /// The rolegroup metrics [`Service`] is a service that exposes metrics and a prometheus scraping label.
792+ pub fn build_rolegroup_metrics_service (
793+ hbase : & v1alpha1:: HbaseCluster ,
794+ hbase_role : & HbaseRole ,
795+ rolegroup : & RoleGroupRef < v1alpha1:: HbaseCluster > ,
796+ resolved_product_image : & ResolvedProductImage ,
797+ ) -> Result < Service , Error > {
798+ let ports = hbase
799+ . metrics_ports ( hbase_role)
800+ . into_iter ( )
801+ . map ( |( name, value) | ServicePort {
802+ name : Some ( name) ,
803+ port : i32:: from ( value) ,
804+ protocol : Some ( "TCP" . to_string ( ) ) ,
805+ ..ServicePort :: default ( )
806+ } )
807+ . collect ( ) ;
808+
809+ let service_selector =
810+ Labels :: role_group_selector ( hbase, APP_NAME , & rolegroup. role , & rolegroup. role_group )
811+ . context ( BuildLabelSnafu ) ?;
812+
813+ Ok ( Service {
814+ metadata : ObjectMetaBuilder :: new ( )
815+ . name_and_namespace ( hbase)
816+ . name ( rolegroup. rolegroup_metrics_service_name ( ) )
817+ . ownerreference_from_resource ( hbase, None , Some ( true ) )
818+ . context ( ObjectMissingMetadataForOwnerRefSnafu ) ?
819+ . with_recommended_labels ( build_recommended_labels (
820+ hbase,
821+ & resolved_product_image. app_version_label_value ,
822+ & rolegroup. role ,
823+ & rolegroup. role_group ,
824+ ) )
825+ . context ( ObjectMetaSnafu ) ?
826+ . with_label ( Label :: try_from ( ( "prometheus.io/scrape" , "true" ) ) . context ( LabelBuildSnafu ) ?)
827+ . with_annotations ( prometheus_annotations ( hbase, hbase_role) )
828+ . build ( ) ,
829+ spec : Some ( ServiceSpec {
830+ // Internal communication does not need to be exposed
831+ type_ : Some ( "ClusterIP" . to_string ( ) ) ,
832+ cluster_ip : Some ( "None" . to_string ( ) ) ,
833+ ports : Some ( ports) ,
834+ selector : Some ( service_selector. into ( ) ) ,
835+ publish_not_ready_addresses : Some ( true ) ,
836+ ..ServiceSpec :: default ( )
837+ } ) ,
838+ status : None ,
839+ } )
840+ }
841+
842+ /// Common annotations for Prometheus
843+ ///
844+ /// These annotations can be used in a ServiceMonitor.
845+ ///
846+ /// see also <https://github.com/prometheus-community/helm-charts/blob/prometheus-27.32.0/charts/prometheus/values.yaml#L983-L1036>
847+ fn prometheus_annotations ( hbase : & v1alpha1:: HbaseCluster , hbase_role : & HbaseRole ) -> Annotations {
848+ Annotations :: try_from ( [
849+ ( "prometheus.io/path" . to_owned ( ) , "/prometheus" . to_owned ( ) ) ,
850+ (
851+ "prometheus.io/port" . to_owned ( ) ,
852+ hbase. metrics_port ( hbase_role) . to_string ( ) ,
853+ ) ,
854+ (
855+ "prometheus.io/scheme" . to_owned ( ) ,
856+ if hbase. has_https_enabled ( ) {
857+ "https" . to_owned ( )
858+ } else {
859+ "http" . to_owned ( )
860+ } ,
861+ ) ,
862+ ( "prometheus.io/scrape" . to_owned ( ) , "true" . to_owned ( ) ) ,
863+ ] )
864+ . expect ( "should be valid annotations" )
865+ }
866+
781867/// The rolegroup [`StatefulSet`] runs the rolegroup, as configured by the administrator.
782868///
783869/// The [`Pod`](`stackable_operator::k8s_openapi::api::core::v1::Pod`)s are accessible through the corresponding [`Service`] (from [`build_rolegroup_service`]).
@@ -1088,7 +1174,7 @@ fn build_rolegroup_statefulset(
10881174 match_labels : Some ( statefulset_match_labels. into ( ) ) ,
10891175 ..LabelSelector :: default ( )
10901176 } ,
1091- service_name : Some ( headless_service_name ( & rolegroup_ref. object_name ( ) ) ) ,
1177+ service_name : Some ( rolegroup_ref. rolegroup_headless_service_name ( ) ) ,
10921178 template : pod_template,
10931179 volume_claim_templates : listener_pvc,
10941180 ..StatefulSetSpec :: default ( )
@@ -1198,10 +1284,6 @@ fn build_hbase_env_sh(
11981284 Ok ( result)
11991285}
12001286
1201- fn headless_service_name ( role_group_name : & str ) -> String {
1202- format ! ( "{name}-headless" , name = role_group_name)
1203- }
1204-
12051287#[ cfg( test) ]
12061288mod test {
12071289 use rstest:: rstest;
0 commit comments