mirror of
https://github.com/prometheus-operator/prometheus-operator.git
synced 2025-04-15 16:56:24 +00:00
Add ServiceDiscoveryRole configuration to toggle service discovery via EndpointSlice vs Endpoints (#6672)
* Add service discovery role in Prometheus and Prometheus Agent CRDs --------- Co-authored-by: haanhvu <haanh6594@gmail.com> Co-authored-by: Simon Pasquier <spasquie@redhat.com>
This commit is contained in:
parent
f0a3778b4b
commit
813bc2b6b9
19 changed files with 282 additions and 29 deletions
100
Documentation/api.md
generated
100
Documentation/api.md
generated
|
@ -2794,6 +2794,22 @@ in a breaking way.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceDiscoveryRole</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.ServiceDiscoveryRole">
|
||||
ServiceDiscoveryRole
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Defines the service discovery role used to discover targets from <code>ServiceMonitor</code> objects.
|
||||
If set, the value should be either “Endpoints” or “EndpointSlice”.
|
||||
If unset, the operator assumes the “Endpoints” role.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>baseImage</code><br/>
|
||||
<em>
|
||||
string
|
||||
|
@ -7468,6 +7484,22 @@ PodMonitors, ServiceMonitors, Probes and ScrapeConfigs.</p>
|
|||
in a breaking way.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceDiscoveryRole</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.ServiceDiscoveryRole">
|
||||
ServiceDiscoveryRole
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Defines the service discovery role used to discover targets from <code>ServiceMonitor</code> objects.
|
||||
If set, the value should be either “Endpoints” or “EndpointSlice”.
|
||||
If unset, the operator assumes the “Endpoints” role.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="monitoring.coreos.com/v1.Condition">Condition
|
||||
|
@ -11644,6 +11676,22 @@ in a breaking way.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceDiscoveryRole</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.ServiceDiscoveryRole">
|
||||
ServiceDiscoveryRole
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Defines the service discovery role used to discover targets from <code>ServiceMonitor</code> objects.
|
||||
If set, the value should be either “Endpoints” or “EndpointSlice”.
|
||||
If unset, the operator assumes the “Endpoints” role.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>baseImage</code><br/>
|
||||
<em>
|
||||
string
|
||||
|
@ -13892,6 +13940,26 @@ Kubernetes core/v1.ConfigMapKeySelector
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="monitoring.coreos.com/v1.ServiceDiscoveryRole">ServiceDiscoveryRole
|
||||
(<code>string</code> alias)</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em><a href="#monitoring.coreos.com/v1.CommonPrometheusFields">CommonPrometheusFields</a>)
|
||||
</p>
|
||||
<div>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr><td><p>"EndpointSlice"</p></td>
|
||||
<td></td>
|
||||
</tr><tr><td><p>"Endpoints"</p></td>
|
||||
<td></td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
<h3 id="monitoring.coreos.com/v1.ServiceMonitorSpec">ServiceMonitorSpec
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -17772,6 +17840,22 @@ PodMonitors, ServiceMonitors, Probes and ScrapeConfigs.</p>
|
|||
in a breaking way.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceDiscoveryRole</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.ServiceDiscoveryRole">
|
||||
ServiceDiscoveryRole
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Defines the service discovery role used to discover targets from <code>ServiceMonitor</code> objects.
|
||||
If set, the value should be either “Endpoints” or “EndpointSlice”.
|
||||
If unset, the operator assumes the “Endpoints” role.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -25016,6 +25100,22 @@ PodMonitors, ServiceMonitors, Probes and ScrapeConfigs.</p>
|
|||
in a breaking way.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceDiscoveryRole</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.ServiceDiscoveryRole">
|
||||
ServiceDiscoveryRole
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Defines the service discovery role used to discover targets from <code>ServiceMonitor</code> objects.
|
||||
If set, the value should be either “Endpoints” or “EndpointSlice”.
|
||||
If unset, the operator assumes the “Endpoints” role.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="monitoring.coreos.com/v1alpha1.PuppetDBSDConfig">PuppetDBSDConfig
|
||||
|
|
|
@ -52,17 +52,17 @@ Further information can also be found in the [Thanos section]({{< ref "thanos.md
|
|||
|
||||
The `ServiceMonitor` custom resource definition (CRD) allows to declaratively define how a dynamic set of services should be monitored. Which services are selected to be monitored with the desired configuration is defined using label selections. This allows an organization to introduce conventions around how metrics are exposed, and then following these conventions new services are automatically discovered, without the need to reconfigure the system.
|
||||
|
||||
For Prometheus to monitor any application within Kubernetes an `Endpoints` object needs to exist. `Endpoints` objects are essentially lists of IP addresses. Typically an `Endpoints` object is populated by a `Service` object. A `Service` object discovers `Pod`s by a label selector and adds those to the `Endpoints` object.
|
||||
For Prometheus to monitor any application within Kubernetes, either an `EndpointSlice` object or an `Endpoints` object needs to exist. These objects are essentially lists of IP addresses. Typically an `EndpointSlice` or an `Endpoints` object is populated by a `Service` object. A `Service` object discovers `Pod`s by a label selector and adds those to the `EndpointSlice` or `Endpoints` object.
|
||||
|
||||
A `Service` may expose one or more service ports, which are backed by a list of multiple endpoints that point to a `Pod` in the common case. This is reflected in the respective `Endpoints` object as well.
|
||||
A `Service` may expose one or more service ports, which are backed by a list of multiple endpoints that point to a `Pod` in the common case. This is reflected in the respective `EndpointSlice` or `Endpoints` object as well.
|
||||
|
||||
The `ServiceMonitor` object introduced by the Prometheus Operator in turn discovers those `Endpoints` objects and configures Prometheus to monitor those `Pod`s.
|
||||
The `ServiceMonitor` object introduced by the Prometheus Operator in turn discovers those `EndpointSlice` or `Endpoints` objects and configures Prometheus to monitor those `Pod`s.
|
||||
|
||||
The `endpoints` section of the `ServiceMonitorSpec`, is used to configure which ports of these `Endpoints` are going to be scraped for metrics, and with which parameters. For advanced use cases one may want to monitor ports of backing `Pod`s, which are not directly part of the service endpoints. Therefore when specifying an endpoint in the `endpoints` section, they are strictly used.
|
||||
The `endpoints` section of the `ServiceMonitorSpec`, is used to configure which ports of these `EndpointSlice`s or `Endpoints` are going to be scraped for metrics, and with which parameters. For advanced use cases one may want to monitor ports of backing `Pod`s, which are not directly part of the service endpoints. Therefore when specifying an endpoint in the `endpoints` section, they are strictly used.
|
||||
|
||||
> Note: `endpoints` (lowercase) is the field in the `ServiceMonitor` CRD, while `Endpoints` (capitalized) is the Kubernetes object kind.
|
||||
> Note: `endpoints` (lowercase) is the field in the `ServiceMonitor` CRD, while `EndpointSlice` or `Endpoints` (capitalized) is the Kubernetes object kind.
|
||||
|
||||
Both `ServiceMonitors` as well as discovered targets may come from any namespace. This is important to allow cross-namespace monitoring use cases, e.g. for meta-monitoring. Using the `ServiceMonitorNamespaceSelector` of the `PrometheusSpec`, one can restrict the namespaces `ServiceMonitor`s are selected from by the respective Prometheus server. Using the `namespaceSelector` of the `ServiceMonitorSpec`, one can restrict the namespaces the `Endpoints` objects are allowed to be discovered from.
|
||||
Both `ServiceMonitors` as well as discovered targets may come from any namespace. This is important to allow cross-namespace monitoring use cases, e.g. for meta-monitoring. Using the `ServiceMonitorNamespaceSelector` of the `PrometheusSpec`, one can restrict the namespaces `ServiceMonitor`s are selected from by the respective Prometheus server. Using the `namespaceSelector` of the `ServiceMonitorSpec`, one can restrict the namespaces the `EndpointSlice` or `Endpoints` objects are allowed to be discovered from.
|
||||
|
||||
One can discover targets in all namespaces like this:
|
||||
|
||||
|
|
18
bundle.yaml
generated
18
bundle.yaml
generated
|
@ -23784,6 +23784,15 @@ spec:
|
|||
ServiceAccountName is the name of the ServiceAccount to use to run the
|
||||
Prometheus Pods.
|
||||
type: string
|
||||
serviceDiscoveryRole:
|
||||
description: |-
|
||||
Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
If unset, the operator assumes the "Endpoints" role.
|
||||
enum:
|
||||
- Endpoints
|
||||
- EndpointSlice
|
||||
type: string
|
||||
serviceMonitorNamespaceSelector:
|
||||
description: |-
|
||||
Namespaces to match for ServicedMonitors discovery. An empty label selector
|
||||
|
@ -35627,6 +35636,15 @@ spec:
|
|||
ServiceAccountName is the name of the ServiceAccount to use to run the
|
||||
Prometheus Pods.
|
||||
type: string
|
||||
serviceDiscoveryRole:
|
||||
description: |-
|
||||
Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
If unset, the operator assumes the "Endpoints" role.
|
||||
enum:
|
||||
- Endpoints
|
||||
- EndpointSlice
|
||||
type: string
|
||||
serviceMonitorNamespaceSelector:
|
||||
description: |-
|
||||
Namespaces to match for ServicedMonitors discovery. An empty label selector
|
||||
|
|
|
@ -6825,6 +6825,15 @@ spec:
|
|||
ServiceAccountName is the name of the ServiceAccount to use to run the
|
||||
Prometheus Pods.
|
||||
type: string
|
||||
serviceDiscoveryRole:
|
||||
description: |-
|
||||
Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
If unset, the operator assumes the "Endpoints" role.
|
||||
enum:
|
||||
- Endpoints
|
||||
- EndpointSlice
|
||||
type: string
|
||||
serviceMonitorNamespaceSelector:
|
||||
description: |-
|
||||
Namespaces to match for ServicedMonitors discovery. An empty label selector
|
||||
|
|
|
@ -8302,6 +8302,15 @@ spec:
|
|||
ServiceAccountName is the name of the ServiceAccount to use to run the
|
||||
Prometheus Pods.
|
||||
type: string
|
||||
serviceDiscoveryRole:
|
||||
description: |-
|
||||
Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
If unset, the operator assumes the "Endpoints" role.
|
||||
enum:
|
||||
- Endpoints
|
||||
- EndpointSlice
|
||||
type: string
|
||||
serviceMonitorNamespaceSelector:
|
||||
description: |-
|
||||
Namespaces to match for ServicedMonitors discovery. An empty label selector
|
||||
|
|
|
@ -6826,6 +6826,15 @@ spec:
|
|||
ServiceAccountName is the name of the ServiceAccount to use to run the
|
||||
Prometheus Pods.
|
||||
type: string
|
||||
serviceDiscoveryRole:
|
||||
description: |-
|
||||
Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
If unset, the operator assumes the "Endpoints" role.
|
||||
enum:
|
||||
- Endpoints
|
||||
- EndpointSlice
|
||||
type: string
|
||||
serviceMonitorNamespaceSelector:
|
||||
description: |-
|
||||
Namespaces to match for ServicedMonitors discovery. An empty label selector
|
||||
|
|
|
@ -8303,6 +8303,15 @@ spec:
|
|||
ServiceAccountName is the name of the ServiceAccount to use to run the
|
||||
Prometheus Pods.
|
||||
type: string
|
||||
serviceDiscoveryRole:
|
||||
description: |-
|
||||
Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
If unset, the operator assumes the "Endpoints" role.
|
||||
enum:
|
||||
- Endpoints
|
||||
- EndpointSlice
|
||||
type: string
|
||||
serviceMonitorNamespaceSelector:
|
||||
description: |-
|
||||
Namespaces to match for ServicedMonitors discovery. An empty label selector
|
||||
|
|
|
@ -5590,6 +5590,14 @@
|
|||
"description": "ServiceAccountName is the name of the ServiceAccount to use to run the\nPrometheus Pods.",
|
||||
"type": "string"
|
||||
},
|
||||
"serviceDiscoveryRole": {
|
||||
"description": "Defines the service discovery role used to discover targets from `ServiceMonitor` objects.\nIf set, the value should be either \"Endpoints\" or \"EndpointSlice\".\nIf unset, the operator assumes the \"Endpoints\" role.",
|
||||
"enum": [
|
||||
"Endpoints",
|
||||
"EndpointSlice"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"serviceMonitorNamespaceSelector": {
|
||||
"description": "Namespaces to match for ServicedMonitors discovery. An empty label selector\nmatches all namespaces. A null label selector (default value) matches the current\nnamespace only.",
|
||||
"properties": {
|
||||
|
|
|
@ -6797,6 +6797,14 @@
|
|||
"description": "ServiceAccountName is the name of the ServiceAccount to use to run the\nPrometheus Pods.",
|
||||
"type": "string"
|
||||
},
|
||||
"serviceDiscoveryRole": {
|
||||
"description": "Defines the service discovery role used to discover targets from `ServiceMonitor` objects.\nIf set, the value should be either \"Endpoints\" or \"EndpointSlice\".\nIf unset, the operator assumes the \"Endpoints\" role.",
|
||||
"enum": [
|
||||
"Endpoints",
|
||||
"EndpointSlice"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"serviceMonitorNamespaceSelector": {
|
||||
"description": "Namespaces to match for ServicedMonitors discovery. An empty label selector\nmatches all namespaces. A null label selector (default value) matches the current\nnamespace only.",
|
||||
"properties": {
|
||||
|
|
|
@ -772,6 +772,12 @@ type CommonPrometheusFields struct {
|
|||
// +listType=map
|
||||
// +listMapKey=name
|
||||
ScrapeClasses []ScrapeClass `json:"scrapeClasses,omitempty"`
|
||||
|
||||
// Defines the service discovery role used to discover targets from `ServiceMonitor` objects.
|
||||
// If set, the value should be either "Endpoints" or "EndpointSlice".
|
||||
// If unset, the operator assumes the "Endpoints" role.
|
||||
// +optional
|
||||
ServiceDiscoveryRole *ServiceDiscoveryRole `json:"serviceDiscoveryRole,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:validation:Enum=HTTP;ProcessSignal
|
||||
|
@ -785,6 +791,14 @@ const (
|
|||
ProcessSignalReloadStrategyType ReloadStrategyType = "ProcessSignal"
|
||||
)
|
||||
|
||||
// +kubebuilder:validation:Enum=Endpoints;EndpointSlice
|
||||
type ServiceDiscoveryRole string
|
||||
|
||||
const (
|
||||
EndpointsRole ServiceDiscoveryRole = "Endpoints"
|
||||
EndpointSliceRole ServiceDiscoveryRole = "EndpointSlice"
|
||||
)
|
||||
|
||||
func (cpf *CommonPrometheusFields) PrometheusURIScheme() string {
|
||||
if cpf.Web != nil && cpf.Web.TLSConfig != nil {
|
||||
return "https"
|
||||
|
|
5
pkg/apis/monitoring/v1/zz_generated.deepcopy.go
generated
5
pkg/apis/monitoring/v1/zz_generated.deepcopy.go
generated
|
@ -969,6 +969,11 @@ func (in *CommonPrometheusFields) DeepCopyInto(out *CommonPrometheusFields) {
|
|||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.ServiceDiscoveryRole != nil {
|
||||
in, out := &in.ServiceDiscoveryRole, &out.ServiceDiscoveryRole
|
||||
*out = new(ServiceDiscoveryRole)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonPrometheusFields.
|
||||
|
|
|
@ -107,6 +107,7 @@ type CommonPrometheusFieldsApplyConfiguration struct {
|
|||
ReloadStrategy *monitoringv1.ReloadStrategyType `json:"reloadStrategy,omitempty"`
|
||||
MaximumStartupDurationSeconds *int32 `json:"maximumStartupDurationSeconds,omitempty"`
|
||||
ScrapeClasses []ScrapeClassApplyConfiguration `json:"scrapeClasses,omitempty"`
|
||||
ServiceDiscoveryRole *monitoringv1.ServiceDiscoveryRole `json:"serviceDiscoveryRole,omitempty"`
|
||||
}
|
||||
|
||||
// CommonPrometheusFieldsApplyConfiguration constructs an declarative configuration of the CommonPrometheusFields type for use with
|
||||
|
@ -826,3 +827,11 @@ func (b *CommonPrometheusFieldsApplyConfiguration) WithScrapeClasses(values ...*
|
|||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithServiceDiscoveryRole sets the ServiceDiscoveryRole field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the ServiceDiscoveryRole field is set to the value of the last call.
|
||||
func (b *CommonPrometheusFieldsApplyConfiguration) WithServiceDiscoveryRole(value monitoringv1.ServiceDiscoveryRole) *CommonPrometheusFieldsApplyConfiguration {
|
||||
b.ServiceDiscoveryRole = &value
|
||||
return b
|
||||
}
|
||||
|
|
|
@ -769,6 +769,14 @@ func (b *PrometheusSpecApplyConfiguration) WithScrapeClasses(values ...*ScrapeCl
|
|||
return b
|
||||
}
|
||||
|
||||
// WithServiceDiscoveryRole sets the ServiceDiscoveryRole field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the ServiceDiscoveryRole field is set to the value of the last call.
|
||||
func (b *PrometheusSpecApplyConfiguration) WithServiceDiscoveryRole(value monitoringv1.ServiceDiscoveryRole) *PrometheusSpecApplyConfiguration {
|
||||
b.ServiceDiscoveryRole = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithBaseImage sets the BaseImage field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the BaseImage field is set to the value of the last call.
|
||||
|
|
|
@ -756,3 +756,11 @@ func (b *PrometheusAgentSpecApplyConfiguration) WithScrapeClasses(values ...*v1.
|
|||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithServiceDiscoveryRole sets the ServiceDiscoveryRole field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the ServiceDiscoveryRole field is set to the value of the last call.
|
||||
func (b *PrometheusAgentSpecApplyConfiguration) WithServiceDiscoveryRole(value monitoringv1.ServiceDiscoveryRole) *PrometheusAgentSpecApplyConfiguration {
|
||||
b.ServiceDiscoveryRole = &value
|
||||
return b
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ type Operator struct {
|
|||
reconciliations *operator.ReconciliationTracker
|
||||
|
||||
config prompkg.Config
|
||||
endpointSliceSupported bool
|
||||
endpointSliceSupported bool // Whether the Kubernetes API suports the EndpointSlice kind.
|
||||
scrapeConfigSupported bool
|
||||
canReadStorageClass bool
|
||||
|
||||
|
@ -318,15 +318,11 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
|||
}
|
||||
}
|
||||
|
||||
endpointSliceSupported, err := k8sutil.IsAPIGroupVersionResourceSupported(o.kclient.Discovery(), schema.GroupVersion{Group: "discovery.k8s.io", Version: "v1"}, "endpointslices")
|
||||
o.endpointSliceSupported, err = k8sutil.IsAPIGroupVersionResourceSupported(o.kclient.Discovery(), schema.GroupVersion{Group: "discovery.k8s.io", Version: "v1"}, "endpointslices")
|
||||
if err != nil {
|
||||
level.Warn(o.logger).Log("msg", "failed to check if the API supports the endpointslice resources", "err ", err)
|
||||
}
|
||||
level.Info(o.logger).Log("msg", "Kubernetes API capabilities", "endpointslices", endpointSliceSupported)
|
||||
// The operator doesn't yet support the endpointslices API.
|
||||
// See https://github.com/prometheus-operator/prometheus-operator/issues/3862
|
||||
// for details.
|
||||
o.endpointSliceSupported = false
|
||||
level.Info(o.logger).Log("msg", "Kubernetes API capabilities", "endpointslices", o.endpointSliceSupported)
|
||||
|
||||
o.statusReporter = prompkg.StatusReporter{
|
||||
Kclient: o.kclient,
|
||||
|
|
|
@ -64,13 +64,15 @@ type ConfigGenerator struct {
|
|||
version semver.Version
|
||||
notCompatible bool
|
||||
prom monitoringv1.PrometheusInterface
|
||||
endpointSliceSupported bool
|
||||
useEndpointSlice bool // Whether to use EndpointSlice for service discovery from `ServiceMonitor` objects.
|
||||
scrapeClasses map[string]monitoringv1.ScrapeClass
|
||||
defaultScrapeClassName string
|
||||
}
|
||||
|
||||
// NewConfigGenerator creates a ConfigGenerator for the provided Prometheus resource.
|
||||
func NewConfigGenerator(logger log.Logger, p monitoringv1.PrometheusInterface, endpointSliceSupported bool) (*ConfigGenerator, error) {
|
||||
func NewConfigGenerator(logger log.Logger,
|
||||
p monitoringv1.PrometheusInterface,
|
||||
endpointSliceSupported bool) (*ConfigGenerator, error) {
|
||||
if logger == nil {
|
||||
logger = log.NewNopLogger()
|
||||
}
|
||||
|
@ -94,11 +96,28 @@ func NewConfigGenerator(logger log.Logger, p monitoringv1.PrometheusInterface, e
|
|||
return nil, fmt.Errorf("failed to parse scrape classes: %w", err)
|
||||
}
|
||||
|
||||
endpointSliceConfigured := false // Always assume false to preserve original prometheus-operator behaviour.
|
||||
|
||||
// Check if the user has explicitly set the service discovery role to use.
|
||||
switch serviceDiscoveryRole := ptr.Deref(cpf.ServiceDiscoveryRole, monitoringv1.EndpointsRole); serviceDiscoveryRole {
|
||||
case monitoringv1.EndpointSliceRole:
|
||||
level.Info(logger).Log("msg", "using endpointslice as service discovery role")
|
||||
endpointSliceConfigured = true
|
||||
case monitoringv1.EndpointsRole:
|
||||
level.Info(logger).Log("msg", "using endpoints as service discovery role")
|
||||
endpointSliceConfigured = false
|
||||
default:
|
||||
level.Warn(logger).Log("msg",
|
||||
"unknown service discovery role %q, defaulting to endpoints. Configure serviceDiscoveryRole to 'EndpointSlice' to use endpointslice as service discovery role.",
|
||||
serviceDiscoveryRole)
|
||||
endpointSliceConfigured = false
|
||||
}
|
||||
|
||||
return &ConfigGenerator{
|
||||
logger: logger,
|
||||
version: version,
|
||||
prom: p,
|
||||
endpointSliceSupported: endpointSliceSupported,
|
||||
useEndpointSlice: endpointSliceConfigured && endpointSliceSupported,
|
||||
scrapeClasses: scrapeClasses,
|
||||
defaultScrapeClassName: defaultScrapeClassName,
|
||||
}, nil
|
||||
|
@ -142,7 +161,7 @@ func (cg *ConfigGenerator) WithKeyVals(keyvals ...interface{}) *ConfigGenerator
|
|||
version: cg.version,
|
||||
notCompatible: cg.notCompatible,
|
||||
prom: cg.prom,
|
||||
endpointSliceSupported: cg.endpointSliceSupported,
|
||||
useEndpointSlice: cg.useEndpointSlice,
|
||||
scrapeClasses: cg.scrapeClasses,
|
||||
defaultScrapeClassName: cg.defaultScrapeClassName,
|
||||
}
|
||||
|
@ -161,7 +180,7 @@ func (cg *ConfigGenerator) WithMinimumVersion(version string) *ConfigGenerator {
|
|||
version: cg.version,
|
||||
notCompatible: true,
|
||||
prom: cg.prom,
|
||||
endpointSliceSupported: cg.endpointSliceSupported,
|
||||
useEndpointSlice: cg.useEndpointSlice,
|
||||
scrapeClasses: cg.scrapeClasses,
|
||||
defaultScrapeClassName: cg.defaultScrapeClassName,
|
||||
}
|
||||
|
@ -183,7 +202,7 @@ func (cg *ConfigGenerator) WithMaximumVersion(version string) *ConfigGenerator {
|
|||
version: cg.version,
|
||||
notCompatible: true,
|
||||
prom: cg.prom,
|
||||
endpointSliceSupported: cg.endpointSliceSupported,
|
||||
useEndpointSlice: cg.useEndpointSlice,
|
||||
scrapeClasses: cg.scrapeClasses,
|
||||
defaultScrapeClassName: cg.defaultScrapeClassName,
|
||||
}
|
||||
|
@ -329,8 +348,11 @@ func (cg *ConfigGenerator) AddHonorLabels(cfg yaml.MapSlice, honorLabels bool) y
|
|||
return cg.AppendMapItem(cfg, "honor_labels", honorLabels)
|
||||
}
|
||||
|
||||
// Returns true if the Prometheus version used supports service discovery via EndpointSlice
|
||||
// and the prometheus-operator config generator is configured to use EndpointSlices for
|
||||
// service discovery from ServiceMonitor objects.
|
||||
func (cg *ConfigGenerator) EndpointSliceSupported() bool {
|
||||
return cg.version.GTE(semver.MustParse("2.21.0")) && cg.endpointSliceSupported
|
||||
return cg.version.GTE(semver.MustParse("2.21.0")) && cg.useEndpointSlice
|
||||
}
|
||||
|
||||
// stringMapToMapSlice returns a yaml.MapSlice from a string map to ensure that
|
||||
|
|
|
@ -66,7 +66,15 @@ func mustNewConfigGenerator(t *testing.T, p *monitoringv1.Prometheus) *ConfigGen
|
|||
}
|
||||
logger := level.NewFilter(log.NewLogfmtLogger(os.Stdout), level.AllowWarn())
|
||||
|
||||
cg, err := NewConfigGenerator(log.With(logger, "test", t.Name()), p, false)
|
||||
useEndpointSlice := false
|
||||
|
||||
if p.Spec.ServiceDiscoveryRole == nil || *p.Spec.ServiceDiscoveryRole == monitoringv1.EndpointsRole {
|
||||
useEndpointSlice = false
|
||||
} else if *p.Spec.ServiceDiscoveryRole == monitoringv1.EndpointSliceRole {
|
||||
useEndpointSlice = true
|
||||
}
|
||||
|
||||
cg, err := NewConfigGenerator(log.With(logger, "test", t.Name()), p, useEndpointSlice)
|
||||
require.NoError(t, err)
|
||||
|
||||
return cg
|
||||
|
@ -825,11 +833,13 @@ func TestK8SSDConfigGeneration(t *testing.T) {
|
|||
testcases := []struct {
|
||||
apiServerConfig *monitoringv1.APIServerConfig
|
||||
store *assets.StoreBuilder
|
||||
role string
|
||||
golden string
|
||||
}{
|
||||
{
|
||||
apiServerConfig: nil,
|
||||
store: assets.NewTestStoreBuilder(),
|
||||
role: "endpoints",
|
||||
golden: "K8SSDConfigGenerationFirst.golden",
|
||||
},
|
||||
{
|
||||
|
@ -864,8 +874,15 @@ func TestK8SSDConfigGeneration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
),
|
||||
role: "endpoints",
|
||||
golden: "K8SSDConfigGenerationTwo.golden",
|
||||
},
|
||||
{
|
||||
apiServerConfig: nil,
|
||||
store: assets.NewTestStoreBuilder(),
|
||||
role: "endpointslice",
|
||||
golden: "K8SSDConfigGenerationThree.golden",
|
||||
},
|
||||
{
|
||||
apiServerConfig: &monitoringv1.APIServerConfig{
|
||||
Host: "example.com",
|
||||
|
@ -897,6 +914,7 @@ func TestK8SSDConfigGeneration(t *testing.T) {
|
|||
},
|
||||
},
|
||||
store: assets.NewTestStoreBuilder(),
|
||||
role: "endpoints",
|
||||
golden: "K8SSDConfigGenerationTLSConfig.golden",
|
||||
},
|
||||
}
|
||||
|
@ -925,7 +943,7 @@ func TestK8SSDConfigGeneration(t *testing.T) {
|
|||
sm.Namespace,
|
||||
tc.apiServerConfig,
|
||||
tc.store.ForNamespace(sm.Namespace),
|
||||
kubernetesSDRoleEndpoint,
|
||||
tc.role,
|
||||
attachMetaConfig,
|
||||
)
|
||||
s, err := yaml.Marshal(yaml.MapSlice{c})
|
||||
|
@ -1564,9 +1582,10 @@ func TestNoEnforcedNamespaceLabelServiceMonitor(t *testing.T) {
|
|||
func TestServiceMonitorWithEndpointSliceEnable(t *testing.T) {
|
||||
p := defaultPrometheus()
|
||||
p.Spec.CommonPrometheusFields.EnforcedNamespaceLabel = "ns-key"
|
||||
p.Spec.CommonPrometheusFields.ServiceDiscoveryRole = ptr.To(monitoringv1.EndpointSliceRole)
|
||||
|
||||
cg := mustNewConfigGenerator(t, p)
|
||||
cg.endpointSliceSupported = true
|
||||
|
||||
cfg, err := cg.GenerateServerConfiguration(
|
||||
p.Spec.EvaluationInterval,
|
||||
p.Spec.QueryLogFile,
|
||||
|
|
|
@ -355,15 +355,11 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
|
|||
}
|
||||
}
|
||||
|
||||
endpointSliceSupported, err := k8sutil.IsAPIGroupVersionResourceSupported(o.kclient.Discovery(), schema.GroupVersion{Group: "discovery.k8s.io", Version: "v1"}, "endpointslices")
|
||||
o.endpointSliceSupported, err = k8sutil.IsAPIGroupVersionResourceSupported(o.kclient.Discovery(), schema.GroupVersion{Group: "discovery.k8s.io", Version: "v1"}, "endpointslices")
|
||||
if err != nil {
|
||||
level.Warn(o.logger).Log("msg", "failed to check if the API supports the endpointslice resources", "err ", err)
|
||||
}
|
||||
level.Info(o.logger).Log("msg", "Kubernetes API capabilities", "endpointslices", endpointSliceSupported)
|
||||
// The operator doesn't yet support the endpointslices API.
|
||||
// See https://github.com/prometheus-operator/prometheus-operator/issues/3862
|
||||
// for details.
|
||||
o.endpointSliceSupported = false
|
||||
level.Info(o.logger).Log("msg", "Kubernetes API capabilities", "endpointslices", o.endpointSliceSupported)
|
||||
|
||||
o.statusReporter = prompkg.StatusReporter{
|
||||
Kclient: o.kclient,
|
||||
|
@ -813,6 +809,7 @@ func (c *Operator) sync(ctx context.Context, key string) error {
|
|||
}
|
||||
|
||||
assetStore := assets.NewStoreBuilder(c.kclient.CoreV1(), c.kclient.CoreV1())
|
||||
|
||||
cg, err := prompkg.NewConfigGenerator(c.logger, p, c.endpointSliceSupported)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
5
pkg/prometheus/testdata/K8SSDConfigGenerationThree.golden
generated
vendored
Normal file
5
pkg/prometheus/testdata/K8SSDConfigGenerationThree.golden
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
kubernetes_sd_configs:
|
||||
- role: endpointslice
|
||||
namespaces:
|
||||
names:
|
||||
- test
|
Loading…
Add table
Reference in a new issue