Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions api/operator/v1beta1/common_scrapeparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// AttachMetadata configures metadata attachment
Expand Down Expand Up @@ -539,6 +541,11 @@ type CommonScrapeParams struct {
// it doesn't affect metrics ingested directly by push API's
// +optional
ExternalLabels map[string]string `json:"externalLabels,omitempty"`
// IngestOnlyMode switches vmagent into unmanaged mode
// it disables any config generation for scraping
// Currently it prevents vmagent from managing tls and auth options for remote write
// +optional
IngestOnlyMode *bool `json:"ingestOnlyMode,omitempty"`
// EnableKubernetesAPISelectors instructs vmagent to use CRD scrape objects spec.selectors for
// Kubernetes API list and watch requests.
// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#list-and-watch-filtering
Expand All @@ -548,8 +555,58 @@ type CommonScrapeParams struct {
CommonScrapeSecurityEnforcements `json:",inline,omitempty"`
}

func (cr *CommonScrapeParams) externalLabelName() string {
// Use "prometheus" external label name by default if field is missing.
// in case of migration from prometheus to vmagent, it helps to have same labels
// Do not add external label if field is set to empty string.
if cr.ExternalLabelName != nil {
return *cr.ExternalLabelName
}
if cr.VMAgentExternalLabelName != nil {
return *cr.VMAgentExternalLabelName
}
return "prometheus"
}

func (cr *CommonScrapeParams) externalLabels(defaultLabelValue string) map[string]string {
m := map[string]string{}

prometheusExternalLabelName := cr.externalLabelName()
if len(prometheusExternalLabelName) > 0 {
m[prometheusExternalLabelName] = defaultLabelValue
}

for n, v := range cr.ExternalLabels {
m[n] = v
}
return m
}

// ScrapeSelectors gets object and namespace sepectors
func (cr *CommonScrapeParams) ScrapeSelectors(scrape client.Object) (*metav1.LabelSelector, *metav1.LabelSelector) {
switch s := scrape.(type) {
case *VMNodeScrape:
return cr.NodeScrapeSelector, cr.NodeScrapeNamespaceSelector
case *VMServiceScrape:
return cr.ServiceScrapeSelector, cr.ServiceScrapeNamespaceSelector
case *VMPodScrape:
return cr.PodScrapeSelector, cr.PodScrapeNamespaceSelector
case *VMProbe:
return cr.ProbeSelector, cr.ProbeNamespaceSelector
case *VMStaticScrape:
return cr.StaticScrapeSelector, cr.StaticScrapeNamespaceSelector
case *VMScrapeConfig:
return cr.ScrapeConfigSelector, cr.ScrapeConfigNamespaceSelector
default:
panic(fmt.Sprintf("BUG: scrape kind %T is not supported", s))
}
}

// isUnmanaged checks if object should managed any config objects
func (cr *CommonScrapeParams) isUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.NodeScrapeSelector == nil && cr.NodeScrapeNamespaceSelector == nil &&
cr.ServiceScrapeSelector == nil && cr.ServiceScrapeNamespaceSelector == nil &&
Expand All @@ -561,36 +618,54 @@ func (cr *CommonScrapeParams) isUnmanaged() bool {

// isNodeScrapeUnmanaged checks if scraping agent should managed any VMNodeScrape objects
func (cr *CommonScrapeParams) isNodeScrapeUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.NodeScrapeSelector == nil && cr.NodeScrapeNamespaceSelector == nil
}

// isServiceScrapeUnmanaged checks if scraping agent should managed any VMServiceScrape objects
func (cr *CommonScrapeParams) isServiceScrapeUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.ServiceScrapeSelector == nil && cr.ServiceScrapeNamespaceSelector == nil
}

// isUnmanaged checks if scraping agent should managed any VMPodScrape objects
func (cr *CommonScrapeParams) isPodScrapeUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.PodScrapeSelector == nil && cr.PodScrapeNamespaceSelector == nil
}

// isProbeUnmanaged checks if scraping agent should managed any VMProbe objects
func (cr *CommonScrapeParams) isProbeUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.ProbeSelector == nil && cr.ProbeNamespaceSelector == nil
}

// isStaticScrapeUnmanaged checks if scraping agent should managed any VMStaticScrape objects
func (cr *CommonScrapeParams) isStaticScrapeUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.StaticScrapeSelector == nil && cr.StaticScrapeNamespaceSelector == nil
}

// isScrapeConfigUnmanaged checks if scraping agent should managed any VMScrapeConfig objects
func (cr *CommonScrapeParams) isScrapeConfigUnmanaged() bool {
if ptr.Deref(cr.IngestOnlyMode, false) {
return true
}
return !cr.SelectAllByDefault &&
cr.ScrapeConfigSelector == nil && cr.ScrapeConfigNamespaceSelector == nil
}
93 changes: 30 additions & 63 deletions api/operator/v1beta1/vmagent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ type VMAgentSpec struct {
// +optional
// +kubebuilder:validation:Enum=default;json
LogFormat string `json:"logFormat,omitempty"`

// APIServerConfig allows specifying a host and auth methods to access apiserver.
// If left empty, VMAgent is assumed to run inside of the cluster
// and will discover API servers automatically and use the pod's CA certificate
// and bearer token file at /var/run/secrets/kubernetes.io/serviceaccount/.
// +optional
APIServerConfig *APIServerConfig `json:"apiServerConfig,omitempty"`

// RemoteWrite list of victoria metrics /some other remote write system
// for vm it must looks like: http://victoria-metrics-single:8428/api/v1/write
// or for cluster different url
Expand Down Expand Up @@ -105,11 +103,6 @@ type VMAgentSpec struct {

// ClaimTemplates allows adding additional VolumeClaimTemplates for VMAgent in StatefulMode
ClaimTemplates []corev1.PersistentVolumeClaim `json:"claimTemplates,omitempty"`
// IngestOnlyMode switches vmagent into unmanaged mode
// it disables any config generation for scraping
// Currently it prevents vmagent from managing tls and auth options for remote write
// +optional
IngestOnlyMode bool `json:"ingestOnlyMode,omitempty"`

// License allows to configure license key to be used for enterprise features.
// Using license key is supported starting from VictoriaMetrics v1.94.0.
Expand Down Expand Up @@ -218,6 +211,11 @@ func (cr *VMAgent) GetShardCount() int {
return *cr.Spec.ShardCount
}

// ExternalLabels returns external labels for scraping
func (cr *VMAgent) ExternalLabels() map[string]string {
return cr.Spec.externalLabels(fmt.Sprintf("%s/%s", cr.Namespace, cr.Name))
}

// GetReloadURL implements reloadable interface
func (cr *VMAgent) GetReloadURL(host string) string {
return BuildLocalURL(reloadAuthKey, host, cr.Spec.Port, reloadPath, cr.Spec.ExtraArgs)
Expand Down Expand Up @@ -567,7 +565,7 @@ func (cr *VMAgent) IsOwnsServiceAccount() bool {
}

func (cr *VMAgent) GetClusterRoleName() string {
return fmt.Sprintf("monitoring:%s:vmagent-%s", cr.Namespace, cr.Name)
return fmt.Sprintf("monitoring:%s:%s", cr.Namespace, cr.PrefixedName())
}

// AsURL - returns url for http access
Expand Down Expand Up @@ -612,67 +610,36 @@ func (*VMAgent) ProbeNeedLiveness() bool {
return true
}

// IsUnmanaged checks if object should managed any config objects
func (cr *VMAgent) IsUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
return true
}
return cr.Spec.isUnmanaged()
}

// IsNodeScrapeUnmanaged checks if vmagent should managed any VMNodeScrape objects
func (cr *VMAgent) IsNodeScrapeUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
return true
}
return cr.Spec.isNodeScrapeUnmanaged()
// ScrapeSelectors gets object and namespace sepectors
func (cr *VMAgent) ScrapeSelectors(scrape client.Object) (*metav1.LabelSelector, *metav1.LabelSelector) {
return cr.Spec.ScrapeSelectors(scrape)
}

// IsServiceScrapeUnmanaged checks if vmagent should managed any VMServiceScrape objects
func (cr *VMAgent) IsServiceScrapeUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
return true
}
return cr.Spec.isServiceScrapeUnmanaged()
}

// IsUnmanaged checks if vmagent should managed any VMPodScrape objects
func (cr *VMAgent) IsPodScrapeUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
// IsUnmanaged checks if object should managed any config objects
func (cr *VMAgent) IsUnmanaged(scrape client.Object) bool {
if !cr.DeletionTimestamp.IsZero() || cr.Spec.ParsingError != "" {
return true
}
return cr.Spec.isPodScrapeUnmanaged()
}

// IsProbeUnmanaged checks if vmagent should managed any VMProbe objects
func (cr *VMAgent) IsProbeUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
return true
if scrape == nil {
return cr.Spec.isUnmanaged()
}
switch s := scrape.(type) {
case *VMNodeScrape:
return cr.Spec.DaemonSetMode || cr.Spec.isNodeScrapeUnmanaged()
case *VMServiceScrape:
return cr.Spec.DaemonSetMode || cr.Spec.isServiceScrapeUnmanaged()
case *VMPodScrape:
return cr.Spec.isPodScrapeUnmanaged()
case *VMProbe:
return cr.Spec.DaemonSetMode || cr.Spec.isProbeUnmanaged()
case *VMStaticScrape:
return cr.Spec.DaemonSetMode || cr.Spec.isStaticScrapeUnmanaged()
case *VMScrapeConfig:
return cr.Spec.DaemonSetMode || cr.Spec.isScrapeConfigUnmanaged()
default:
panic(fmt.Sprintf("BUG: scrape kind %T is not supported", s))
}
return cr.Spec.isProbeUnmanaged()
}

// IsStaticScrapeUnmanaged checks if vmagent should managed any VMStaticScrape objects
func (cr *VMAgent) IsStaticScrapeUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
return true
}
return cr.Spec.isStaticScrapeUnmanaged()
}

// IsScrapeConfigUnmanaged checks if vmagent should managed any VMScrapeConfig objects
func (cr *VMAgent) IsScrapeConfigUnmanaged() bool {
// fast path
if cr.Spec.IngestOnlyMode {
return true
}
return cr.Spec.isScrapeConfigUnmanaged()
}

// LastAppliedSpecAsPatch return last applied cluster spec as patch annotation
Expand Down
5 changes: 5 additions & 0 deletions api/operator/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/examples/vmagent-full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ spec:
repository: victoriametrics/vmagent
tag: v1.46.0
pullPolicy: IfNotPresent
vmAgentExternalLabelName: vmagent
externalLabelName: vmagent
scrapeInterval: 30s
externalLabels:
key: value
Expand Down
1 change: 1 addition & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,7 @@ Appears in: [VMAgentSpec](#vmagentspec)
| globalScrapeMetricRelabelConfigs<a href="#commonscrapeparams-globalscrapemetricrelabelconfigs" id="commonscrapeparams-globalscrapemetricrelabelconfigs">#</a><br/>_[RelabelConfig](#relabelconfig) array_ | _(Optional)_<br/>GlobalScrapeMetricRelabelConfigs is a global metric relabel configuration, which is applied to each scrape job. |
| globalScrapeRelabelConfigs<a href="#commonscrapeparams-globalscraperelabelconfigs" id="commonscrapeparams-globalscraperelabelconfigs">#</a><br/>_[RelabelConfig](#relabelconfig) array_ | _(Optional)_<br/>GlobalScrapeRelabelConfigs is a global relabel configuration, which is applied to each samples of each scrape job during service discovery. |
| ignoreNamespaceSelectors<a href="#commonscrapeparams-ignorenamespaceselectors" id="commonscrapeparams-ignorenamespaceselectors">#</a><br/>_boolean_ | _(Optional)_<br/>IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from<br />scrape objects, and they will only discover endpoints<br />within their current namespace. Defaults to false. |
| ingestOnlyMode<a href="#commonscrapeparams-ingestonlymode" id="commonscrapeparams-ingestonlymode">#</a><br/>_boolean_ | _(Optional)_<br/>IngestOnlyMode switches vmagent into unmanaged mode<br />it disables any config generation for scraping<br />Currently it prevents vmagent from managing tls and auth options for remote write |
| inlineScrapeConfig<a href="#commonscrapeparams-inlinescrapeconfig" id="commonscrapeparams-inlinescrapeconfig">#</a><br/>_string_ | _(Optional)_<br/>InlineScrapeConfig As scrape configs are appended, the user is responsible to make sure it<br />is valid. Note that using this feature may expose the possibility to<br />break upgrades of VMAgent. It is advised to review VMAgent release<br />notes to ensure that no incompatible scrape configs are going to break<br />VMAgent after the upgrade.<br />it should be defined as single yaml file.<br />inlineScrapeConfig: \|<br /> - job_name: "prometheus"<br /> static_configs:<br /> - targets: ["localhost:9090"] |
| maxScrapeInterval<a href="#commonscrapeparams-maxscrapeinterval" id="commonscrapeparams-maxscrapeinterval">#</a><br/>_string_ | _(Required)_<br/>MaxScrapeInterval allows limiting maximum scrape interval for VMServiceScrape, VMPodScrape and other scrapes<br />If interval is higher than defined limit, `maxScrapeInterval` will be used. |
| minScrapeInterval<a href="#commonscrapeparams-minscrapeinterval" id="commonscrapeparams-minscrapeinterval">#</a><br/>_string_ | _(Required)_<br/>MinScrapeInterval allows limiting minimal scrape interval for VMServiceScrape, VMPodScrape and other scrapes<br />If interval is lower than defined limit, `minScrapeInterval` will be used. |
Expand Down
8 changes: 4 additions & 4 deletions docs/resources/vmagent.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ metadata:
spec:
# ...
selectAllByDefault: true
vmAgentExternalLabelName: vmagent_ha
externalLabelName: vmagent_ha
remoteWrite:
- url: "http://vmsingle-example.default.svc:8428/api/v1/write"
scrapeInterval: 30s
Expand Down Expand Up @@ -225,7 +225,7 @@ metadata:
spec:
# ...
selectAllByDefault: true
vmAgentExternalLabelName: vmagent_ha
externalLabelName: vmagent_ha
remoteWrite:
- url: "http://vmsingle-example.default.svc:8428/api/v1/write"
scrapeInterval: 30s
Expand Down Expand Up @@ -259,7 +259,7 @@ metadata:
spec:
# ...
selectAllByDefault: true
vmAgentExternalLabelName: vmagent_ha
externalLabelName: vmagent_ha
remoteWrite:
- url: "http://vmsingle-example.default.svc:8428/api/v1/write"
# Replication:
Expand Down Expand Up @@ -785,7 +785,7 @@ spec:
scrapeTimeout: 10s
externalLabels:
cluster: my-cluster
vmAgentExternalLabelName: example
externalLabelName: example
remoteWrite:
- url: "http://vmsingle-example.default.svc:8428/api/v1/write"
inlineRelabelConfig:
Expand Down
3 changes: 3 additions & 0 deletions internal/controller/operator/factory/build/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ func addVMAgentDefaults(objI any) {
cv := config.ApplicationDefaults(c.VMAgentDefault)
addDefaultsToCommonParams(&cr.Spec.CommonDefaultableParams, cr.Spec.License, &cv)
addDefaultsToConfigReloader(&cr.Spec.CommonConfigReloaderParams, ptr.Deref(cr.Spec.UseDefaultResources, false))
if cr.Spec.IngestOnlyMode == nil {
cr.Spec.IngestOnlyMode = ptr.To(false)
}
}

func addVLAgentDefaults(objI any) {
Expand Down
Loading
Loading