1
0
Fork 0
mirror of https://github.com/prometheus-operator/prometheus-operator.git synced 2025-04-21 03:38:43 +00:00

feat: add bodySizeLimit to service and pod monitors ()

* feat: add EnforcedBodySizeLimit to service and monitor
This commit is contained in:
Mohammad 2024-03-12 13:28:31 +03:30 committed by GitHub
parent 4030eb75f6
commit bc0b84218b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 270 additions and 13 deletions

66
Documentation/api.md generated
View file

@ -1041,6 +1041,22 @@ string
<p>The scrape class to apply.</p>
</td>
</tr>
<tr>
<td>
<code>bodySizeLimit</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ByteSize">
ByteSize
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>When defined, bodySizeLimit specifies a job level limit on the size
of uncompressed response body that will be accepted by Prometheus.</p>
<p>It requires Prometheus &gt;= v2.28.0.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -3384,6 +3400,22 @@ string
<p>The scrape class to apply.</p>
</td>
</tr>
<tr>
<td>
<code>bodySizeLimit</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ByteSize">
ByteSize
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>When defined, bodySizeLimit specifies a job level limit on the size
of uncompressed response body that will be accepted by Prometheus.</p>
<p>It requires Prometheus &gt;= v2.28.0.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -5893,7 +5925,7 @@ authentication.</p>
<h3 id="monitoring.coreos.com/v1.ByteSize">ByteSize
(<code>string</code> alias)</h3>
<p>
(<em>Appears on:</em><a href="#monitoring.coreos.com/v1.CommonPrometheusFields">CommonPrometheusFields</a>, <a href="#monitoring.coreos.com/v1.PrometheusSpec">PrometheusSpec</a>)
(<em>Appears on:</em><a href="#monitoring.coreos.com/v1.CommonPrometheusFields">CommonPrometheusFields</a>, <a href="#monitoring.coreos.com/v1.PodMonitorSpec">PodMonitorSpec</a>, <a href="#monitoring.coreos.com/v1.PrometheusSpec">PrometheusSpec</a>, <a href="#monitoring.coreos.com/v1.ServiceMonitorSpec">ServiceMonitorSpec</a>)
</p>
<div>
<p>ByteSize is a valid memory size type based on powers-of-2, so 1KB is 1024B.
@ -9438,6 +9470,22 @@ string
<p>The scrape class to apply.</p>
</td>
</tr>
<tr>
<td>
<code>bodySizeLimit</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ByteSize">
ByteSize
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>When defined, bodySizeLimit specifies a job level limit on the size
of uncompressed response body that will be accepted by Prometheus.</p>
<p>It requires Prometheus &gt;= v2.28.0.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="monitoring.coreos.com/v1.ProbeSpec">ProbeSpec
@ -13717,6 +13765,22 @@ string
<p>The scrape class to apply.</p>
</td>
</tr>
<tr>
<td>
<code>bodySizeLimit</code><br/>
<em>
<a href="#monitoring.coreos.com/v1.ByteSize">
ByteSize
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>When defined, bodySizeLimit specifies a job level limit on the size
of uncompressed response body that will be accepted by Prometheus.</p>
<p>It requires Prometheus &gt;= v2.28.0.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="monitoring.coreos.com/v1.ShardStatus">ShardStatus

12
bundle.yaml generated
View file

@ -13532,6 +13532,12 @@ spec:
permission on the `Nodes` objects.
type: boolean
type: object
bodySizeLimit:
description: "When defined, bodySizeLimit specifies a job level limit
on the size of uncompressed response body that will be accepted
by Prometheus. \n It requires Prometheus >= v2.28.0."
pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$
type: string
jobLabel:
description: "The label to use to retrieve the job name from. `jobLabel`
selects the label from the associated Kubernetes `Pod` object which
@ -37148,6 +37154,12 @@ spec:
permission on the `Nodes` objects.
type: boolean
type: object
bodySizeLimit:
description: "When defined, bodySizeLimit specifies a job level limit
on the size of uncompressed response body that will be accepted
by Prometheus. \n It requires Prometheus >= v2.28.0."
pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$
type: string
endpoints:
description: List of endpoints part of this ServiceMonitor.
items:

View file

@ -48,6 +48,12 @@ spec:
permission on the `Nodes` objects.
type: boolean
type: object
bodySizeLimit:
description: "When defined, bodySizeLimit specifies a job level limit
on the size of uncompressed response body that will be accepted
by Prometheus. \n It requires Prometheus >= v2.28.0."
pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$
type: string
jobLabel:
description: "The label to use to retrieve the job name from. `jobLabel`
selects the label from the associated Kubernetes `Pod` object which

View file

@ -48,6 +48,12 @@ spec:
permission on the `Nodes` objects.
type: boolean
type: object
bodySizeLimit:
description: "When defined, bodySizeLimit specifies a job level limit
on the size of uncompressed response body that will be accepted
by Prometheus. \n It requires Prometheus >= v2.28.0."
pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$
type: string
endpoints:
description: List of endpoints part of this ServiceMonitor.
items:

View file

@ -49,6 +49,12 @@ spec:
permission on the `Nodes` objects.
type: boolean
type: object
bodySizeLimit:
description: "When defined, bodySizeLimit specifies a job level limit
on the size of uncompressed response body that will be accepted
by Prometheus. \n It requires Prometheus >= v2.28.0."
pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$
type: string
jobLabel:
description: "The label to use to retrieve the job name from. `jobLabel`
selects the label from the associated Kubernetes `Pod` object which

View file

@ -49,6 +49,12 @@ spec:
permission on the `Nodes` objects.
type: boolean
type: object
bodySizeLimit:
description: "When defined, bodySizeLimit specifies a job level limit
on the size of uncompressed response body that will be accepted
by Prometheus. \n It requires Prometheus >= v2.28.0."
pattern: (^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$
type: string
endpoints:
description: List of endpoints part of this ServiceMonitor.
items:

2
go.mod
View file

@ -4,6 +4,7 @@ go 1.22
require (
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/blang/semver/v4 v4.0.0
github.com/cespare/xxhash/v2 v2.2.0
@ -44,7 +45,6 @@ require (
)
require (
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect

View file

@ -54,6 +54,11 @@
},
"type": "object"
},
"bodySizeLimit": {
"description": "When defined, bodySizeLimit specifies a job level limit on the size of uncompressed response body that will be accepted by Prometheus. \n It requires Prometheus >= v2.28.0.",
"pattern": "(^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$",
"type": "string"
},
"jobLabel": {
"description": "The label to use to retrieve the job name from. `jobLabel` selects the label from the associated Kubernetes `Pod` object which will be used as the `job` label for all metrics. \n For example if `jobLabel` is set to `foo` and the Kubernetes `Pod` object is labeled with `foo: bar`, then Prometheus adds the `job=\"bar\"` label to all ingested metrics. \n If the value of this field is empty, the `job` label of the metrics defaults to the namespace and name of the PodMonitor object (e.g. `<namespace>/<name>`).",
"type": "string"

View file

@ -54,6 +54,11 @@
},
"type": "object"
},
"bodySizeLimit": {
"description": "When defined, bodySizeLimit specifies a job level limit on the size of uncompressed response body that will be accepted by Prometheus. \n It requires Prometheus >= v2.28.0.",
"pattern": "(^0|([0-9]*[.])?[0-9]+((K|M|G|T|E|P)i?)?B)$",
"type": "string"
},
"endpoints": {
"description": "List of endpoints part of this ServiceMonitor.",
"items": {

View file

@ -136,6 +136,14 @@ type PodMonitorSpec struct {
// +optional
// +kubebuilder:validation:MinLength=1
ScrapeClassName *string `json:"scrapeClass,omitempty"`
// When defined, bodySizeLimit specifies a job level limit on the size
// of uncompressed response body that will be accepted by Prometheus.
//
// It requires Prometheus >= v2.28.0.
//
// +optional
BodySizeLimit *ByteSize `json:"bodySizeLimit,omitempty"`
}
// PodMonitorList is a list of PodMonitors.

View file

@ -141,6 +141,14 @@ type ServiceMonitorSpec struct {
// +optional
// +kubebuilder:validation:MinLength=1
ScrapeClassName *string `json:"scrapeClass,omitempty"`
// When defined, bodySizeLimit specifies a job level limit on the size
// of uncompressed response body that will be accepted by Prometheus.
//
// It requires Prometheus >= v2.28.0.
//
// +optional
BodySizeLimit *ByteSize `json:"bodySizeLimit,omitempty"`
}
// ServiceMonitorList is a list of ServiceMonitors.

View file

@ -1651,6 +1651,11 @@ func (in *PodMonitorSpec) DeepCopyInto(out *PodMonitorSpec) {
*out = new(string)
**out = **in
}
if in.BodySizeLimit != nil {
in, out := &in.BodySizeLimit, &out.BodySizeLimit
*out = new(ByteSize)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodMonitorSpec.
@ -2818,6 +2823,11 @@ func (in *ServiceMonitorSpec) DeepCopyInto(out *ServiceMonitorSpec) {
*out = new(string)
**out = **in
}
if in.BodySizeLimit != nil {
in, out := &in.BodySizeLimit, &out.BodySizeLimit
*out = new(ByteSize)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMonitorSpec.

View file

@ -38,6 +38,7 @@ type PodMonitorSpecApplyConfiguration struct {
KeepDroppedTargets *uint64 `json:"keepDroppedTargets,omitempty"`
AttachMetadata *AttachMetadataApplyConfiguration `json:"attachMetadata,omitempty"`
ScrapeClassName *string `json:"scrapeClass,omitempty"`
BodySizeLimit *monitoringv1.ByteSize `json:"bodySizeLimit,omitempty"`
}
// PodMonitorSpecApplyConfiguration constructs an declarative configuration of the PodMonitorSpec type for use with
@ -166,3 +167,11 @@ func (b *PodMonitorSpecApplyConfiguration) WithScrapeClassName(value string) *Po
b.ScrapeClassName = &value
return b
}
// WithBodySizeLimit sets the BodySizeLimit 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 BodySizeLimit field is set to the value of the last call.
func (b *PodMonitorSpecApplyConfiguration) WithBodySizeLimit(value monitoringv1.ByteSize) *PodMonitorSpecApplyConfiguration {
b.BodySizeLimit = &value
return b
}

View file

@ -39,6 +39,7 @@ type ServiceMonitorSpecApplyConfiguration struct {
KeepDroppedTargets *uint64 `json:"keepDroppedTargets,omitempty"`
AttachMetadata *AttachMetadataApplyConfiguration `json:"attachMetadata,omitempty"`
ScrapeClassName *string `json:"scrapeClass,omitempty"`
BodySizeLimit *monitoringv1.ByteSize `json:"bodySizeLimit,omitempty"`
}
// ServiceMonitorSpecApplyConfiguration constructs an declarative configuration of the ServiceMonitorSpec type for use with
@ -177,3 +178,11 @@ func (b *ServiceMonitorSpecApplyConfiguration) WithScrapeClassName(value string)
b.ScrapeClassName = &value
return b
}
// WithBodySizeLimit sets the BodySizeLimit 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 BodySizeLimit field is set to the value of the last call.
func (b *ServiceMonitorSpecApplyConfiguration) WithBodySizeLimit(value monitoringv1.ByteSize) *ServiceMonitorSpecApplyConfiguration {
b.BodySizeLimit = &value
return b
}

View file

@ -22,6 +22,7 @@ import (
"sort"
"strings"
"github.com/alecthomas/units"
"github.com/blang/semver/v4"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
@ -1034,8 +1035,8 @@ func (cg *ConfigGenerator) generatePodMonitorConfig(
cfg = cg.AddLimitsToYAML(cfg, keepDroppedTargetsKey, m.Spec.KeepDroppedTargets, cpf.EnforcedKeepDroppedTargets)
cfg = cg.AddScrapeProtocols(cfg, m.Spec.ScrapeProtocols)
if cpf.EnforcedBodySizeLimit != "" {
cfg = cg.WithMinimumVersion("2.28.0").AppendMapItem(cfg, "body_size_limit", cpf.EnforcedBodySizeLimit)
if bodySizeLimit := getLowerByteSize(m.Spec.BodySizeLimit, &cpf); !isByteSizeEmpty(bodySizeLimit) {
cfg = cg.WithMinimumVersion("2.28.0").AppendMapItem(cfg, "body_size_limit", bodySizeLimit)
}
cfg = append(cfg, yaml.MapItem{Key: "metric_relabel_configs", Value: generateRelabelConfig(labeler.GetRelabelingConfigs(m.TypeMeta, m.ObjectMeta, ep.MetricRelabelConfigs))})
@ -1546,8 +1547,8 @@ func (cg *ConfigGenerator) generateServiceMonitorConfig(
cfg = cg.AddLimitsToYAML(cfg, keepDroppedTargetsKey, m.Spec.KeepDroppedTargets, cpf.EnforcedKeepDroppedTargets)
cfg = cg.AddScrapeProtocols(cfg, m.Spec.ScrapeProtocols)
if cpf.EnforcedBodySizeLimit != "" {
cfg = cg.WithMinimumVersion("2.28.0").AppendMapItem(cfg, "body_size_limit", cpf.EnforcedBodySizeLimit)
if bodySizeLimit := getLowerByteSize(m.Spec.BodySizeLimit, &cpf); !isByteSizeEmpty(bodySizeLimit) {
cfg = cg.WithMinimumVersion("2.28.0").AppendMapItem(cfg, "body_size_limit", bodySizeLimit)
}
cfg = append(cfg, yaml.MapItem{Key: "metric_relabel_configs", Value: generateRelabelConfig(labeler.GetRelabelingConfigs(m.TypeMeta, m.ObjectMeta, ep.MetricRelabelConfigs))})
@ -3413,3 +3414,26 @@ func (cg *ConfigGenerator) getScrapeClassOrDefault(name *string) *monitoringv1.S
}
return nil
}
func getLowerByteSize(v *monitoringv1.ByteSize, cpf *monitoringv1.CommonPrometheusFields) *monitoringv1.ByteSize {
if isByteSizeEmpty(&cpf.EnforcedBodySizeLimit) {
return v
}
if isByteSizeEmpty(v) {
return &cpf.EnforcedBodySizeLimit
}
vBytes, _ := units.ParseBase2Bytes(string(*v))
pBytes, _ := units.ParseBase2Bytes(string(cpf.EnforcedBodySizeLimit))
if vBytes > pBytes {
return &cpf.EnforcedBodySizeLimit
}
return v
}
func isByteSizeEmpty(v *monitoringv1.ByteSize) bool {
return v == nil || *v == ""
}

View file

@ -4356,21 +4356,29 @@ func TestKeepDroppedTargets(t *testing.T) {
func TestBodySizeLimits(t *testing.T) {
for _, tc := range []struct {
version string
enforcedBodySizeLimit monitoringv1.ByteSize
expectedErr error
golden string
version string
enforcedBodySizeLimit monitoringv1.ByteSize
serviceMonitorBodySizeLimit *monitoringv1.ByteSize
expectedErr error
golden string
}{
{
version: "v2.27.0",
enforcedBodySizeLimit: "1000MB",
golden: "BodySizeLimits_enforce1000MB_v2.27.0.golden",
version: "v2.27.0",
enforcedBodySizeLimit: "1000MB",
serviceMonitorBodySizeLimit: ptr.To[monitoringv1.ByteSize]("2GB"),
golden: "BodySizeLimits_enforce_v2.27.0.golden",
},
{
version: "v2.28.0",
enforcedBodySizeLimit: "1000MB",
golden: "BodySizeLimits_enforce1000MB_v2.28.0.golden",
},
{
version: "v2.28.0",
enforcedBodySizeLimit: "4000MB",
serviceMonitorBodySizeLimit: ptr.To[monitoringv1.ByteSize]("2GB"),
golden: "BodySizeLimits_enforce2GB_v2.28.0.golden",
},
{
version: "v2.28.0",
enforcedBodySizeLimit: "",
@ -4400,6 +4408,7 @@ func TestBodySizeLimits(t *testing.T) {
Interval: "30s",
},
},
BodySizeLimit: tc.serviceMonitorBodySizeLimit,
},
}

View file

@ -0,0 +1,70 @@
global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
scrape_configs:
- job_name: serviceMonitor/default/testservicemonitor1/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- source_labels:
- job
target_label: __tmp_prometheus_job_name
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- action: drop
source_labels:
- __meta_kubernetes_pod_phase
regex: (Failed|Succeeded)
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
- source_labels:
- __address__
target_label: __tmp_hash
modulus: 1
action: hashmod
- source_labels:
- __tmp_hash
regex: $(SHARD)
action: keep
body_size_limit: 2GB
metric_relabel_configs: []