1
0
Fork 0
mirror of https://github.com/prometheus-operator/prometheus-operator.git synced 2025-04-16 01:06:27 +00:00

prometheus: enforce external labels

Add external labels `prometheus` and `prometheus_replica` via Pod env
variables and Prometheus config expansion.
This commit is contained in:
Fabian Reinartz 2018-03-22 15:59:22 +01:00 committed by Max Leonard Inden
parent df92241c26
commit 50d7b9f56e
No known key found for this signature in database
GPG key ID: 5403C5464810BC26
8 changed files with 86 additions and 70 deletions

View file

@ -50,7 +50,7 @@ func init() {
flagset.StringVar(&cfg.TLSConfig.CAFile, "ca-file", "", "- NOT RECOMMENDED FOR PRODUCTION - Path to TLS CA file.") flagset.StringVar(&cfg.TLSConfig.CAFile, "ca-file", "", "- NOT RECOMMENDED FOR PRODUCTION - Path to TLS CA file.")
flagset.StringVar(&cfg.KubeletObject, "kubelet-service", "", "Service/Endpoints object to write kubelets into in format \"namespace/name\"") flagset.StringVar(&cfg.KubeletObject, "kubelet-service", "", "Service/Endpoints object to write kubelets into in format \"namespace/name\"")
flagset.BoolVar(&cfg.TLSInsecure, "tls-insecure", false, "- NOT RECOMMENDED FOR PRODUCTION - Don't verify API server's CA certificate.") flagset.BoolVar(&cfg.TLSInsecure, "tls-insecure", false, "- NOT RECOMMENDED FOR PRODUCTION - Don't verify API server's CA certificate.")
flagset.StringVar(&cfg.PrometheusConfigReloader, "prometheus-config-reloader", "quay.io/coreos/prometheus-config-reloader:v0.0.3", "Config and rule reload image") flagset.StringVar(&cfg.PrometheusConfigReloader, "prometheus-config-reloader", "quay.io/coreos/prometheus-config-reloader:v0.0.4", "Config and rule reload image")
flagset.StringVar(&cfg.ConfigReloaderImage, "config-reloader-image", "quay.io/coreos/configmap-reload:v0.0.1", "Reload Image") flagset.StringVar(&cfg.ConfigReloaderImage, "config-reloader-image", "quay.io/coreos/configmap-reload:v0.0.1", "Reload Image")
flagset.StringVar(&cfg.AlertmanagerDefaultBaseImage, "alertmanager-default-base-image", "quay.io/prometheus/alertmanager", "Alertmanager default base image") flagset.StringVar(&cfg.AlertmanagerDefaultBaseImage, "alertmanager-default-base-image", "quay.io/prometheus/alertmanager", "Alertmanager default base image")
flagset.StringVar(&cfg.PrometheusDefaultBaseImage, "prometheus-default-base-image", "quay.io/prometheus/prometheus", "Prometheus default base image") flagset.StringVar(&cfg.PrometheusDefaultBaseImage, "prometheus-default-base-image", "quay.io/prometheus/prometheus", "Prometheus default base image")

View file

@ -30,7 +30,7 @@ spec:
mountPath: /etc/prometheus/rules mountPath: /etc/prometheus/rules
readOnly: true readOnly: true
- name: prometheus-config-reloader - name: prometheus-config-reloader
image: quay.io/coreos/prometheus-config-reloader:v0.0.3 image: quay.io/coreos/prometheus-config-reloader:v0.0.4
args: args:
- '-config-volume-dir=/etc/prometheus/config' - '-config-volume-dir=/etc/prometheus/config'
- '-rule-volume-dir=/etc/prometheus/rules' - '-rule-volume-dir=/etc/prometheus/rules'

View file

@ -186,7 +186,6 @@ func (rf *ruleFetcher) refresh(ctx context.Context, cms []*configMapRef) error {
return err return err
} }
} }
return nil
} }
if err := os.RemoveAll(rf.outDir); err != nil { if err := os.RemoveAll(rf.outDir); err != nil {

View file

@ -45,8 +45,6 @@ import (
) )
const ( const (
configFilename = "prometheus.yaml"
resyncPeriod = 5 * time.Minute resyncPeriod = 5 * time.Minute
) )
@ -1015,10 +1013,12 @@ func (c *Operator) createConfig(p *monitoringv1.Prometheus, ruleFileConfigMaps [
return err return err
} }
generatedConf := s.Data[configFilename] var (
generatedConfigMaps := s.Data[configMapsFilename] generatedConf = s.Data[configFilename]
curConfig, curConfigFound := curSecret.Data[configFilename] generatedConfigMaps = s.Data[ruleConfigmapsFilename]
curConfigMaps, curConfigMapsFound := curSecret.Data[configMapsFilename] curConfig, curConfigFound = curSecret.Data[configFilename]
curConfigMaps, curConfigMapsFound = curSecret.Data[ruleConfigmapsFilename]
)
if curConfigFound && curConfigMapsFound { if curConfigFound && curConfigMapsFound {
if bytes.Equal(curConfig, generatedConf) && bytes.Equal(curConfigMaps, generatedConfigMaps) { if bytes.Equal(curConfig, generatedConf) && bytes.Equal(curConfigMaps, generatedConfigMaps) {
c.logger.Log("msg", "updating config skipped, no configuration change") c.logger.Log("msg", "updating config skipped, no configuration change")

View file

@ -37,7 +37,7 @@ func sanitizeLabelName(name string) string {
} }
func configMapRuleFileFolder(configMapNumber int) string { func configMapRuleFileFolder(configMapNumber int) string {
return fmt.Sprintf("/etc/prometheus/rules/rules-%d/", configMapNumber) return fmt.Sprintf("/etc/prometheus/config_out/rules/rules-%d/", configMapNumber)
} }
func stringMapToMapSlice(m map[string]string) yaml.MapSlice { func stringMapToMapSlice(m map[string]string) yaml.MapSlice {
@ -78,6 +78,18 @@ func addTLStoYaml(cfg yaml.MapSlice, tls *v1.TLSConfig) yaml.MapSlice {
return cfg return cfg
} }
func buildExternalLabels(p *v1.Prometheus) yaml.MapSlice {
m := map[string]string{}
m["prometheus"] = fmt.Sprintf("%s/%s", p.Namespace, p.Name)
m["prometheus_replica"] = "$(POD_NAME)"
for n, v := range p.Spec.ExternalLabels {
m[n] = v
}
return stringMapToMapSlice(m)
}
func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleConfigMaps int, basicAuthSecrets map[string]BasicAuthCredentials) ([]byte, error) { func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleConfigMaps int, basicAuthSecrets map[string]BasicAuthCredentials) ([]byte, error) {
versionStr := p.Spec.Version versionStr := p.Spec.Version
if versionStr == "" { if versionStr == "" {
@ -106,7 +118,7 @@ func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleCo
Value: yaml.MapSlice{ Value: yaml.MapSlice{
{Key: "evaluation_interval", Value: evaluationInterval}, {Key: "evaluation_interval", Value: evaluationInterval},
{Key: "scrape_interval", Value: scrapeInterval}, {Key: "scrape_interval", Value: scrapeInterval},
{Key: "external_labels", Value: stringMapToMapSlice(p.Spec.ExternalLabels)}, {Key: "external_labels", Value: buildExternalLabels(p)},
}, },
}) })
@ -231,20 +243,17 @@ func generateServiceMonitorConfig(version semver.Version, m *v1.ServiceMonitor,
// Filter targets by services selected by the monitor. // Filter targets by services selected by the monitor.
// Exact label matches. // Exact label matches.
labelKeys := make([]string, len(m.Spec.Selector.MatchLabels)) var labelKeys []string
i = 0 for k := range m.Spec.Selector.MatchLabels {
for k, _ := range m.Spec.Selector.MatchLabels { labelKeys = append(labelKeys, k)
labelKeys[i] = k
i++
} }
sort.Strings(labelKeys) sort.Strings(labelKeys)
for i := range labelKeys {
k := labelKeys[i] for _, k := range labelKeys {
v := m.Spec.Selector.MatchLabels[k]
relabelings = append(relabelings, yaml.MapSlice{ relabelings = append(relabelings, yaml.MapSlice{
{Key: "action", Value: "keep"}, {Key: "action", Value: "keep"},
{Key: "source_labels", Value: []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(k)}}, {Key: "source_labels", Value: []string{"__meta_kubernetes_service_label_" + sanitizeLabelName(k)}},
{Key: "regex", Value: v}, {Key: "regex", Value: m.Spec.Selector.MatchLabels[k]},
}) })
} }
// Set based label matching. We have to map the valid relations // Set based label matching. We have to map the valid relations

View file

@ -117,7 +117,9 @@ func TestAlertmanagerBearerToken(t *testing.T) {
expected := `global: expected := `global:
evaluation_interval: 30s evaluation_interval: 30s
scrape_interval: 30s scrape_interval: 30s
external_labels: {} external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
scrape_configs: [] scrape_configs: []
alerting: alerting:
alertmanagers: alertmanagers:

View file

@ -36,15 +36,17 @@ import (
) )
const ( const (
governingServiceName = "prometheus-operated" governingServiceName = "prometheus-operated"
DefaultVersion = "v2.2.1" DefaultVersion = "v2.2.1"
defaultRetention = "24h" defaultRetention = "24h"
configMapsFilename = "configmaps.json" storageDir = "/prometheus"
prometheusConfDir = "/etc/prometheus/config" confDir = "/etc/prometheus/config"
prometheusConfFile = prometheusConfDir + "/prometheus.yaml" confOutDir = "/etc/prometheus/config_out"
prometheusStorageDir = "/prometheus" rulesDir = "/etc/prometheus/config_out/rules"
prometheusRulesDir = "/etc/prometheus/rules" secretsDir = "/etc/prometheus/secrets/"
prometheusSecretsDir = "/etc/prometheus/secrets/" configFilename = "prometheus.yaml"
configEnvsubstFilename = "prometheus.env.yaml"
ruleConfigmapsFilename = "configmaps.json"
) )
var ( var (
@ -274,8 +276,8 @@ func makeConfigSecret(p *monitoringv1.Prometheus, configMaps []*v1.ConfigMap, co
}, },
}, },
Data: map[string][]byte{ Data: map[string][]byte{
configFilename: []byte{}, configFilename: []byte{},
configMapsFilename: b, ruleConfigmapsFilename: b,
}, },
}, nil }, nil
} }
@ -325,9 +327,10 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
promArgs = append(promArgs, promArgs = append(promArgs,
"-storage.local.retention="+p.Spec.Retention, "-storage.local.retention="+p.Spec.Retention,
"-storage.local.num-fingerprint-mutexes=4096", "-storage.local.num-fingerprint-mutexes=4096",
fmt.Sprintf("-storage.local.path=%s", prometheusStorageDir), fmt.Sprintf("-storage.local.path=%s", storageDir),
"-storage.local.chunk-encoding-version=2", "-storage.local.chunk-encoding-version=2",
fmt.Sprintf("-config.file=%s", prometheusConfFile)) fmt.Sprintf("-config.file=%s", path.Join(confOutDir, configEnvsubstFilename)),
)
// We attempt to specify decent storage tuning flags based on how much the // We attempt to specify decent storage tuning flags based on how much the
// requested memory can fit. The user has to specify an appropriate buffering // requested memory can fit. The user has to specify an appropriate buffering
// in memory limits to catch increased memory usage during query bursts. // in memory limits to catch increased memory usage during query bursts.
@ -356,8 +359,8 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
securityContext = &v1.PodSecurityContext{} securityContext = &v1.PodSecurityContext{}
case 2: case 2:
promArgs = append(promArgs, promArgs = append(promArgs,
fmt.Sprintf("-config.file=%s", prometheusConfFile), fmt.Sprintf("-config.file=%s", path.Join(confOutDir, configEnvsubstFilename)),
fmt.Sprintf("-storage.tsdb.path=%s", prometheusStorageDir), fmt.Sprintf("-storage.tsdb.path=%s", storageDir),
"-storage.tsdb.retention="+p.Spec.Retention, "-storage.tsdb.retention="+p.Spec.Retention,
"-web.enable-lifecycle", "-web.enable-lifecycle",
"-storage.tsdb.no-lockfile", "-storage.tsdb.no-lockfile",
@ -430,7 +433,7 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
}, },
}, },
{ {
Name: "rules", Name: "config-out",
VolumeSource: v1.VolumeSource{ VolumeSource: v1.VolumeSource{
EmptyDir: &v1.EmptyDirVolumeSource{}, EmptyDir: &v1.EmptyDirVolumeSource{},
}, },
@ -439,18 +442,13 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
promVolumeMounts := []v1.VolumeMount{ promVolumeMounts := []v1.VolumeMount{
{ {
Name: "config", Name: "config-out",
ReadOnly: true, ReadOnly: true,
MountPath: prometheusConfDir, MountPath: confOutDir,
},
{
Name: "rules",
ReadOnly: true,
MountPath: prometheusRulesDir,
}, },
{ {
Name: volumeName(p.Name), Name: volumeName(p.Name),
MountPath: prometheusStorageDir, MountPath: storageDir,
SubPath: subPathForStorage(p.Spec.Storage), SubPath: subPathForStorage(p.Spec.Storage),
}, },
} }
@ -467,26 +465,27 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
promVolumeMounts = append(promVolumeMounts, v1.VolumeMount{ promVolumeMounts = append(promVolumeMounts, v1.VolumeMount{
Name: "secret-" + s, Name: "secret-" + s,
ReadOnly: true, ReadOnly: true,
MountPath: prometheusSecretsDir + s, MountPath: secretsDir + s,
}) })
} }
configReloadVolumeMounts := []v1.VolumeMount{ configReloadVolumeMounts := []v1.VolumeMount{
{ {
Name: "config", Name: "config",
ReadOnly: true, MountPath: confDir,
MountPath: prometheusConfDir,
}, },
{ {
Name: "rules", Name: "config-out",
MountPath: prometheusRulesDir, MountPath: confOutDir,
}, },
} }
configReloadArgs := []string{ configReloadArgs := []string{
fmt.Sprintf("-reload-url=%s", localReloadURL), fmt.Sprintf("--reload-url=%s", localReloadURL),
fmt.Sprintf("-config-volume-dir=%s", prometheusConfDir), fmt.Sprintf("--config-file=%s", path.Join(confDir, configFilename)),
fmt.Sprintf("-rule-volume-dir=%s", prometheusRulesDir), fmt.Sprintf("--rule-list-file=%s", path.Join(confDir, ruleConfigmapsFilename)),
fmt.Sprintf("--config-envsubst-file=%s", path.Join(confOutDir, configEnvsubstFilename)),
fmt.Sprintf("--rule-dir=%s", rulesDir),
} }
var livenessProbeHandler v1.Handler var livenessProbeHandler v1.Handler
@ -551,10 +550,10 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
} }
} }
} }
podLabels["app"] = "prometheus" podLabels["app"] = "prometheus"
podLabels["prometheus"] = p.Name podLabels["prometheus"] = p.Name
finalLabels := c.Labels.Merge(podLabels)
return &appsv1.StatefulSetSpec{ return &appsv1.StatefulSetSpec{
ServiceName: governingServiceName, ServiceName: governingServiceName,
Replicas: p.Spec.Replicas, Replicas: p.Spec.Replicas,
@ -562,12 +561,9 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
UpdateStrategy: appsv1.StatefulSetUpdateStrategy{ UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
Type: appsv1.RollingUpdateStatefulSetStrategyType, Type: appsv1.RollingUpdateStatefulSetStrategyType,
}, },
Selector: &metav1.LabelSelector{
MatchLabels: finalLabels,
},
Template: v1.PodTemplateSpec{ Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Labels: finalLabels, Labels: c.Labels.Merge(podLabels),
Annotations: podAnnotations, Annotations: podAnnotations,
}, },
Spec: v1.PodSpec{ Spec: v1.PodSpec{
@ -582,8 +578,16 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
ReadinessProbe: readinessProbe, ReadinessProbe: readinessProbe,
Resources: p.Spec.Resources, Resources: p.Spec.Resources,
}, { }, {
Name: "prometheus-config-reloader", Name: "prometheus-config-reloader",
Image: c.PrometheusConfigReloader, Image: c.PrometheusConfigReloader,
Env: []v1.EnvVar{
{
Name: "POD_NAME",
ValueFrom: &v1.EnvVarSource{
FieldRef: &v1.ObjectFieldSelector{FieldPath: "metadata.name"},
},
},
},
Args: configReloadArgs, Args: configReloadArgs,
VolumeMounts: configReloadVolumeMounts, VolumeMounts: configReloadVolumeMounts,
Resources: v1.ResourceRequirements{ Resources: v1.ResourceRequirements{

View file

@ -159,14 +159,9 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
{ {
VolumeMounts: []v1.VolumeMount{ VolumeMounts: []v1.VolumeMount{
{ {
Name: "config", Name: "config-out",
ReadOnly: true, ReadOnly: true,
MountPath: "/etc/prometheus/config", MountPath: "/etc/prometheus/config_out",
SubPath: "",
}, {
Name: "rules",
ReadOnly: true,
MountPath: "/etc/prometheus/rules",
SubPath: "", SubPath: "",
}, { }, {
Name: "prometheus--db", Name: "prometheus--db",
@ -192,7 +187,7 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
}, },
}, },
{ {
Name: "rules", Name: "config-out",
VolumeSource: v1.VolumeSource{ VolumeSource: v1.VolumeSource{
EmptyDir: &v1.EmptyDirVolumeSource{}, EmptyDir: &v1.EmptyDirVolumeSource{},
}, },
@ -227,8 +222,15 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if !reflect.DeepEqual(expected.Spec.Template.Spec.Volumes, sset.Spec.Template.Spec.Volumes) || !reflect.DeepEqual(expected.Spec.Template.Spec.Containers[0].VolumeMounts, sset.Spec.Template.Spec.Containers[0].VolumeMounts) { if !reflect.DeepEqual(expected.Spec.Template.Spec.Volumes, sset.Spec.Template.Spec.Volumes) {
t.Fatal("Volumes mounted in a Pod are not created correctly initially.") t.Fatalf("Unexpected volumes: want %v, got %v",
expected.Spec.Template.Spec.Volumes,
sset.Spec.Template.Spec.Volumes)
}
if !reflect.DeepEqual(expected.Spec.Template.Spec.Containers[0].VolumeMounts, sset.Spec.Template.Spec.Containers[0].VolumeMounts) {
t.Fatalf("Unexpected volume mounts: want %v, got %v",
expected.Spec.Template.Spec.Containers[0].VolumeMounts,
sset.Spec.Template.Spec.Containers[0].VolumeMounts)
} }
} }