Path: blob/main/component/prometheus/operator/configgen/config_gen_podmonitor.go
5393 views
package configgen12// SEE https://github.com/prometheus-operator/prometheus-operator/blob/aa8222d7e9b66e9293ed11c9291ea70173021029/pkg/prometheus/promcfg.go34import (5"fmt"6"net/url"7"sort"8"strings"910promopv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"11namespacelabeler "github.com/prometheus-operator/prometheus-operator/pkg/namespace-labeler"12commonConfig "github.com/prometheus/common/config"13"github.com/prometheus/common/model"14"github.com/prometheus/prometheus/config"15promk8s "github.com/prometheus/prometheus/discovery/kubernetes"16"github.com/prometheus/prometheus/model/relabel"17metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"18)1920var (21regexFilterRunning = relabel.MustNewRegexp("(Failed|Succeeded)")22regexTrue = relabel.MustNewRegexp("true")23regexAnything = relabel.MustNewRegexp("(.+)")24regexNode = relabel.MustNewRegexp("Node;(.*)")25regexPod = relabel.MustNewRegexp("Pod;(.*)")26)2728func (cg *ConfigGenerator) GeneratePodMonitorConfig(m *promopv1.PodMonitor, ep promopv1.PodMetricsEndpoint, i int) (cfg *config.ScrapeConfig, err error) {29c := config.DefaultScrapeConfig30cfg = &c31cfg.ScrapeInterval = config.DefaultGlobalConfig.ScrapeInterval32cfg.ScrapeTimeout = config.DefaultGlobalConfig.ScrapeTimeout33cfg.JobName = fmt.Sprintf("podMonitor/%s/%s/%d", m.Namespace, m.Name, i)34cfg.HonorLabels = ep.HonorLabels35if ep.HonorTimestamps != nil {36cfg.HonorTimestamps = *ep.HonorTimestamps37}3839cfg.ServiceDiscoveryConfigs = append(cfg.ServiceDiscoveryConfigs, cg.generateK8SSDConfig(m.Spec.NamespaceSelector, m.Namespace, promk8s.RolePod, m.Spec.AttachMetadata))4041if ep.Interval != "" {42if cfg.ScrapeInterval, err = model.ParseDuration(string(ep.Interval)); err != nil {43return nil, fmt.Errorf("parsing interval from podMonitor: %w", err)44}45}46if ep.ScrapeTimeout != "" {47if cfg.ScrapeTimeout, err = model.ParseDuration(string(ep.ScrapeTimeout)); err != nil {48return nil, fmt.Errorf("parsing timeout from podMonitor: %w", err)49}50}51if ep.Path != "" {52cfg.MetricsPath = ep.Path53}54if ep.ProxyURL != nil {55if u, err := url.Parse(*ep.ProxyURL); err != nil {56return nil, fmt.Errorf("parsing ProxyURL from podMonitor: %w", err)57} else {58cfg.HTTPClientConfig.ProxyURL = commonConfig.URL{URL: u}59}60}61if ep.Params != nil {62cfg.Params = ep.Params63}64if ep.Scheme != "" {65cfg.Scheme = ep.Scheme66}67if ep.FollowRedirects != nil {68cfg.HTTPClientConfig.FollowRedirects = *ep.FollowRedirects69}70if ep.EnableHttp2 != nil {71cfg.HTTPClientConfig.EnableHTTP2 = *ep.EnableHttp272}73if ep.TLSConfig != nil {74if cfg.HTTPClientConfig.TLSConfig, err = cg.generateSafeTLS(ep.TLSConfig.SafeTLSConfig); err != nil {75return nil, err76}77}78if ep.BearerTokenSecret.Name != "" {79return nil, fmt.Errorf("bearer tokens in podmonitors not supported yet: %w", err)80}81if ep.BasicAuth != nil {82return nil, fmt.Errorf("basic auth in podmonitors not supported yet: %w", err)83}84// TODO: Add support for ep.OAuth2 and ep.Authorization8586relabels := cg.initRelabelings()87if ep.FilterRunning == nil || *ep.FilterRunning {88relabels.add(&relabel.Config{89SourceLabels: model.LabelNames{"__meta_kubernetes_pod_phase"},90Action: "drop",91Regex: regexFilterRunning,92})93}9495var labelKeys []string96// Filter targets by pods selected by the monitor.97// Exact label matches.98for k := range m.Spec.Selector.MatchLabels {99labelKeys = append(labelKeys, k)100}101sort.Strings(labelKeys)102103for _, k := range labelKeys {104regex, err := relabel.NewRegexp(fmt.Sprintf("(%s);true", m.Spec.Selector.MatchLabels[k]))105if err != nil {106return nil, fmt.Errorf("parsing MatchLabels regex: %w", err)107}108relabels.add(&relabel.Config{109SourceLabels: model.LabelNames{"__meta_kubernetes_pod_label_" + sanitizeLabelName(k), "__meta_kubernetes_pod_labelpresent_" + sanitizeLabelName(k)},110Action: "keep",111Regex: regex,112})113}114115// Set based label matching. We have to map the valid relations116// `In`, `NotIn`, `Exists`, and `DoesNotExist`, into relabeling rules.117for _, exp := range m.Spec.Selector.MatchExpressions {118switch exp.Operator {119case metav1.LabelSelectorOpIn:120regex, err := relabel.NewRegexp(fmt.Sprintf("(%s);true", strings.Join(exp.Values, "|")))121if err != nil {122return nil, fmt.Errorf("parsing MatchExpressions regex: %w", err)123}124relabels.add(&relabel.Config{125SourceLabels: model.LabelNames{"__meta_kubernetes_pod_label_" + sanitizeLabelName(exp.Key), "__meta_kubernetes_pod_labelpresent_" + sanitizeLabelName(exp.Key)},126Action: "keep",127Regex: regex,128})129case metav1.LabelSelectorOpNotIn:130regex, err := relabel.NewRegexp(fmt.Sprintf("(%s);true", strings.Join(exp.Values, "|")))131if err != nil {132return nil, fmt.Errorf("parsing MatchExpressions regex: %w", err)133}134relabels.add(&relabel.Config{135SourceLabels: model.LabelNames{"__meta_kubernetes_pod_label_" + sanitizeLabelName(exp.Key), "__meta_kubernetes_pod_labelpresent_" + sanitizeLabelName(exp.Key)},136Action: "drop",137Regex: regex,138})139case metav1.LabelSelectorOpExists:140relabels.add(&relabel.Config{141SourceLabels: model.LabelNames{"__meta_kubernetes_pod_labelpresent_" + sanitizeLabelName(exp.Key)},142Action: "keep",143Regex: regexTrue,144})145case metav1.LabelSelectorOpDoesNotExist:146relabels.add(&relabel.Config{147SourceLabels: model.LabelNames{"__meta_kubernetes_pod_labelpresent_" + sanitizeLabelName(exp.Key)},148Action: "drop",149Regex: regexTrue,150})151}152}153154// Filter targets based on correct port for the endpoint.155if ep.Port != "" {156regex, err := relabel.NewRegexp(ep.Port)157if err != nil {158return nil, fmt.Errorf("parsing Port as regex: %w", err)159}160relabels.add(&relabel.Config{161SourceLabels: model.LabelNames{"__meta_kubernetes_pod_container_port_name"},162Action: "keep",163Regex: regex,164})165} else if ep.TargetPort != nil { //nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.166//nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.167regex, err := relabel.NewRegexp(ep.TargetPort.String())168if err != nil {169return nil, fmt.Errorf("parsing TargetPort as regex: %w", err)170}171if ep.TargetPort.StrVal != "" { //nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.172relabels.add(&relabel.Config{173SourceLabels: model.LabelNames{"__meta_kubernetes_pod_container_port_name"},174Action: "keep",175Regex: regex,176})177}178} else if ep.TargetPort.IntVal != 0 { //nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.179regex, err := relabel.NewRegexp(ep.TargetPort.String()) //nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.180if err != nil {181return nil, fmt.Errorf("parsing TargetPort as regex: %w", err)182}183relabels.add(&relabel.Config{184SourceLabels: model.LabelNames{"__meta_kubernetes_pod_container_port_number"},185Action: "keep",186Regex: regex,187})188}189190// Relabel namespace and pod and service labels into proper labels.191relabels.add(&relabel.Config{192SourceLabels: model.LabelNames{"__meta_kubernetes_namespace"},193TargetLabel: "namespace",194}, &relabel.Config{195SourceLabels: model.LabelNames{"__meta_kubernetes_pod_container_name"},196TargetLabel: "container",197}, &relabel.Config{198SourceLabels: model.LabelNames{"__meta_kubernetes_pod_name"},199TargetLabel: "pod",200})201202// Relabel targetLabels from Pod onto target.203for _, l := range m.Spec.PodTargetLabels {204relabels.add(&relabel.Config{205SourceLabels: model.LabelNames{"__meta_kubernetes_pod_label_" + sanitizeLabelName(l)},206Replacement: "${1}",207Regex: regexAnything,208TargetLabel: string(sanitizeLabelName(l)),209})210}211212// By default, generate a safe job name from the PodMonitor. We also keep213// this around if a jobLabel is set in case the targets don't actually have a214// value for it. A single pod may potentially have multiple metrics215// endpoints, therefore the endpoints labels is filled with the ports name or216// as a fallback the port number.217218relabels.add(&relabel.Config{219Replacement: fmt.Sprintf("%s/%s", m.GetNamespace(), m.GetName()),220TargetLabel: "job",221})222if m.Spec.JobLabel != "" {223relabels.add(&relabel.Config{224Replacement: "${1}",225TargetLabel: "job",226Regex: regexAnything,227SourceLabels: model.LabelNames{"__meta_kubernetes_pod_label_" + sanitizeLabelName(m.Spec.JobLabel)},228})229}230231if ep.Port != "" {232relabels.add(&relabel.Config{233Replacement: ep.Port,234TargetLabel: "endpoint",235})236} else if ep.TargetPort != nil && ep.TargetPort.String() != "" { //nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.237relabels.add(&relabel.Config{238TargetLabel: "endpoint",239Replacement: ep.TargetPort.String(), //nolint:staticcheck // Ignore SA1019 this field is marked as deprecated.240})241}242243labeler := namespacelabeler.New("", nil, false)244if err = relabels.addFromV1(labeler.GetRelabelingConfigs(m.TypeMeta, m.ObjectMeta, ep.RelabelConfigs)...); err != nil {245return nil, fmt.Errorf("parsing relabel configs: %w", err)246}247248cfg.RelabelConfigs = relabels.configs249250metricRelabels := relabeler{}251if err = metricRelabels.addFromV1(labeler.GetRelabelingConfigs(m.TypeMeta, m.ObjectMeta, ep.MetricRelabelConfigs)...); err != nil {252return nil, fmt.Errorf("parsing metric relabel configs: %w", err)253}254cfg.MetricRelabelConfigs = metricRelabels.configs255256cfg.SampleLimit = uint(m.Spec.SampleLimit)257cfg.TargetLimit = uint(m.Spec.TargetLimit)258cfg.LabelLimit = uint(m.Spec.LabelLimit)259cfg.LabelNameLengthLimit = uint(m.Spec.LabelNameLengthLimit)260cfg.LabelValueLengthLimit = uint(m.Spec.LabelValueLengthLimit)261262return cfg, nil263}264265266