diff --git a/api/operator/v1/vmanomaly_types.go b/api/operator/v1/vmanomaly_types.go
index 9962ea257..857aee36c 100644
--- a/api/operator/v1/vmanomaly_types.go
+++ b/api/operator/v1/vmanomaly_types.go
@@ -235,7 +235,7 @@ type VMAnomalyMonitoringSpec struct {
}
// VMAnomalyMonitoringPullSpec defines pull monitoring configuration
-// which is enabled by default and served at POD_IP:8490/metrics
+// which is enabled by default and served at POD_IP:8080/metrics
type VMAnomalyMonitoringPullSpec struct {
// Port defines a port for metrics scrape
Port string `json:"port"`
@@ -397,7 +397,10 @@ func (cr *VMAnomaly) GetServiceScrape() *vmv1beta1.VMServiceScrapeSpec {
// Port returns port for accessing anomaly UI
func (cr *VMAnomaly) Port() string {
- return cr.Spec.Port
+ if cr == nil || cr.Spec.Server == nil || len(cr.Spec.Server.Port) == 0 {
+ return "8490"
+ }
+ return cr.Spec.Server.Port
}
// GetVolumeName returns volume name for persistent storage
@@ -428,7 +431,10 @@ func (cr *VMAnomaly) ProbeScheme() string {
// ProbePort implements build.probeCRD interface
func (cr *VMAnomaly) ProbePort() string {
- return cr.Port()
+ if cr == nil || cr.Spec.Monitoring == nil || cr.Spec.Monitoring.Pull == nil || len(cr.Spec.Monitoring.Pull.Port) == 0 {
+ return "8080"
+ }
+ return cr.Spec.Monitoring.Pull.Port
}
// ProbeNeedLiveness implements build.probeCRD interface
@@ -436,6 +442,13 @@ func (*VMAnomaly) ProbeNeedLiveness() bool {
return true
}
+// AsURL returns url for http access to the first replica.
+// Returns empty string if spec.server.port is not configured.
+func (cr *VMAnomaly) AsURL() string {
+ port := cr.Port()
+ return fmt.Sprintf("http://%s.%s.svc:%s", cr.PrefixedName(), cr.Namespace, port)
+}
+
// Validate performs semantic validation for component
func (cr *VMAnomaly) Validate() error {
if vmv1beta1.MustSkipCRValidation(cr) {
diff --git a/api/operator/v1beta1/vmuser_types.go b/api/operator/v1beta1/vmuser_types.go
index 420c98b26..bc2e665ba 100644
--- a/api/operator/v1beta1/vmuser_types.go
+++ b/api/operator/v1beta1/vmuser_types.go
@@ -195,8 +195,8 @@ type NamespacedName struct {
// CRDRef describe CRD target reference.
type CRDRef struct {
// Kind one of:
- // VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent
- // +kubebuilder:validation:Enum=VMAgent;VMAlert;VMSingle;VLogs;VMAlertManager;VMAlertmanager;VMCluster/vmselect;VMCluster/vmstorage;VMCluster/vminsert;VLSingle;VLCluster/vlinsert;VLCluster/vlselect;VLCluster/vlstorage;VLAgent;VTCluster/vtinsert;VTCluster/vtselect;VTCluster/vtstorage;VTSingle
+ // VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent
+ // +kubebuilder:validation:Enum=VMAgent;VMAlert;VMSingle;VLogs;VMAlertManager;VMAlertmanager;VMCluster/vmselect;VMCluster/vmstorage;VMCluster/vminsert;VLSingle;VLCluster/vlinsert;VLCluster/vlselect;VLCluster/vlstorage;VLAgent;VTCluster/vtinsert;VTCluster/vtselect;VTCluster/vtstorage;VTSingle;VMAnomaly
Kind string `json:"kind"`
NamespacedName `json:",inline"`
// Objects defines list of name/namespace pairs that define existing k8s object
diff --git a/config/crd/overlay/crd.descriptionless.yaml b/config/crd/overlay/crd.descriptionless.yaml
index fbab3c958..b5e8eb470 100644
--- a/config/crd/overlay/crd.descriptionless.yaml
+++ b/config/crd/overlay/crd.descriptionless.yaml
@@ -13770,6 +13770,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
type: string
@@ -14848,6 +14849,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
type: string
@@ -19114,6 +19116,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
type: string
@@ -22005,6 +22008,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
type: string
@@ -42966,6 +42970,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
type: string
diff --git a/config/crd/overlay/crd.yaml b/config/crd/overlay/crd.yaml
index b6a283774..190040c1a 100644
--- a/config/crd/overlay/crd.yaml
+++ b/config/crd/overlay/crd.yaml
@@ -24571,7 +24571,7 @@ spec:
pull:
description: |-
VMAnomalyMonitoringPullSpec defines pull monitoring configuration
- which is enabled by default and served at POD_IP:8490/metrics
+ which is enabled by default and served at POD_IP:8080/metrics
properties:
port:
description: Port defines a port for metrics scrape
@@ -26800,7 +26800,7 @@ spec:
kind:
description: |-
Kind one of:
- VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent
+ VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent
enum:
- VMAgent
- VMAlert
@@ -26820,6 +26820,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
description: Name of the target Kubernetes object
@@ -28976,7 +28977,7 @@ spec:
kind:
description: |-
Kind one of:
- VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent
+ VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent
enum:
- VMAgent
- VMAlert
@@ -28996,6 +28997,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
description: Name of the target Kubernetes object
@@ -37425,7 +37427,7 @@ spec:
kind:
description: |-
Kind one of:
- VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent
+ VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent
enum:
- VMAgent
- VMAlert
@@ -37445,6 +37447,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
description: Name of the target Kubernetes object
@@ -43598,7 +43601,7 @@ spec:
kind:
description: |-
Kind one of:
- VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent
+ VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent
enum:
- VMAgent
- VMAlert
@@ -43618,6 +43621,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
description: Name of the target Kubernetes object
@@ -85844,7 +85848,7 @@ spec:
kind:
description: |-
Kind one of:
- VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent
+ VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent
enum:
- VMAgent
- VMAlert
@@ -85864,6 +85868,7 @@ spec:
- VTCluster/vtselect
- VTCluster/vtstorage
- VTSingle
+ - VMAnomaly
type: string
name:
description: Name of the target Kubernetes object
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 98fe4b923..c2e55d240 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -15,6 +15,7 @@ aliases:
* Dependency: [vmoperator](https://docs.victoriametrics.com/operator/): Updated default versions for VM apps to [v1.142.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.142.0) version
* FEATURE: [vmauth](https://docs.victoriametrics.com/operator/resources/vmauth): previously VMAuth could read configuration only from predefined locations; now VMAuth supports arbitrary filesystem access configuration, allowing users to reference required files directly and reducing configuration workarounds. See [#899](https://github.com/VictoriaMetrics/operator/issues/899).
+* FEATURE: [vmuser](https://docs.victoriametrics.com/operator/resources/vmuser/): support VMAnomaly CRD in VMUser targetRefs. See [#2141](https://github.com/VictoriaMetrics/operator/issues/2141).
* BUGFIX: [converter](https://docs.victoriametrics.com/operator/integrations/prometheus/#objects-conversion): disable all prometheus controllers if CRD group was not found. See [#2838](https://github.com/VictoriaMetrics/helm-charts/issues/2838).
* BUGFIX: [vmdistributed](https://docs.victoriametrics.com/operator/resources/vmdistributed/): change default load balancing policy for write requests from `first_available` to `least_loaded`. This should allow to evenly distribute write load across all VMAgents.
diff --git a/docs/api.md b/docs/api.md
index 63b7790e5..5e308237a 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -616,7 +616,7 @@ Appears in: [VMAnomalyMonitoringPushSpec](#vmanomalymonitoringpushspec), [VMAnom
#### VMAnomalyMonitoringPullSpec
VMAnomalyMonitoringPullSpec defines pull monitoring configuration
-which is enabled by default and served at POD_IP:8490/metrics
+which is enabled by default and served at POD_IP:8080/metrics
Appears in: [VMAnomalyMonitoringSpec](#vmanomalymonitoringspec)
@@ -1453,7 +1453,7 @@ Appears in: [TargetRef](#targetref)
| Field | Description |
| --- | --- |
-| kind#
_string_ | _(Required)_
Kind one of:
VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage and VLAgent |
+| kind#
_string_ | _(Required)_
Kind one of:
VMAgent,VMAlert, VMSingle, VMCluster/vmselect, VMCluster/vmstorage,VMCluster/vminsert,VMAlertManager, VLSingle, VLCluster/vlinsert, VLCluster/vlselect, VLCluster/vlstorage, VTSingle, VTCluster/vtinsert, VTCluster/vtselect, VTCluster/vtstorage VMAnomaly and VLAgent |
| name#
_string_ | _(Required)_
Name of the target Kubernetes object |
| namespace#
_string_ | _(Required)_
Namespace of the target Kubernetes object |
| objects#
_[NamespacedName](#namespacedname) array_ | _(Optional)_
Objects defines list of name/namespace pairs that define existing k8s object |
diff --git a/internal/controller/operator/factory/build/defaults.go b/internal/controller/operator/factory/build/defaults.go
index cc70e86ad..0f0157b61 100644
--- a/internal/controller/operator/factory/build/defaults.go
+++ b/internal/controller/operator/factory/build/defaults.go
@@ -333,11 +333,19 @@ func addVMAnomalyDefaults(objI any) {
}
addDefaultsToCommonParams(&cr.Spec.CommonAppsParams, &cp, &cv)
if cr.Spec.Monitoring == nil {
- cr.Spec.Monitoring = &vmv1.VMAnomalyMonitoringSpec{
- Pull: &vmv1.VMAnomalyMonitoringPullSpec{
- Port: "8080",
- },
- }
+ cr.Spec.Monitoring = &vmv1.VMAnomalyMonitoringSpec{}
+ }
+ if cr.Spec.Monitoring.Pull == nil {
+ cr.Spec.Monitoring.Pull = &vmv1.VMAnomalyMonitoringPullSpec{}
+ }
+ if len(cr.Spec.Monitoring.Pull.Port) == 0 {
+ cr.Spec.Monitoring.Pull.Port = "8080"
+ }
+ if cr.Spec.Server == nil {
+ cr.Spec.Server = &vmv1.VMAnomalyServerSpec{}
+ }
+ if len(cr.Spec.Server.Port) == 0 {
+ cr.Spec.Server.Port = cv.Port
}
}
diff --git a/internal/controller/operator/factory/finalize/vmanomaly.go b/internal/controller/operator/factory/finalize/vmanomaly.go
index b3deed356..a0698bd55 100644
--- a/internal/controller/operator/factory/finalize/vmanomaly.go
+++ b/internal/controller/operator/factory/finalize/vmanomaly.go
@@ -28,6 +28,7 @@ func OnVMAnomalyDelete(ctx context.Context, rclient client.Client, cr *vmv1.VMAn
}
objsToRemove := []client.Object{
&appsv1.StatefulSet{ObjectMeta: objMeta},
+ &corev1.Service{ObjectMeta: objMeta},
&corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{
Name: cr.GetServiceAccountName(),
Namespace: ns,
diff --git a/internal/controller/operator/factory/vmanomaly/config/config_test.go b/internal/controller/operator/factory/vmanomaly/config/config_test.go
index 4da611da7..b04532a55 100644
--- a/internal/controller/operator/factory/vmanomaly/config/config_test.go
+++ b/internal/controller/operator/factory/vmanomaly/config/config_test.go
@@ -310,6 +310,8 @@ monitoring:
label1: value1
settings:
restore_state: true
+server:
+ port: "8490"
`,
})
@@ -388,6 +390,8 @@ settings:
retention:
ttl: 24h
check_interval: 30m
+server:
+ port: "8490"
`,
})
@@ -543,6 +547,8 @@ writer:
monitoring:
pull:
port: "8080"
+server:
+ port: "8490"
`,
})
@@ -617,6 +623,8 @@ writer:
monitoring:
pull:
port: "8080"
+server:
+ port: "8490"
`,
})
@@ -838,6 +846,8 @@ monitoring:
port: "8080"
settings:
restore_state: true
+server:
+ port: "8490"
`,
})
}
diff --git a/internal/controller/operator/factory/vmanomaly/statefulset.go b/internal/controller/operator/factory/vmanomaly/statefulset.go
index 3d94c9931..deffff36e 100644
--- a/internal/controller/operator/factory/vmanomaly/statefulset.go
+++ b/internal/controller/operator/factory/vmanomaly/statefulset.go
@@ -23,6 +23,13 @@ import (
"github.com/VictoriaMetrics/operator/internal/controller/operator/factory/reconcile"
)
+func buildService(cr *vmv1.VMAnomaly) *corev1.Service {
+ return build.Service(cr, cr.Spec.Server.Port, func(svc *corev1.Service) {
+ svc.Spec.ClusterIP = "None"
+ svc.Spec.PublishNotReadyAddresses = true
+ })
+}
+
func buildScrape(cr *vmv1.VMAnomaly) *vmv1beta1.VMPodScrape {
if cr == nil || ptr.Deref(cr.Spec.DisableSelfServiceScrape, false) {
return nil
@@ -54,6 +61,15 @@ func CreateOrUpdate(ctx context.Context, cr *vmv1.VMAnomaly, rclient client.Clie
}
}
+ svc := buildService(cr)
+ var prevSvc *corev1.Service
+ if prevCR != nil {
+ prevSvc = buildService(prevCR)
+ }
+ if err := reconcile.Service(ctx, rclient, svc, prevSvc, &owner); err != nil {
+ return fmt.Errorf("cannot reconcile headless service for vmanomaly: %w", err)
+ }
+
if !ptr.Deref(cr.Spec.DisableSelfServiceScrape, false) {
svs := buildScrape(cr)
prevSvs := buildScrape(prevCR)
@@ -125,6 +141,7 @@ func newK8sApp(cr *vmv1.VMAnomaly, ac *build.AssetsCache) (*appsv1.StatefulSet,
OwnerReferences: []metav1.OwnerReference{cr.AsOwner()},
},
Spec: appsv1.StatefulSetSpec{
+ ServiceName: cr.PrefixedName(),
Selector: &metav1.LabelSelector{
MatchLabels: build.ShardSelectorLabels(cr),
},
diff --git a/internal/controller/operator/factory/vmanomaly/vmanomaly_reconcile_test.go b/internal/controller/operator/factory/vmanomaly/vmanomaly_reconcile_test.go
index 2b3622e40..d19c57eab 100644
--- a/internal/controller/operator/factory/vmanomaly/vmanomaly_reconcile_test.go
+++ b/internal/controller/operator/factory/vmanomaly/vmanomaly_reconcile_test.go
@@ -142,6 +142,8 @@ schedulers:
actions: []k8stools.ClientAction{
{Verb: "Get", Kind: "ServiceAccount", Resource: vmanomalyName},
{Verb: "Create", Kind: "ServiceAccount", Resource: vmanomalyName},
+ {Verb: "Get", Kind: "Service", Resource: vmanomalyName},
+ {Verb: "Create", Kind: "Service", Resource: vmanomalyName},
{Verb: "Get", Kind: "VMPodScrape", Resource: vmanomalyName},
{Verb: "Create", Kind: "VMPodScrape", Resource: vmanomalyName},
// Secrets
@@ -195,6 +197,7 @@ schedulers:
want{
actions: []k8stools.ClientAction{
{Verb: "Get", Kind: "ServiceAccount", Resource: vmanomalyName},
+ {Verb: "Get", Kind: "Service", Resource: vmanomalyName},
{Verb: "Get", Kind: "VMPodScrape", Resource: vmanomalyName},
// Secrets
{Verb: "Get", Kind: "Secret", Resource: tlsAssetName},
@@ -245,6 +248,7 @@ schedulers:
want{
actions: []k8stools.ClientAction{
{Verb: "Get", Kind: "ServiceAccount", Resource: vmanomalyName},
+ {Verb: "Get", Kind: "Service", Resource: vmanomalyName},
{Verb: "Get", Kind: "VMPodScrape", Resource: vmanomalyName},
// Secrets
{Verb: "Get", Kind: "Secret", Resource: tlsAssetName},
diff --git a/internal/controller/operator/factory/vmauth/vmusers_config.go b/internal/controller/operator/factory/vmauth/vmusers_config.go
index af8706dba..d7ddb73f7 100644
--- a/internal/controller/operator/factory/vmauth/vmusers_config.go
+++ b/internal/controller/operator/factory/vmauth/vmusers_config.go
@@ -318,6 +318,7 @@ var crdNameToObject = map[string]objectWithURL{
"VMCluster/vmselect": newClusterWithURL("vmselect"),
"VMCluster/vminsert": newClusterWithURL("vminsert"),
"VMCluster/vmstorage": newClusterWithURL("vmstorage"),
+ "VMAnomaly": &vmv1.VMAnomaly{},
"VLSingle": &vmv1.VLSingle{},
"VLCluster/vlselect": newClusterWithURL("vlselect"),
"VLCluster/vlinsert": newClusterWithURL("vlinsert"),
diff --git a/internal/controller/operator/factory/vmauth/vmusers_config_test.go b/internal/controller/operator/factory/vmauth/vmusers_config_test.go
index 437cdf6dd..982d6675d 100644
--- a/internal/controller/operator/factory/vmauth/vmusers_config_test.go
+++ b/internal/controller/operator/factory/vmauth/vmusers_config_test.go
@@ -2948,9 +2948,25 @@ unauthorized_user:
},
Paths: []string{"/internal.*"},
},
+ {
+ CRD: &vmv1beta1.CRDRef{
+ Kind: "VMAnomaly",
+ NamespacedName: vmv1beta1.NamespacedName{
+ Name: "test",
+ Namespace: "default",
+ },
+ },
+ Paths: []string{"/anomaly.*"},
+ },
},
},
},
+ &vmv1.VMAnomaly{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test",
+ Namespace: "default",
+ },
+ },
&vmv1.VLCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
@@ -2977,6 +2993,10 @@ unauthorized_user:
- http://vlstorage-test.default.svc:9491
src_paths:
- /internal.*
+ - url_prefix:
+ - http://vmanomaly-test.default.svc:8490
+ src_paths:
+ - /anomaly.*
name: user1
bearer_token: bearer
`,