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 `,