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