mirror of
https://github.com/prometheus-operator/prometheus-operator.git
synced 2025-04-21 03:38:43 +00:00
Feat: Add servicename
field to the Prometheus server and agent CRDs (#6687)
This commit is contained in:
parent
4d26aaecf6
commit
78bffbb698
20 changed files with 527 additions and 25 deletions
Documentation/api-reference
bundle.yamlexample
prometheus-operator-crd-full
prometheus-operator-crd
jsonnet/prometheus-operator
pkg
apis/monitoring/v1
client/applyconfiguration/monitoring
prometheus
test/e2e
|
@ -3103,6 +3103,23 @@ It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceName</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named <code>prometheus-operated</code> for Prometheus resources,
|
||||
or <code>prometheus-agent-operated</code> for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id">https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id</a> for more details.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>runtime</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.RuntimeConfig">
|
||||
|
@ -8247,6 +8264,23 @@ It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceName</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named <code>prometheus-operated</code> for Prometheus resources,
|
||||
or <code>prometheus-agent-operated</code> for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id">https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id</a> for more details.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>runtime</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.RuntimeConfig">
|
||||
|
@ -13109,6 +13143,23 @@ It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceName</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named <code>prometheus-operated</code> for Prometheus resources,
|
||||
or <code>prometheus-agent-operated</code> for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id">https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id</a> for more details.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>runtime</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.RuntimeConfig">
|
||||
|
@ -19889,6 +19940,23 @@ It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceName</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named <code>prometheus-operated</code> for Prometheus resources,
|
||||
or <code>prometheus-agent-operated</code> for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id">https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id</a> for more details.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>runtime</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.RuntimeConfig">
|
||||
|
@ -27850,6 +27918,23 @@ It requires Prometheus >= v2.39.0 or PrometheusAgent >= v2.54.0.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>serviceName</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named <code>prometheus-operated</code> for Prometheus resources,
|
||||
or <code>prometheus-agent-operated</code> for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id">https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id</a> for more details.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>runtime</code><br/>
|
||||
<em>
|
||||
<a href="#monitoring.coreos.com/v1.RuntimeConfig">
|
||||
|
|
20
bundle.yaml
generated
20
bundle.yaml
generated
|
@ -28427,6 +28427,16 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
serviceName:
|
||||
description: |-
|
||||
The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
minLength: 1
|
||||
type: string
|
||||
shards:
|
||||
description: |-
|
||||
Number of shards to distribute scraped targets onto.
|
||||
|
@ -40920,6 +40930,16 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
serviceName:
|
||||
description: |-
|
||||
The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
minLength: 1
|
||||
type: string
|
||||
sha:
|
||||
description: 'Deprecated: use ''spec.image'' instead. The image''s
|
||||
digest can be specified as part of the image name.'
|
||||
|
|
|
@ -7267,6 +7267,16 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
serviceName:
|
||||
description: |-
|
||||
The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
minLength: 1
|
||||
type: string
|
||||
shards:
|
||||
description: |-
|
||||
Number of shards to distribute scraped targets onto.
|
||||
|
|
|
@ -8976,6 +8976,16 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
serviceName:
|
||||
description: |-
|
||||
The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
minLength: 1
|
||||
type: string
|
||||
sha:
|
||||
description: 'Deprecated: use ''spec.image'' instead. The image''s
|
||||
digest can be specified as part of the image name.'
|
||||
|
|
|
@ -7268,6 +7268,16 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
serviceName:
|
||||
description: |-
|
||||
The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
minLength: 1
|
||||
type: string
|
||||
shards:
|
||||
description: |-
|
||||
Number of shards to distribute scraped targets onto.
|
||||
|
|
|
@ -8977,6 +8977,16 @@ spec:
|
|||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
serviceName:
|
||||
description: |-
|
||||
The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
minLength: 1
|
||||
type: string
|
||||
sha:
|
||||
description: 'Deprecated: use ''spec.image'' instead. The image''s
|
||||
digest can be specified as part of the image name.'
|
||||
|
|
|
@ -6151,6 +6151,11 @@
|
|||
"type": "object",
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
},
|
||||
"serviceName": {
|
||||
"description": "The name of the service name used by the underlying StatefulSet(s) as the governing service.\nIf defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.\nIf empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,\nor `prometheus-agent-operated` for PrometheusAgent resources.\nWhen deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.\nSee https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.",
|
||||
"minLength": 1,
|
||||
"type": "string"
|
||||
},
|
||||
"shards": {
|
||||
"description": "Number of shards to distribute scraped targets onto.\n\n`spec.replicas` multiplied by `spec.shards` is the total number of Pods\nbeing created.\n\nWhen not defined, the operator assumes only one shard.\n\nNote that scaling down shards will not reshard data onto the remaining\ninstances, it must be manually moved. Increasing shards will not reshard\ndata either but it will continue to be available from the same\ninstances. To query globally, use Thanos sidecar and Thanos querier or\nremote write data to a central location.\nAlerting and recording rules\n\nBy default, the sharding is performed on:\n* The `__address__` target's metadata label for PodMonitor,\nServiceMonitor and ScrapeConfig resources.\n* The `__param_target__` label for Probe resources.\n\nUsers can define their own sharding implementation by setting the\n`__tmp_hash` label during the target discovery with relabeling\nconfiguration (either in the monitoring resources or via scrape class).",
|
||||
"format": "int32",
|
||||
|
|
|
@ -7659,6 +7659,11 @@
|
|||
"type": "object",
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
},
|
||||
"serviceName": {
|
||||
"description": "The name of the service name used by the underlying StatefulSet(s) as the governing service.\nIf defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.\nIf empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,\nor `prometheus-agent-operated` for PrometheusAgent resources.\nWhen deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.\nSee https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.",
|
||||
"minLength": 1,
|
||||
"type": "string"
|
||||
},
|
||||
"sha": {
|
||||
"description": "Deprecated: use 'spec.image' instead. The image's digest can be specified as part of the image name.",
|
||||
"type": "string"
|
||||
|
|
|
@ -857,6 +857,16 @@ type CommonPrometheusFields struct {
|
|||
// +optional
|
||||
TSDB *TSDBSpec `json:"tsdb,omitempty"`
|
||||
|
||||
// The name of the service name used by the underlying StatefulSet(s) as the governing service.
|
||||
// If defined, the Service must be created before the Prometheus/PrometheusAgent resource in the same namespace and it must define a selector that matches the pod labels.
|
||||
// If empty, the operator will create and manage a headless service named `prometheus-operated` for Prometheus resources,
|
||||
// or `prometheus-agent-operated` for PrometheusAgent resources.
|
||||
// When deploying multiple Prometheus/PrometheusAgent resources in the same namespace, it is recommended to specify a different value for each.
|
||||
// See https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id for more details.
|
||||
// +optional
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
ServiceName *string `json:"serviceName,omitempty"`
|
||||
|
||||
// RuntimeConfig configures the values for the Prometheus process behavior
|
||||
// +optional
|
||||
Runtime *RuntimeConfig `json:"runtime,omitempty"`
|
||||
|
|
5
pkg/apis/monitoring/v1/zz_generated.deepcopy.go
generated
5
pkg/apis/monitoring/v1/zz_generated.deepcopy.go
generated
|
@ -1035,6 +1035,11 @@ func (in *CommonPrometheusFields) DeepCopyInto(out *CommonPrometheusFields) {
|
|||
*out = new(TSDBSpec)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ServiceName != nil {
|
||||
in, out := &in.ServiceName, &out.ServiceName
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Runtime != nil {
|
||||
in, out := &in.Runtime, &out.Runtime
|
||||
*out = new(RuntimeConfig)
|
||||
|
|
|
@ -115,6 +115,7 @@ type CommonPrometheusFieldsApplyConfiguration struct {
|
|||
ScrapeClasses []ScrapeClassApplyConfiguration `json:"scrapeClasses,omitempty"`
|
||||
ServiceDiscoveryRole *monitoringv1.ServiceDiscoveryRole `json:"serviceDiscoveryRole,omitempty"`
|
||||
TSDB *TSDBSpecApplyConfiguration `json:"tsdb,omitempty"`
|
||||
ServiceName *string `json:"serviceName,omitempty"`
|
||||
Runtime *RuntimeConfigApplyConfiguration `json:"runtime,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -902,6 +903,14 @@ func (b *CommonPrometheusFieldsApplyConfiguration) WithTSDB(value *TSDBSpecApply
|
|||
return b
|
||||
}
|
||||
|
||||
// WithServiceName sets the ServiceName 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 ServiceName field is set to the value of the last call.
|
||||
func (b *CommonPrometheusFieldsApplyConfiguration) WithServiceName(value string) *CommonPrometheusFieldsApplyConfiguration {
|
||||
b.ServiceName = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithRuntime sets the Runtime 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 Runtime field is set to the value of the last call.
|
||||
|
|
|
@ -835,6 +835,14 @@ func (b *PrometheusSpecApplyConfiguration) WithTSDB(value *TSDBSpecApplyConfigur
|
|||
return b
|
||||
}
|
||||
|
||||
// WithServiceName sets the ServiceName 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 ServiceName field is set to the value of the last call.
|
||||
func (b *PrometheusSpecApplyConfiguration) WithServiceName(value string) *PrometheusSpecApplyConfiguration {
|
||||
b.ServiceName = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithRuntime sets the Runtime 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 Runtime field is set to the value of the last call.
|
||||
|
|
|
@ -824,6 +824,14 @@ func (b *PrometheusAgentSpecApplyConfiguration) WithTSDB(value *v1.TSDBSpecApply
|
|||
return b
|
||||
}
|
||||
|
||||
// WithServiceName sets the ServiceName 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 ServiceName field is set to the value of the last call.
|
||||
func (b *PrometheusAgentSpecApplyConfiguration) WithServiceName(value string) *PrometheusAgentSpecApplyConfiguration {
|
||||
b.ServiceName = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithRuntime sets the Runtime 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 Runtime field is set to the value of the last call.
|
||||
|
|
|
@ -692,15 +692,24 @@ func (c *Operator) syncDaemonSet(ctx context.Context, key string, p *monitoringv
|
|||
func (c *Operator) syncStatefulSet(ctx context.Context, key string, p *monitoringv1alpha1.PrometheusAgent, cg *prompkg.ConfigGenerator, tlsAssets *operator.ShardedSecret) error {
|
||||
logger := c.logger.With("key", key)
|
||||
|
||||
// Reconcile the governing service.
|
||||
svc := prompkg.BuildStatefulSetService(
|
||||
governingServiceName,
|
||||
map[string]string{"app.kubernetes.io/name": "prometheus-agent"},
|
||||
p,
|
||||
c.config,
|
||||
)
|
||||
if _, err := k8sutil.CreateOrUpdateService(ctx, c.kclient.CoreV1().Services(p.Namespace), svc); err != nil {
|
||||
return fmt.Errorf("synchronizing governing service failed: %w", err)
|
||||
if p.Spec.ServiceName != nil {
|
||||
svcClient := c.kclient.CoreV1().Services(p.Namespace)
|
||||
selectorLabels := makeSelectorLabels(p.Name)
|
||||
|
||||
if err := prompkg.EnsureCustomGoverningService(ctx, p.Namespace, *p.Spec.ServiceName, svcClient, selectorLabels); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
svc := prompkg.BuildStatefulSetService(
|
||||
governingServiceName,
|
||||
map[string]string{"app.kubernetes.io/name": "prometheus-agent"},
|
||||
p,
|
||||
c.config,
|
||||
)
|
||||
|
||||
if _, err := k8sutil.CreateOrUpdateService(ctx, c.kclient.CoreV1().Services(p.Namespace), svc); err != nil {
|
||||
return fmt.Errorf("synchronizing default governing service failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ssetClient := c.kclient.AppsV1().StatefulSets(p.Namespace)
|
||||
|
|
|
@ -16,6 +16,7 @@ package prometheus
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
|
@ -23,7 +24,9 @@ import (
|
|||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
clientv1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
|
||||
|
@ -474,3 +477,32 @@ func BuildStatefulSetService(name string, selector map[string]string, p monitori
|
|||
|
||||
return svc
|
||||
}
|
||||
|
||||
// This function is responsible for the following:
|
||||
//
|
||||
// Verify that the service exists in the Prometheus/PrometheusAgent resource's namespace
|
||||
// If it does not exist, fail the reconciliation.
|
||||
//
|
||||
// If the ServiceName is specified and a service with the same name exists in the same namespace as the
|
||||
// Prometheus/PrometheusAgent resource, ensure that the custom governing service's selector matches the
|
||||
// Prometheus/PrometheusAgent statefulsets.
|
||||
// If it is not selected, fail the reconciliation
|
||||
// Warning: the function will panic if the resource's ServiceName is nil..
|
||||
func EnsureCustomGoverningService(ctx context.Context, namespace string, serviceName string, svcClient clientv1.ServiceInterface, selectorLabels map[string]string) error {
|
||||
// Check if the custom governing service is defined in the same namespace and selects the Prometheus pod.
|
||||
svc, err := svcClient.Get(ctx, serviceName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get custom governing service %s/%s: %w", namespace, serviceName, err)
|
||||
}
|
||||
|
||||
svcSelector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: svc.Spec.Selector})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse the selector labels for custom governing service %s/%s: %w", namespace, serviceName, err)
|
||||
}
|
||||
|
||||
if !svcSelector.Matches(labels.Set(selectorLabels)) {
|
||||
return fmt.Errorf("custom governing service %s/%s with selector %q does not select Prometheus/PrometheusAgent pods with labels %q",
|
||||
namespace, serviceName, svcSelector.String(), labels.Set(selectorLabels).String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -15,11 +15,14 @@
|
|||
package prometheus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
|
||||
|
@ -282,3 +285,153 @@ func TestBuildCommonPrometheusArgsWithOTLPReceiver(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureCustomGoverningService(t *testing.T) {
|
||||
name := "test-prometheus"
|
||||
serviceName := "test-svc"
|
||||
ns := "test-ns"
|
||||
testcases := []struct {
|
||||
name string
|
||||
service v1.Service
|
||||
selectorLabels map[string]string
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "custom service selects prometheus",
|
||||
service: v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: serviceName,
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
},
|
||||
},
|
||||
selectorLabels: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "custom service does not select prometheus",
|
||||
service: v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-svc",
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"prometheus": "different-name",
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": "different-name",
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
},
|
||||
},
|
||||
selectorLabels: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "custom service selects prometheus but in different ns",
|
||||
service: v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-svc",
|
||||
Namespace: "wrong-ns",
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
},
|
||||
},
|
||||
selectorLabels: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "custom service selects prometheus but in different ns",
|
||||
service: v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-svc",
|
||||
Namespace: "wrong-ns",
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
},
|
||||
},
|
||||
selectorLabels: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "custom svc doesn't exist",
|
||||
selectorLabels: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
p := makeBarebonesPrometheus(name, ns)
|
||||
p.Spec.ServiceName = &serviceName
|
||||
|
||||
clientSet := fake.NewSimpleClientset(&tc.service)
|
||||
svcClient := clientSet.CoreV1().Services(ns)
|
||||
|
||||
err := EnsureCustomGoverningService(context.Background(), p.Namespace, *p.Spec.ServiceName, svcClient, tc.selectorLabels)
|
||||
if tc.expectedErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func makeBarebonesPrometheus(name, ns string) *monitoringv1.Prometheus {
|
||||
return &monitoringv1.Prometheus{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: ns,
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
Spec: monitoringv1.PrometheusSpec{
|
||||
CommonPrometheusFields: monitoringv1.CommonPrometheusFields{
|
||||
Replicas: ptr.To(int32(1)),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -797,24 +797,33 @@ func (c *Operator) sync(ctx context.Context, key string) error {
|
|||
return fmt.Errorf("failed to reconcile Thanos config secret: %w", err)
|
||||
}
|
||||
|
||||
// Reconcile the governing service.
|
||||
svc := prompkg.BuildStatefulSetService(
|
||||
governingServiceName,
|
||||
map[string]string{"app.kubernetes.io/name": "prometheus"},
|
||||
p,
|
||||
c.config,
|
||||
)
|
||||
if p.Spec.ServiceName != nil {
|
||||
svcClient := c.kclient.CoreV1().Services(p.Namespace)
|
||||
selectorLabels := makeSelectorLabels(p.Name)
|
||||
|
||||
if p.Spec.Thanos != nil {
|
||||
svc.Spec.Ports = append(svc.Spec.Ports, v1.ServicePort{
|
||||
Name: "grpc",
|
||||
Port: 10901,
|
||||
TargetPort: intstr.FromString("grpc"),
|
||||
})
|
||||
}
|
||||
if err := prompkg.EnsureCustomGoverningService(ctx, p.Namespace, *p.Spec.ServiceName, svcClient, selectorLabels); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Reconcile the default governing service.
|
||||
svc := prompkg.BuildStatefulSetService(
|
||||
governingServiceName,
|
||||
map[string]string{"app.kubernetes.io/name": "prometheus"},
|
||||
p,
|
||||
c.config,
|
||||
)
|
||||
|
||||
if _, err := k8sutil.CreateOrUpdateService(ctx, c.kclient.CoreV1().Services(p.Namespace), svc); err != nil {
|
||||
return fmt.Errorf("synchronizing governing service failed: %w", err)
|
||||
if p.Spec.Thanos != nil {
|
||||
svc.Spec.Ports = append(svc.Spec.Ports, v1.ServicePort{
|
||||
Name: "grpc",
|
||||
Port: 10901,
|
||||
TargetPort: intstr.FromString("grpc"),
|
||||
})
|
||||
}
|
||||
|
||||
if _, err := k8sutil.CreateOrUpdateService(ctx, c.kclient.CoreV1().Services(p.Namespace), svc); err != nil {
|
||||
return fmt.Errorf("synchronizing default governing service failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ssetClient := c.kclient.AppsV1().StatefulSets(p.Namespace)
|
||||
|
|
|
@ -304,6 +304,8 @@ func testAllNSPrometheus(t *testing.T) {
|
|||
"PrometheusAgentStatusScale": testPrometheusAgentStatusScale,
|
||||
"PrometheusStatusScale": testPrometheusStatusScale,
|
||||
"ScrapeConfigCRDValidations": testScrapeConfigCRDValidations,
|
||||
"PrometheusServiceName": testPrometheusServiceName,
|
||||
"PrometheusAgentSSetServiceName": testPrometheusAgentSSetServiceName,
|
||||
}
|
||||
|
||||
for name, f := range testFuncs {
|
||||
|
|
|
@ -5300,6 +5300,57 @@ func testPrometheusStatusScale(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testPrometheusServiceName(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCtx := framework.NewTestCtx(t)
|
||||
defer testCtx.Cleanup(t)
|
||||
ns := framework.CreateNamespace(context.Background(), t, testCtx)
|
||||
name := "test-servicename"
|
||||
|
||||
svc := &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("%s-service", name),
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Name: "web",
|
||||
Port: 9090,
|
||||
},
|
||||
},
|
||||
Selector: map[string]string{
|
||||
"prometheus": name,
|
||||
"app.kubernetes.io/name": "prometheus",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := framework.KubeClient.CoreV1().Services(ns).Create(context.Background(), svc, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
framework.SetupPrometheusRBAC(context.Background(), t, testCtx, ns)
|
||||
|
||||
p := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
p.Spec.ServiceName = &svc.Name
|
||||
|
||||
_, err = framework.CreatePrometheusAndWaitUntilReady(context.Background(), ns, p)
|
||||
require.NoError(t, err)
|
||||
|
||||
targets, err := framework.GetActiveTargets(context.Background(), ns, svc.Name)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, targets)
|
||||
|
||||
// Ensure that the default governing service was not created by the operator.
|
||||
svcList, err := framework.KubeClient.CoreV1().Services(ns).List(context.Background(), metav1.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, svcList.Items, 1)
|
||||
require.Equal(t, svcList.Items[0].Name, svc.Name)
|
||||
}
|
||||
|
||||
func isAlertmanagerDiscoveryWorking(ns, promSVCName, alertmanagerName string) func(ctx context.Context) (bool, error) {
|
||||
return func(ctx context.Context) (bool, error) {
|
||||
pods, err := framework.KubeClient.CoreV1().Pods(ns).List(ctx, alertmanager.ListOptions(alertmanagerName))
|
||||
|
|
|
@ -576,6 +576,57 @@ func testPrometheusAgentDaemonSetSelectPodMonitor(t *testing.T) {
|
|||
require.NotEqual(t, firstTargetIP, secondTargetIP)
|
||||
}
|
||||
|
||||
func testPrometheusAgentSSetServiceName(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCtx := framework.NewTestCtx(t)
|
||||
defer testCtx.Cleanup(t)
|
||||
ns := framework.CreateNamespace(context.Background(), t, testCtx)
|
||||
name := "test-agent-servicename"
|
||||
|
||||
svc := &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("%s-service", name),
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
Ports: []v1.ServicePort{
|
||||
{
|
||||
Name: "web",
|
||||
Port: 9090,
|
||||
},
|
||||
},
|
||||
Selector: map[string]string{
|
||||
"app.kubernetes.io/name": "prometheus-agent",
|
||||
"app.kubernetes.io/instance": name,
|
||||
"app.kubernetes.io/managed-by": "prometheus-operator",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := framework.KubeClient.CoreV1().Services(ns).Create(context.Background(), svc, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
framework.SetupPrometheusRBAC(context.Background(), t, testCtx, ns)
|
||||
|
||||
p := framework.MakeBasicPrometheusAgent(ns, name, name, 1)
|
||||
p.Spec.ServiceName = &svc.Name
|
||||
|
||||
_, err = framework.CreatePrometheusAgentAndWaitUntilReady(context.Background(), ns, p)
|
||||
require.NoError(t, err)
|
||||
|
||||
targets, err := framework.GetActiveTargets(context.Background(), ns, svc.Name)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, targets)
|
||||
|
||||
// Ensure that the default governing service was not created by the operator.
|
||||
svcList, err := framework.KubeClient.CoreV1().Services(ns).List(context.Background(), metav1.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, svcList.Items, 1)
|
||||
require.Equal(t, svcList.Items[0].Name, svc.Name)
|
||||
|
||||
}
|
||||
|
||||
type Target struct {
|
||||
Labels struct {
|
||||
Instance string `json:"instance"`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue