From 8ef0ecbe8c204f3e31ea53b3f7867aa1d340f3ad Mon Sep 17 00:00:00 2001 From: Daniel Hrabovcak Date: Thu, 14 Sep 2023 16:30:53 -0400 Subject: [PATCH] Add flag to compress the Prometheus ConfigMap --- ...toring.googleapis.com_operatorconfigs.yaml | 10 +++++ doc/api.md | 15 +++++++ manifests/setup.yaml | 10 +++++ pkg/operator/apis/monitoring/v1/types.go | 13 ++++++ .../monitoring/v1/zz_generated.deepcopy.go | 17 ++++++++ pkg/operator/collection.go | 41 ++++++++++++++++--- 6 files changed, 101 insertions(+), 5 deletions(-) diff --git a/cmd/operator/deploy/crds/monitoring.googleapis.com_operatorconfigs.yaml b/cmd/operator/deploy/crds/monitoring.googleapis.com_operatorconfigs.yaml index 585713d9eb..d61478b720 100644 --- a/cmd/operator/deploy/crds/monitoring.googleapis.com_operatorconfigs.yaml +++ b/cmd/operator/deploy/crds/monitoring.googleapis.com_operatorconfigs.yaml @@ -93,6 +93,16 @@ spec: type: object description: Features holds configuration for optional managed-collection features. properties: + config: + type: object + description: Settings for the collector configuration propagation. + properties: + compression: + type: string + description: Compression enables compression of the config data propagated by the operator to collectors. It is recommended to use the gzip option when using a large number of ClusterPodMonitoring and/or PodMonitoring. + enum: + - none + - gzip targetStatus: type: object description: Configuration of target status reporting. diff --git a/doc/api.md b/doc/api.md index 88bce966f4..7ec987c948 100644 --- a/doc/api.md +++ b/doc/api.md @@ -26,6 +26,7 @@ This Document documents the types introduced by the GMP CRDs to be consumed by u * [ClusterRules](#clusterrules) * [ClusterRulesList](#clusterruleslist) * [CollectionSpec](#collectionspec) +* [ConfigSpec](#configspec) * [ExportFilters](#exportfilters) * [GlobalRules](#globalrules) * [GlobalRulesList](#globalruleslist) @@ -190,6 +191,19 @@ CollectionSpec specifies how the operator configures collection of metric data. [Back to TOC](#table-of-contents) +## ConfigSpec + +ConfigSpec holds configurations for the Prometheus configuration. + + +appears in: [OperatorFeatures](#operatorfeatures) + +| Field | Description | Scheme | Required | +| ----- | ----------- | ------ | -------- | +| compression | Compression enables compression of the config data propagated by the operator to collectors. It is recommended to use the gzip option when using a large number of ClusterPodMonitoring and/or PodMonitoring. | CompressionType | false | + +[Back to TOC](#table-of-contents) + ## ExportFilters ExportFilters provides mechanisms to filter the scraped data that's sent to GMP. @@ -325,6 +339,7 @@ OperatorFeatures holds configuration for optional managed-collection features. | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | targetStatus | Configuration of target status reporting. | [TargetStatusSpec](#targetstatusspec) | false | +| config | Settings for the collector configuration propagation. | [ConfigSpec](#configspec) | false | [Back to TOC](#table-of-contents) diff --git a/manifests/setup.yaml b/manifests/setup.yaml index 096ad09fd4..9de2639140 100644 --- a/manifests/setup.yaml +++ b/manifests/setup.yaml @@ -929,6 +929,16 @@ spec: type: object description: Features holds configuration for optional managed-collection features. properties: + config: + type: object + description: Settings for the collector configuration propagation. + properties: + compression: + type: string + description: Compression enables compression of the config data propagated by the operator to collectors. It is recommended to use the gzip option when using a large number of ClusterPodMonitoring and/or PodMonitoring. + enum: + - none + - gzip targetStatus: type: object description: Configuration of target status reporting. diff --git a/pkg/operator/apis/monitoring/v1/types.go b/pkg/operator/apis/monitoring/v1/types.go index 4ff32fc6f3..169d1cb446 100644 --- a/pkg/operator/apis/monitoring/v1/types.go +++ b/pkg/operator/apis/monitoring/v1/types.go @@ -117,6 +117,16 @@ type CollectionSpec struct { type OperatorFeatures struct { // Configuration of target status reporting. TargetStatus TargetStatusSpec `json:"targetStatus,omitempty"` + // Settings for the collector configuration propagation. + Config ConfigSpec `json:"config,omitempty"` +} + +// ConfigSpec holds configurations for the Prometheus configuration. +type ConfigSpec struct { + // Compression enables compression of the config data propagated by the operator to collectors. + // It is recommended to use the gzip option when using a large number of ClusterPodMonitoring + // and/or PodMonitoring. + Compression CompressionType `json:"compression,omitempty"` } // TargetStatusSpec holds configuration for target status reporting. @@ -128,6 +138,9 @@ type TargetStatusSpec struct { // +kubebuilder:validation:Enum=none;gzip type CompressionType string +const CompressionNone CompressionType = "none" +const CompressionGzip CompressionType = "gzip" + // KubeletScraping allows enabling scraping of the Kubelets' metric endpoints. type KubeletScraping struct { // The interval at which the metric endpoints are scraped. diff --git a/pkg/operator/apis/monitoring/v1/zz_generated.deepcopy.go b/pkg/operator/apis/monitoring/v1/zz_generated.deepcopy.go index ee5189a0c0..6ca4c57409 100644 --- a/pkg/operator/apis/monitoring/v1/zz_generated.deepcopy.go +++ b/pkg/operator/apis/monitoring/v1/zz_generated.deepcopy.go @@ -282,6 +282,22 @@ func (in *CollectionSpec) DeepCopy() *CollectionSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. +func (in *ConfigSpec) DeepCopy() *ConfigSpec { + if in == nil { + return nil + } + out := new(ConfigSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExportFilters) DeepCopyInto(out *ExportFilters) { *out = *in @@ -506,6 +522,7 @@ func (in *OperatorConfigList) DeepCopyObject() runtime.Object { func (in *OperatorFeatures) DeepCopyInto(out *OperatorFeatures) { *out = *in out.TargetStatus = in.TargetStatus + out.Config = in.Config return } diff --git a/pkg/operator/collection.go b/pkg/operator/collection.go index c1920065ce..a4b191f36b 100644 --- a/pkg/operator/collection.go +++ b/pkg/operator/collection.go @@ -15,6 +15,8 @@ package operator import ( + "bytes" + "compress/gzip" "context" "encoding/json" "fmt" @@ -174,7 +176,7 @@ func (r *collectionReconciler) Reconcile(ctx context.Context, req reconcile.Requ return reconcile.Result{}, fmt.Errorf("ensure collector daemon set: %w", err) } - if err := r.ensureCollectorConfig(ctx, &config.Collection); err != nil { + if err := r.ensureCollectorConfig(ctx, &config.Collection, config.Features.Config.Compression); err != nil { return reconcile.Result{}, fmt.Errorf("ensure collector config: %w", err) } @@ -255,7 +257,7 @@ func (r *collectionReconciler) ensureCollectorDaemonSet(ctx context.Context, spe flags = append(flags, fmt.Sprintf("--export.credentials-file=%q", p)) } - if len(spec.Compression) > 0 && spec.Compression != "none" { + if len(spec.Compression) > 0 && spec.Compression != monitoringv1.CompressionNone { flags = append(flags, fmt.Sprintf("--export.compression=%s", spec.Compression)) } @@ -300,8 +302,20 @@ func resolveLabels(opts Options, externalLabels map[string]string) (projectID st return } +func gzipData(data []byte) ([]byte, error) { + var b bytes.Buffer + gz := gzip.NewWriter(&b) + if _, err := gz.Write(data); err != nil { + return nil, err + } + if err := gz.Close(); err != nil { + return nil, err + } + return b.Bytes(), nil +} + // ensureCollectorConfig generates the collector config and creates or updates it. -func (r *collectionReconciler) ensureCollectorConfig(ctx context.Context, spec *monitoringv1.CollectionSpec) error { +func (r *collectionReconciler) ensureCollectorConfig(ctx context.Context, spec *monitoringv1.CollectionSpec, compression monitoringv1.CompressionType) error { cfg, err := r.makeCollectorConfig(ctx, spec) if err != nil { return fmt.Errorf("generate Prometheus config: %w", err) @@ -316,9 +330,26 @@ func (r *collectionReconciler) ensureCollectorConfig(ctx context.Context, spec * Namespace: r.opts.OperatorNamespace, Name: NameCollector, }, - Data: map[string]string{ + } + + // Thanos config-reloader detects gzip compression automatically, so no sync with + // config-reloaders is needed when switching between these. + switch compression { + case monitoringv1.CompressionGzip: + compressedCfg, err := gzipData(cfgEncoded) + if err != nil { + return fmt.Errorf("gzip Prometheus config: %w", err) + } + + cm.BinaryData = map[string][]byte{ + configFilename: compressedCfg, + } + case "", monitoringv1.CompressionNone: + cm.Data = map[string]string{ configFilename: string(cfgEncoded), - }, + } + default: + return fmt.Errorf("unknown compression type: %q", compression) } if err := r.client.Update(ctx, cm); apierrors.IsNotFound(err) {