diff --git a/api/operator/v1beta1/vmservicescrape_types.go b/api/operator/v1beta1/vmservicescrape_types.go index 324d14b66..d1b983f7d 100644 --- a/api/operator/v1beta1/vmservicescrape_types.go +++ b/api/operator/v1beta1/vmservicescrape_types.go @@ -20,7 +20,7 @@ type VMServiceScrapeSpec struct { // note, that with service setting, you have to use port: "name" // and cannot use targetPort for endpoints. // +optional - // +kubebuilder:validation:Enum=endpoints;service;endpointslices + // +kubebuilder:validation:Enum=endpoints;service;endpointslices;endpointslice DiscoveryRole string `json:"discoveryRole,omitempty"` // The label to use to retrieve the job name from. // +optional diff --git a/config/crd/overlay/crd.yaml b/config/crd/overlay/crd.yaml index 667068228..4ec01b2c2 100644 --- a/config/crd/overlay/crd.yaml +++ b/config/crd/overlay/crd.yaml @@ -23210,6 +23210,7 @@ spec: - endpoints - service - endpointslices + - endpointslice type: string endpoints: items: @@ -29001,6 +29002,7 @@ spec: - endpoints - service - endpointslices + - endpointslice type: string endpoints: items: diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 24aa9c930..c425736f3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -26,6 +26,7 @@ aliases: * BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): fixed conflicts for `VMAlert`, `VMAlertmanager` and `VMAuth` reconcilers, which are updating same objects concurrently with reconcilers for their child objects. * BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): previously PVC downscaling always emitted a warning, which is not expected, while using PVC autoresizer; now warning during attempt to downsize PVC is only emitted if `operator.victoriametrics.com/pvc-allow-volume-expansion: false` is not set. See [#1747](https://github.com/VictoriaMetrics/operator/issues/1747). * BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): skip self scrape objects management if respective controller is disabled. See [#1718](https://github.com/VictoriaMetrics/operator/issues/1718). +* BUGFIX: [vmagent](https://docs.victoriametrics.com/operator/resources/vmagent/): support both prometheus-compatible `endpointslice` and old `endpointslices` roles. ## [v0.67.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.67.0) **Release date:** 23 January 2026 diff --git a/docs/resources/vmservicescrape.md b/docs/resources/vmservicescrape.md index 90364267f..ddaf59ca9 100644 --- a/docs/resources/vmservicescrape.md +++ b/docs/resources/vmservicescrape.md @@ -23,7 +23,7 @@ need to reconfigure. It has various options for scraping configuration of target (with basic auth,tls access, by specific port name etc.). Monitoring configuration is based on `discoveryRole` setting. By default, `endpoints` is used to get objects from kubernetes api. -It's also possible to use `discoveryRole: service` or `discoveryRole: endpointslices`. +It's also possible to use `discoveryRole: service` or `discoveryRole: endpointslice`. `Endpoints` objects are essentially lists of IP addresses. Typically, `Endpoints` objects are populated by `Service` object. `Service` object discovers `Pod`s by a label diff --git a/internal/controller/operator/factory/vmagent/servicescrape.go b/internal/controller/operator/factory/vmagent/servicescrape.go index 5fa7ffdf6..52ce8808e 100644 --- a/internal/controller/operator/factory/vmagent/servicescrape.go +++ b/internal/controller/operator/factory/vmagent/servicescrape.go @@ -87,7 +87,7 @@ func generateServiceScrapeConfig( {Key: "source_labels", Value: []string{"__meta_kubernetes_endpoint_port_name"}}, {Key: "regex", Value: ep.Port}, }) - case k8sSDRoleEndpointslice: + case k8sSDRoleEndpointslice, k8sSDRoleLegacyEndpointslices: relabelings = append(relabelings, yaml.MapSlice{ {Key: "action", Value: "keep"}, {Key: "source_labels", Value: []string{"__meta_kubernetes_endpointslice_port_name"}}, @@ -120,7 +120,7 @@ func generateServiceScrapeConfig( switch spec.DiscoveryRole { case k8sSDRoleService: // nothing to do, service doesn't have relations with pods. - case k8sSDRoleEndpointslice: + case k8sSDRoleEndpointslice, k8sSDRoleLegacyEndpointslices: // Relabel namespace and pod and service labels into proper labels. relabelings = append(relabelings, []yaml.MapSlice{ { // Relabel node labels for pre v2.3 meta labels diff --git a/internal/controller/operator/factory/vmagent/vmagent_scrapeconfig.go b/internal/controller/operator/factory/vmagent/vmagent_scrapeconfig.go index cd8f76cd4..8d6222e01 100644 --- a/internal/controller/operator/factory/vmagent/vmagent_scrapeconfig.go +++ b/internal/controller/operator/factory/vmagent/vmagent_scrapeconfig.go @@ -185,6 +185,9 @@ const ( k8sSDRolePod = "pod" k8sSDRoleIngress = "ingress" k8sSDRoleNode = "node" + + // before 0.67.0 endpointslice was called endpointslices. keeping old name for backward compatibility + k8sSDRoleLegacyEndpointslices = "endpointslices" ) var invalidLabelCharRE = regexp.MustCompile(`[^a-zA-Z0-9_]`) @@ -244,7 +247,7 @@ func addAttachMetadata(dst yaml.MapSlice, am *vmv1beta1.AttachMetadata, role str var items yaml.MapSlice if am.Node != nil && *am.Node { switch role { - case k8sSDRolePod, k8sSDRoleEndpoints, k8sSDRoleEndpointslice: + case k8sSDRolePod, k8sSDRoleEndpoints, k8sSDRoleEndpointslice, k8sSDRoleLegacyEndpointslices: items = append(items, yaml.MapItem{ Key: "node", Value: true, @@ -253,7 +256,7 @@ func addAttachMetadata(dst yaml.MapSlice, am *vmv1beta1.AttachMetadata, role str } if am.Namespace != nil && *am.Namespace { switch role { - case k8sSDRolePod, k8sSDRoleService, k8sSDRoleEndpoints, k8sSDRoleEndpointslice, k8sSDRoleIngress: + case k8sSDRolePod, k8sSDRoleService, k8sSDRoleEndpoints, k8sSDRoleEndpointslice, k8sSDRoleIngress, k8sSDRoleLegacyEndpointslices: items = append(items, yaml.MapItem{ Key: "namespace", Value: true, @@ -462,7 +465,7 @@ func generateK8SSDConfig(ac *build.AssetsCache, opts generateK8SSDConfigOptions) // special case, given roles create additional watchers for // pod and services roles - if opts.role == k8sSDRoleEndpoints || opts.role == k8sSDRoleEndpointslice { + if opts.role == k8sSDRoleEndpoints || opts.role == k8sSDRoleEndpointslice || opts.role == k8sSDRoleLegacyEndpointslices { for _, role := range []string{k8sSDRolePod, k8sSDRoleService} { selectors = append(selectors, yaml.MapSlice{ { diff --git a/internal/webhook/operator/v1beta1/vmservicescrape_webhook.go b/internal/webhook/operator/v1beta1/vmservicescrape_webhook.go index d301e6030..4d102b66d 100644 --- a/internal/webhook/operator/v1beta1/vmservicescrape_webhook.go +++ b/internal/webhook/operator/v1beta1/vmservicescrape_webhook.go @@ -26,6 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" vmv1beta1 "github.com/VictoriaMetrics/operator/api/operator/v1beta1" + "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/logger" ) // SetupVMServiceScrapeWebhookWithManager will setup the manager to manage the webhooks @@ -42,7 +43,7 @@ type VMServiceScrapeCustomValidator struct{} var _ admission.CustomValidator = &VMServiceScrapeCustomValidator{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (*VMServiceScrapeCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { +func (*VMServiceScrapeCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { r, ok := obj.(*vmv1beta1.VMServiceScrape) if !ok { return nil, fmt.Errorf("BUG: unexpected type: %T", obj) @@ -53,11 +54,14 @@ func (*VMServiceScrapeCustomValidator) ValidateCreate(_ context.Context, obj run if err := r.Validate(); err != nil { return nil, err } + if r.Spec.DiscoveryRole == "endpointslices" { + logger.WithContext(ctx).Info("deprecated discoverRole value `endpointslices`, use `endpointslice` instead.") + } return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (*VMServiceScrapeCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { +func (*VMServiceScrapeCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { r, ok := newObj.(*vmv1beta1.VMServiceScrape) if !ok { return nil, fmt.Errorf("BUG: unexpected type: %T", newObj) @@ -68,6 +72,9 @@ func (*VMServiceScrapeCustomValidator) ValidateUpdate(_ context.Context, oldObj, if err := r.Validate(); err != nil { return nil, err } + if r.Spec.DiscoveryRole == "endpointslices" { + logger.WithContext(ctx).Info("deprecated discoverRole value `endpointslices`, use `endpointslice` instead.") + } return nil, nil }