@@ -2,10 +2,12 @@ package main
22
33import (
44 "context"
5+ "errors"
56 "flag"
67 "fmt"
78 "os"
89 "runtime"
10+ "strings"
911
1012 // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
1113 _ "k8s.io/client-go/plugin/pkg/client/auth"
@@ -24,7 +26,7 @@ import (
2426 "github.com/spf13/pflag"
2527 v1 "k8s.io/api/core/v1"
2628 "k8s.io/apimachinery/pkg/util/intstr"
27- "sigs.k8s.io/controller-runtime/pkg/client/apiutil "
29+ "sigs.k8s.io/controller-runtime/pkg/cache "
2830 "sigs.k8s.io/controller-runtime/pkg/client/config"
2931 logf "sigs.k8s.io/controller-runtime/pkg/log"
3032 "sigs.k8s.io/controller-runtime/pkg/manager"
@@ -90,12 +92,23 @@ func main() {
9092 os .Exit (1 )
9193 }
9294
93- // Create a new Cmd to provide shared dependencies and start components
94- mgr , err := manager . New ( cfg , manager.Options {
95+ // Set default manager options
96+ options := manager.Options {
9597 Namespace : namespace ,
96- MapperProvider : apiutil .NewDiscoveryRESTMapper ,
9798 MetricsBindAddress : fmt .Sprintf ("%s:%d" , metricsHost , metricsPort ),
98- })
99+ }
100+
101+ // Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)
102+ // Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate
103+ // Also note that you may face performance issues when using this with a high number of namespaces.
104+ // More Info: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
105+ if strings .Contains (namespace , "," ) {
106+ options .Namespace = ""
107+ options .NewCache = cache .MultiNamespacedCacheBuilder (strings .Split (namespace , "," ))
108+ }
109+
110+ // Create a new manager to provide shared dependencies and start components
111+ mgr , err := manager .New (cfg , options )
99112 if err != nil {
100113 log .Error (err , "" )
101114 os .Exit (1 )
@@ -115,7 +128,31 @@ func main() {
115128 os .Exit (1 )
116129 }
117130
118- if err = serveCRMetrics (cfg ); err != nil {
131+ // Add the Metrics Service
132+ addMetrics (ctx , cfg )
133+
134+ log .Info ("Starting the Cmd." )
135+
136+ // Start the Cmd
137+ if err := mgr .Start (signals .SetupSignalHandler ()); err != nil {
138+ log .Error (err , "Manager exited non-zero" )
139+ os .Exit (1 )
140+ }
141+ }
142+
143+ // addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using
144+ // the Prometheus operator
145+ func addMetrics (ctx context.Context , cfg * rest.Config ) {
146+ // Get the namespace the operator is currently deployed in.
147+ operatorNs , err := k8sutil .GetOperatorNamespace ()
148+ if err != nil {
149+ if errors .Is (err , k8sutil .ErrRunLocal ) {
150+ log .Info ("Skipping CR metrics server creation; not running in a cluster." )
151+ return
152+ }
153+ }
154+
155+ if err := serveCRMetrics (cfg , operatorNs ); err != nil {
119156 log .Info ("Could not generate and serve custom resource metrics" , "error" , err .Error ())
120157 }
121158
@@ -124,6 +161,7 @@ func main() {
124161 {Port : metricsPort , Name : metrics .OperatorPortName , Protocol : v1 .ProtocolTCP , TargetPort : intstr.IntOrString {Type : intstr .Int , IntVal : metricsPort }},
125162 {Port : operatorMetricsPort , Name : metrics .CRPortName , Protocol : v1 .ProtocolTCP , TargetPort : intstr.IntOrString {Type : intstr .Int , IntVal : operatorMetricsPort }},
126163 }
164+
127165 // Create Service object to expose the metrics port(s).
128166 service , err := metrics .CreateMetricsService (ctx , cfg , servicePorts )
129167 if err != nil {
@@ -133,7 +171,9 @@ func main() {
133171 // CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources
134172 // necessary to configure Prometheus to scrape metrics from this operator.
135173 services := []* v1.Service {service }
136- _ , err = metrics .CreateServiceMonitors (cfg , namespace , services )
174+
175+ // The ServiceMonitor is created in the same namespace where the operator is deployed
176+ _ , err = metrics .CreateServiceMonitors (cfg , operatorNs , services )
137177 if err != nil {
138178 log .Info ("Could not create ServiceMonitor object" , "error" , err .Error ())
139179 // If this operator is deployed to a cluster without the prometheus-operator running, it will return
@@ -142,32 +182,26 @@ func main() {
142182 log .Info ("Install prometheus-operator in your cluster to create ServiceMonitor objects" , "error" , err .Error ())
143183 }
144184 }
145-
146- log .Info ("Starting the Cmd." )
147-
148- // Start the Cmd
149- if err := mgr .Start (signals .SetupSignalHandler ()); err != nil {
150- log .Error (err , "Manager exited non-zero" )
151- os .Exit (1 )
152- }
153185}
154186
155187// serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.
156188// It serves those metrics on "http://metricsHost:operatorMetricsPort".
157- func serveCRMetrics (cfg * rest.Config ) error {
158- // Below function returns filtered operator/CustomResource specific GVKs.
159- // For more control override the below GVK list with your own custom logic.
189+ func serveCRMetrics (cfg * rest.Config , operatorNs string ) error {
190+ // The function below returns a list of filtered operator/CR specific GVKs. For more control, override the GVK list below
191+ // with your own custom logic. Note that if you are adding third party API schemas, probably you will need to
192+ // customize this implementation to avoid permissions issues.
160193 filteredGVK , err := k8sutil .GetGVKsFromAddToScheme (apis .AddToScheme )
161194 if err != nil {
162195 return err
163196 }
164- // Get the namespace the operator is currently deployed in.
165- operatorNs , err := k8sutil .GetOperatorNamespace ()
197+
198+ // The metrics will be generated from the namespaces which are returned here.
199+ // NOTE that passing nil or an empty list of namespaces in GenerateAndServeCRMetrics will result in an error.
200+ ns , err := kubemetrics .GetNamespacesForMetrics (operatorNs )
166201 if err != nil {
167202 return err
168203 }
169- // To generate metrics in other namespaces, add the values below.
170- ns := []string {operatorNs }
204+
171205 // Generate and serve custom resource specific metrics.
172206 err = kubemetrics .GenerateAndServeCRMetrics (cfg , ns , filteredGVK , metricsHost , operatorMetricsPort )
173207 if err != nil {
0 commit comments