1
0
mirror of https://github.com/coreos/prometheus-operator.git synced 2026-02-05 15:46:31 +01:00

chore: add well-known labels to statefulsets

Signed-off-by: Simon Pasquier <spasquie@redhat.com>
This commit is contained in:
Simon Pasquier
2025-08-07 11:42:34 +02:00
parent fc4bab09f7
commit 40ceb1c16c
14 changed files with 149 additions and 32 deletions

View File

@@ -1,6 +1,7 @@
## Unreleased
* [CHANGE/BUGFIX] Add the `--watch-referenced-objects-in-all-namespaces` CLI argument. When enabled, the operator watches for secrets and configmaps in both workload and configuration resources. It ensures that reconciliation happens when a referenced secret/configmap is updated. #7615
* [ENHANCEMENT] Add well-known Kubernetes labels to workload objects managed by the operator (StatefulSet and DaemonSet). #7786
## 0.84.0 / 2025-07-14

View File

@@ -275,6 +275,16 @@ func (c *Operator) bootstrap(ctx context.Context, config operator.Config) error
c.kclient,
resyncPeriod,
func(options *metav1.ListOptions) {
// TODO(simonpasquier): use a more restrictive label selector
// selecting only Alertmanager statefulsets (e.g.
// "app.kubernetes.io/name in (alertmanager)").
//
// We need to wait for a couple of releases after [1] merges to
// ensure that the expected labels have been propagated to the
// Alertmanager statefulsets otherwise the informer won't
// select any object.
//
// [1] https://github.com/prometheus-operator/prometheus-operator/pull/7786
options.LabelSelector = operator.ManagedByOperatorLabelSelector()
},
),

View File

@@ -110,10 +110,11 @@ func makeStatefulSet(logger *slog.Logger, am *monitoringv1.Alertmanager, config
operator.UpdateObject(
statefulset,
operator.WithName(prefixedName(am.Name)),
operator.WithInputHashAnnotation(inputHash),
operator.WithAnnotations(am.GetAnnotations()),
operator.WithAnnotations(config.Annotations),
operator.WithInputHashAnnotation(inputHash),
operator.WithLabels(am.GetLabels()),
operator.WithSelectorLabels(spec.Selector),
operator.WithLabels(config.Labels),
operator.WithManagingOwner(am),
operator.WithoutKubectlAnnotations(),

View File

@@ -54,29 +54,35 @@ func TestStatefulSetLabelingAndAnnotations(t *testing.T) {
// kubectl annotations must not be on the statefulset so kubectl does
// not manage the generated object
expectedStatefulSetAnnotations := map[string]string{
"prometheus-operator-input-hash": "",
"prometheus-operator-input-hash": "abc",
"testannotation": "testannotationvalue",
}
expectedStatefulSetLabels := map[string]string{
"testlabel": "testlabelvalue",
"managed-by": "prometheus-operator",
"testlabel": "testlabelvalue",
"managed-by": "prometheus-operator",
"alertmanager": "test",
"app.kubernetes.io/instance": "test",
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/name": "alertmanager",
}
expectedPodLabels := map[string]string{
"alertmanager": "",
"alertmanager": "test",
"app.kubernetes.io/name": "alertmanager",
"app.kubernetes.io/version": strings.TrimPrefix(operator.DefaultAlertmanagerVersion, "v"),
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/instance": "",
"app.kubernetes.io/instance": "test",
}
sset, err := makeStatefulSet(nil, &monitoringv1.Alertmanager{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns",
Labels: labels,
Annotations: annotations,
},
}, defaultTestConfig, "", &operator.ShardedSecret{})
}, defaultTestConfig, "abc", &operator.ShardedSecret{})
require.NoError(t, err)

View File

@@ -105,6 +105,23 @@ func WithLabels(labels map[string]string) ObjectOption {
}
}
// WithSelectorLabels merges the labels from the selector with the existing
// object's labels.
// The selector's labels take precedence over the existing ones.
func WithSelectorLabels(selector *metav1.LabelSelector) ObjectOption {
return func(o metav1.Object) {
if selector == nil {
return
}
l := Map{}
l = l.Merge(selector.MatchLabels)
l = l.Merge(o.GetLabels())
o.SetLabels(l)
}
}
// WithAnnotations merges the given annotations with the existing object's annotations.
// The given annotations take precedence over the existing ones.
func WithAnnotations(annotations map[string]string) ObjectOption {

View File

@@ -58,9 +58,9 @@ func makeDaemonSet(
operator.WithAnnotations(config.Annotations),
operator.WithLabels(objMeta.GetLabels()),
operator.WithLabels(map[string]string{
prompkg.PrometheusNameLabelName: objMeta.GetName(),
prompkg.PrometheusModeLabelName: prometheusMode,
}),
operator.WithSelectorLabels(spec.Selector),
operator.WithLabels(config.Labels),
operator.WithManagingOwner(p),
operator.WithoutKubectlAnnotations(),

View File

@@ -156,22 +156,27 @@ func TestDaemonSetLabelingAndAnnotations(t *testing.T) {
}
expectedDaemonSetLabels := map[string]string{
"testlabel": "testlabelvalue",
"operator.prometheus.io/name": "",
"operator.prometheus.io/mode": "agent",
"managed-by": "prometheus-operator",
"testlabel": "testlabelvalue",
"operator.prometheus.io/name": "test",
"operator.prometheus.io/mode": "agent",
"managed-by": "prometheus-operator",
"app.kubernetes.io/instance": "test",
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/name": "prometheus-agent",
}
expectedPodLabels := map[string]string{
"app.kubernetes.io/name": "prometheus-agent",
"app.kubernetes.io/version": strings.TrimPrefix(operator.DefaultPrometheusVersion, "v"),
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/instance": "",
"operator.prometheus.io/name": "",
"app.kubernetes.io/instance": "test",
"operator.prometheus.io/name": "test",
}
dset, err := makeDaemonSetFromPrometheus(monitoringv1alpha1.PrometheusAgent{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns",
Labels: labels,
Annotations: annotations,
},

View File

@@ -65,15 +65,14 @@ func makeStatefulSet(
operator.UpdateObject(
statefulset,
operator.WithName(name),
operator.WithInputHashAnnotation(inputHash),
operator.WithAnnotations(objMeta.GetAnnotations()),
operator.WithAnnotations(config.Annotations),
operator.WithInputHashAnnotation(inputHash),
operator.WithLabels(objMeta.GetLabels()),
operator.WithLabels(map[string]string{
prompkg.ShardLabelName: fmt.Sprintf("%d", shard),
prompkg.PrometheusNameLabelName: objMeta.GetName(),
prompkg.PrometheusModeLabelName: prometheusMode,
}),
operator.WithSelectorLabels(spec.Selector),
operator.WithLabels(config.Labels),
operator.WithManagingOwner(p),
operator.WithoutKubectlAnnotations(),

View File

@@ -15,6 +15,7 @@
package prometheusagent
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -147,7 +148,7 @@ func makeStatefulSetFromPrometheus(p monitoringv1alpha1.PrometheusAgent) (*appsv
&p,
defaultTestConfig,
cg,
"",
"abc",
0,
&operator.ShardedSecret{})
}
@@ -333,6 +334,58 @@ func TestScrapeFailureLogFileVolumeMountNotPresent(t *testing.T) {
require.False(t, found, "Scrape failure log file mounted, when it shouldn't be.")
}
func TestStatefulSetLabelingAndAnnotations(t *testing.T) {
labels := map[string]string{
"testlabel": "testlabelvalue",
}
annotations := map[string]string{
"testannotation": "testannotationvalue",
"kubectl.kubernetes.io/last-applied-configuration": "something",
"kubectl.kubernetes.io/something": "something",
}
// kubectl annotations must not be on the statefulset so kubectl does
// not manage the generated object
expectedStatefulSetAnnotations := map[string]string{
"prometheus-operator-input-hash": "abc",
"testannotation": "testannotationvalue",
}
expectedStatefulSetLabels := map[string]string{
"testlabel": "testlabelvalue",
"operator.prometheus.io/name": "test",
"operator.prometheus.io/shard": "0",
"operator.prometheus.io/mode": "agent",
"managed-by": "prometheus-operator",
"app.kubernetes.io/instance": "test",
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/name": "prometheus-agent",
}
expectedPodLabels := map[string]string{
"app.kubernetes.io/name": "prometheus-agent",
"app.kubernetes.io/version": strings.TrimPrefix(operator.DefaultPrometheusVersion, "v"),
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/instance": "test",
"operator.prometheus.io/name": "test",
"operator.prometheus.io/shard": "0",
}
sset, err := makeStatefulSetFromPrometheus(monitoringv1alpha1.PrometheusAgent{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns",
Labels: labels,
Annotations: annotations,
},
})
require.NoError(t, err)
require.Equal(t, expectedStatefulSetLabels, sset.Labels)
require.Equal(t, expectedStatefulSetAnnotations, sset.Annotations)
require.Equal(t, expectedPodLabels, sset.Spec.Template.ObjectMeta.Labels)
}
func TestStatefulSetenableServiceLinks(t *testing.T) {
tests := []struct {
enableServiceLinks *bool

View File

@@ -70,15 +70,14 @@ func makeStatefulSet(
operator.UpdateObject(
statefulset,
operator.WithName(name),
operator.WithInputHashAnnotation(inputHash),
operator.WithAnnotations(objMeta.GetAnnotations()),
operator.WithAnnotations(config.Annotations),
operator.WithInputHashAnnotation(inputHash),
operator.WithLabels(objMeta.GetLabels()),
operator.WithLabels(map[string]string{
prompkg.ShardLabelName: fmt.Sprintf("%d", shard),
prompkg.PrometheusNameLabelName: objMeta.GetName(),
prompkg.PrometheusModeLabelName: prometheusMode,
}),
operator.WithSelectorLabels(spec.Selector),
operator.WithLabels(config.Labels),
operator.WithManagingOwner(p),
operator.WithoutKubectlAnnotations(),

View File

@@ -59,7 +59,7 @@ func makeStatefulSetFromPrometheus(p monitoringv1.Prometheus) (*appsv1.StatefulS
defaultTestConfig,
cg,
nil,
"",
"abc",
0,
&operator.ShardedSecret{})
}
@@ -73,33 +73,40 @@ func TestStatefulSetLabelingAndAnnotations(t *testing.T) {
"kubectl.kubernetes.io/last-applied-configuration": "something",
"kubectl.kubernetes.io/something": "something",
}
// kubectl annotations must not be on the statefulset so kubectl does
// not manage the generated object
expectedStatefulSetAnnotations := map[string]string{
"prometheus-operator-input-hash": "",
"prometheus-operator-input-hash": "abc",
"testannotation": "testannotationvalue",
}
expectedStatefulSetLabels := map[string]string{
"testlabel": "testlabelvalue",
"operator.prometheus.io/name": "",
"operator.prometheus.io/name": "test",
"operator.prometheus.io/shard": "0",
"operator.prometheus.io/mode": "server",
"managed-by": "prometheus-operator",
"prometheus": "test",
"app.kubernetes.io/instance": "test",
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/name": "prometheus",
}
expectedPodLabels := map[string]string{
"prometheus": "",
"prometheus": "test",
"app.kubernetes.io/name": "prometheus",
"app.kubernetes.io/version": strings.TrimPrefix(operator.DefaultPrometheusVersion, "v"),
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/instance": "",
"operator.prometheus.io/name": "",
"app.kubernetes.io/instance": "test",
"operator.prometheus.io/name": "test",
"operator.prometheus.io/shard": "0",
}
sset, err := makeStatefulSetFromPrometheus(monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns",
Labels: labels,
Annotations: annotations,
},

View File

@@ -227,6 +227,16 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger
o.kclient,
resyncPeriod,
func(options *metav1.ListOptions) {
// TODO(simonpasquier): use a more restrictive label selector
// selecting only ThanosRuler statefulsets (e.g.
// "app.kubernetes.io/name in (thanos-ruler)").
//
// We need to wait for a couple of releases after [1] to ensure
// that the expected labels have been propagated to the
// ThanosRuler statefulsets otherwise the informer won't select
// any object.
//
// [1] https://github.com/prometheus-operator/prometheus-operator/pull/7786
options.LabelSelector = operator.ManagedByOperatorLabelSelector()
},
),

View File

@@ -75,10 +75,11 @@ func makeStatefulSet(tr *monitoringv1.ThanosRuler, config Config, ruleConfigMapN
operator.UpdateObject(
statefulset,
operator.WithName(prefixedName(tr.Name)),
operator.WithInputHashAnnotation(inputHash),
operator.WithAnnotations(tr.GetAnnotations()),
operator.WithAnnotations(config.Annotations),
operator.WithInputHashAnnotation(inputHash),
operator.WithLabels(tr.GetLabels()),
operator.WithSelectorLabels(spec.Selector),
operator.WithLabels(config.Labels),
operator.WithManagingOwner(tr),
operator.WithoutKubectlAnnotations(),

View File

@@ -44,28 +44,36 @@ var (
func TestStatefulSetLabelingAndAnnotations(t *testing.T) {
labels := map[string]string{
"testlabel": "testlabelvalue",
"managed-by": "prometheus-operator",
"testlabel": "testlabelvalue",
"managed-by": "prometheus-operator",
"thanos-ruler": "test",
"app.kubernetes.io/instance": "test",
"app.kubernetes.io/managed-by": "prometheus-operator",
"app.kubernetes.io/name": "thanos-ruler",
}
annotations := map[string]string{
"testannotation": "testannotationvalue",
"kubectl.kubernetes.io/last-applied-configuration": "something",
"kubectl.kubernetes.io/something": "something",
}
// kubectl annotations must not be on the statefulset so kubectl does
// not manage the generated object
expectedAnnotations := map[string]string{
"prometheus-operator-input-hash": "",
"prometheus-operator-input-hash": "abc",
"testannotation": "testannotationvalue",
}
sset, err := makeStatefulSet(&monitoringv1.ThanosRuler{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns",
Labels: labels,
Annotations: annotations,
},
Spec: monitoringv1.ThanosRulerSpec{QueryEndpoints: emptyQueryEndpoints},
}, defaultTestConfig, nil, "", &operator.ShardedSecret{})
}, defaultTestConfig, nil, "abc", &operator.ShardedSecret{})
require.NoError(t, err)