diff --git a/api/operator/v1/vlagent_types.go b/api/operator/v1/vlagent_types.go index 4a711f9a8..924fd163d 100644 --- a/api/operator/v1/vlagent_types.go +++ b/api/operator/v1/vlagent_types.go @@ -97,7 +97,10 @@ type VLAgentSpec struct { // UseLegacyNaming uses standalone Helm chart naming for managed resources: // the CR name is used directly instead of the default "-" convention. // +optional - UseLegacyNaming bool `json:"useLegacyNaming,omitempty"` + UseLegacyNaming bool `json:"useLegacyNaming,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *vmv1beta1.EmbeddedVPA `json:"vpa,omitempty"` vmv1beta1.CommonAppsParams `json:",inline,omitempty"` } @@ -183,6 +186,11 @@ func (cr *VLAgent) Validate() error { return fmt.Errorf("remoteWrite.tlsConfig has incorrect syntax at idx: %d: %w", idx, err) } } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } @@ -417,6 +425,14 @@ func (cr *VLAgent) PrefixedName() string { return fmt.Sprintf("vlagent-%s", cr.Name) } +// WorkloadKind returns the kind of workload deployed for VLAgent based on the current mode. +func (cr *VLAgent) WorkloadKind() vmv1beta1.WorkloadKind { + if cr.Spec.K8sCollector.Enabled { + return vmv1beta1.WorkloadKindDaemonSet + } + return vmv1beta1.WorkloadKindStatefulSet +} + // HealthPath returns path for health requests func (cr *VLAgent) HealthPath() string { return vmv1beta1.BuildPathWithPrefixFlag(cr.Spec.ExtraArgs, healthPath) diff --git a/api/operator/v1/vlsingle_types.go b/api/operator/v1/vlsingle_types.go index b963fdfff..d20ab34b7 100644 --- a/api/operator/v1/vlsingle_types.go +++ b/api/operator/v1/vlsingle_types.go @@ -111,6 +111,9 @@ type VLSingleSpec struct { // SyslogSpec defines syslog listener configuration // +optional SyslogSpec *SyslogServerSpec `json:"syslogSpec,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *vmv1beta1.EmbeddedVPA `json:"vpa,omitempty"` } // VLSingleStatus defines the observed state of VLSingle @@ -297,6 +300,11 @@ func (cr *VLSingle) Validate() error { if cr.Spec.ServiceSpec != nil && cr.Spec.ServiceSpec.Name == cr.PrefixedName() { return fmt.Errorf("spec.serviceSpec.Name cannot be equal to prefixed name=%q", cr.PrefixedName()) } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } diff --git a/api/operator/v1/vmanomaly_types.go b/api/operator/v1/vmanomaly_types.go index 26e979abe..b613022c1 100644 --- a/api/operator/v1/vmanomaly_types.go +++ b/api/operator/v1/vmanomaly_types.go @@ -61,6 +61,9 @@ type VMAnomalySpec struct { // PodDisruptionBudget created by operator // +optional PodDisruptionBudget *vmv1beta1.EmbeddedPodDisruptionBudgetSpec `json:"podDisruptionBudget,omitempty"` + // VPA defines configuration for the VerticalPodAutoscaler. + // +optional + VPA *vmv1beta1.EmbeddedVPA `json:"vpa,omitempty"` // ConfigRawYaml - raw configuration for anomaly, // it helps it to start without secret. // priority -> hardcoded ConfigRaw -> ConfigRaw, provided by user -> ConfigSecret. @@ -489,6 +492,11 @@ func (cr *VMAnomaly) Validate() error { if !cr.Spec.License.IsProvided() { return fmt.Errorf("no license is provided!. Either spec.license.key or spec.license.keyRef is required") } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } diff --git a/api/operator/v1/vtsingle_types.go b/api/operator/v1/vtsingle_types.go index 647139558..4849d891d 100644 --- a/api/operator/v1/vtsingle_types.go +++ b/api/operator/v1/vtsingle_types.go @@ -105,6 +105,9 @@ type VTSingleSpec struct { // it can be overwritten with component specific image.tag value. // +optional ComponentVersion string `json:"componentVersion,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *vmv1beta1.EmbeddedVPA `json:"vpa,omitempty"` } // VTSingleStatus defines the observed state of VTSingle @@ -292,6 +295,11 @@ func (cr *VTSingle) Validate() error { if cr.Spec.ServiceSpec != nil && cr.Spec.ServiceSpec.Name == cr.PrefixedName() { return fmt.Errorf("spec.serviceSpec.Name cannot be equal to prefixed name=%q", cr.PrefixedName()) } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } diff --git a/api/operator/v1/zz_generated.deepcopy.go b/api/operator/v1/zz_generated.deepcopy.go index 8ed149ec0..ccef729c2 100644 --- a/api/operator/v1/zz_generated.deepcopy.go +++ b/api/operator/v1/zz_generated.deepcopy.go @@ -484,6 +484,11 @@ func (in *VLAgentSpec) DeepCopyInto(out *VLAgentSpec) { *out = new(v1beta1.License) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(v1beta1.EmbeddedVPA) + (*in).DeepCopyInto(*out) + } in.CommonAppsParams.DeepCopyInto(&out.CommonAppsParams) } @@ -870,6 +875,11 @@ func (in *VLSingleSpec) DeepCopyInto(out *VLSingleSpec) { *out = new(SyslogServerSpec) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(v1beta1.EmbeddedVPA) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VLSingleSpec. @@ -1292,6 +1302,11 @@ func (in *VMAnomalySpec) DeepCopyInto(out *VMAnomalySpec) { *out = new(v1beta1.EmbeddedPodDisruptionBudgetSpec) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(v1beta1.EmbeddedVPA) + (*in).DeepCopyInto(*out) + } if in.ConfigSecret != nil { in, out := &in.ConfigSecret, &out.ConfigSecret *out = new(corev1.SecretKeySelector) @@ -1754,6 +1769,11 @@ func (in *VTSingleSpec) DeepCopyInto(out *VTSingleSpec) { *out = new(v1beta1.VMServiceScrapeSpec) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(v1beta1.EmbeddedVPA) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VTSingleSpec. diff --git a/api/operator/v1beta1/vmagent_types.go b/api/operator/v1beta1/vmagent_types.go index 9a4c200ea..9fb28012c 100644 --- a/api/operator/v1beta1/vmagent_types.go +++ b/api/operator/v1beta1/vmagent_types.go @@ -137,6 +137,9 @@ type VMAgentSpec struct { // Configures horizontal pod autoscaling. // +optional HPA *EmbeddedHPA `json:"hpa,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *EmbeddedVPA `json:"vpa,omitempty"` CommonRelabelParams `json:",inline,omitempty"` CommonScrapeParams `json:",inline,omitempty"` @@ -189,6 +192,9 @@ func (cr *VMAgent) Validate() error { if cr.Spec.HPA != nil { return fmt.Errorf("hpa cannot be used with daemonSetMode") } + if cr.Spec.VPA != nil { + return fmt.Errorf("vpa cannot be used with daemonSetMode") + } if cr.Spec.PodDisruptionBudget != nil { return fmt.Errorf("podDisruptionBudget cannot be used with daemonSetMode") } @@ -201,6 +207,11 @@ func (cr *VMAgent) Validate() error { return err } } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } scrapeClassNames := sets.New[string]() defaultScrapeClass := false for _, sc := range cr.Spec.ScrapeClasses { @@ -241,6 +252,18 @@ func (cr *VMAgent) IsSharded() bool { return cr != nil && cr.Spec.ShardCount != nil && *cr.Spec.ShardCount > 0 && !cr.Spec.DaemonSetMode } +// WorkloadKind returns the kind of workload deployed for VMAgent based on the current mode. +func (cr *VMAgent) WorkloadKind() WorkloadKind { + switch { + case cr.Spec.DaemonSetMode: + return WorkloadKindDaemonSet + case cr.Spec.StatefulMode: + return WorkloadKindStatefulSet + default: + return WorkloadKindDeployment + } +} + // GetShardCount returns shard count for vmagent func (cr *VMAgent) GetShardCount() int32 { if !cr.IsSharded() { diff --git a/api/operator/v1beta1/vmalert_types.go b/api/operator/v1beta1/vmalert_types.go index 973253558..cdf3db71a 100644 --- a/api/operator/v1beta1/vmalert_types.go +++ b/api/operator/v1beta1/vmalert_types.go @@ -135,6 +135,9 @@ type VMAlertSpec struct { // PodDisruptionBudget created by operator // +optional PodDisruptionBudget *EmbeddedPodDisruptionBudgetSpec `json:"podDisruptionBudget,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *EmbeddedVPA `json:"vpa,omitempty"` // License allows to configure license key to be used for enterprise features. // Using license key is supported starting from VictoriaMetrics v1.94.0. // See [here](https://docs.victoriametrics.com/victoriametrics/enterprise/) @@ -403,6 +406,11 @@ func (cr *VMAlert) Validate() error { if err := validateNotifierConfigs(); err != nil { return err } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } diff --git a/api/operator/v1beta1/vmalertmanager_types.go b/api/operator/v1beta1/vmalertmanager_types.go index 2dc14afb2..54167d78d 100644 --- a/api/operator/v1beta1/vmalertmanager_types.go +++ b/api/operator/v1beta1/vmalertmanager_types.go @@ -219,6 +219,9 @@ type VMAlertmanagerSpec struct { // it can be overwritten with component specific image.tag value. // +optional ComponentVersion string `json:"componentVersion,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *EmbeddedVPA `json:"vpa,omitempty"` CommonConfigReloaderParams `json:",inline,omitempty"` CommonAppsParams `json:",inline,omitempty"` @@ -594,6 +597,11 @@ func (cr *VMAlertmanager) Validate() error { if cr.Spec.DisableNamespaceMatcher && cr.Spec.EnforcedNamespaceLabel != "" { return fmt.Errorf("cannot use both disableNamespaceMatcher and enforcedNamespaceLabel at the same time") } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } diff --git a/api/operator/v1beta1/vmextra_types.go b/api/operator/v1beta1/vmextra_types.go index abf6b22b9..4f3164f3f 100644 --- a/api/operator/v1beta1/vmextra_types.go +++ b/api/operator/v1beta1/vmextra_types.go @@ -35,6 +35,15 @@ const ( UpdateStatusPaused UpdateStatus = "paused" ) +// WorkloadKind represents the kind of Kubernetes workload managed by an operator component. +type WorkloadKind string + +const ( + WorkloadKindDaemonSet WorkloadKind = "DaemonSet" + WorkloadKindStatefulSet WorkloadKind = "StatefulSet" + WorkloadKindDeployment WorkloadKind = "Deployment" +) + // ClusterComponent defines component kind for cluster type ClusterComponent string diff --git a/api/operator/v1beta1/vmsingle_types.go b/api/operator/v1beta1/vmsingle_types.go index 3922a6e89..d227fdb43 100644 --- a/api/operator/v1beta1/vmsingle_types.go +++ b/api/operator/v1beta1/vmsingle_types.go @@ -105,6 +105,9 @@ type VMSingleSpec struct { // it can be overwritten with component specific image.tag value. // +optional ComponentVersion string `json:"componentVersion,omitempty"` + // Configures vertical pod autoscaling. + // +optional + VPA *EmbeddedVPA `json:"vpa,omitempty"` CommonRelabelParams `json:",inline,omitempty"` CommonScrapeParams `json:",inline,omitempty"` @@ -462,6 +465,11 @@ func (cr *VMSingle) Validate() error { return fmt.Errorf("spec.volumeMounts must have at least 1 value OR spec.volumes must have volume.name `data` for spec.storageDataPath=%q", cr.Spec.StorageDataPath) } } + if cr.Spec.VPA != nil { + if err := cr.Spec.VPA.Validate(); err != nil { + return err + } + } if err := cr.Spec.Validate(); err != nil { return err } diff --git a/api/operator/v1beta1/zz_generated.deepcopy.go b/api/operator/v1beta1/zz_generated.deepcopy.go index 90854863a..e636c921b 100644 --- a/api/operator/v1beta1/zz_generated.deepcopy.go +++ b/api/operator/v1beta1/zz_generated.deepcopy.go @@ -4873,6 +4873,11 @@ func (in *VMAgentSpec) DeepCopyInto(out *VMAgentSpec) { *out = new(EmbeddedHPA) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(EmbeddedVPA) + (*in).DeepCopyInto(*out) + } in.CommonRelabelParams.DeepCopyInto(&out.CommonRelabelParams) in.CommonScrapeParams.DeepCopyInto(&out.CommonScrapeParams) in.CommonConfigReloaderParams.DeepCopyInto(&out.CommonConfigReloaderParams) @@ -5151,6 +5156,11 @@ func (in *VMAlertSpec) DeepCopyInto(out *VMAlertSpec) { *out = new(EmbeddedPodDisruptionBudgetSpec) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(EmbeddedVPA) + (*in).DeepCopyInto(*out) + } if in.License != nil { in, out := &in.License, &out.License *out = new(License) @@ -5499,6 +5509,11 @@ func (in *VMAlertmanagerSpec) DeepCopyInto(out *VMAlertmanagerSpec) { (*in).DeepCopyInto(*out) } out.ArbitraryFSAccessThroughSMs = in.ArbitraryFSAccessThroughSMs + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(EmbeddedVPA) + (*in).DeepCopyInto(*out) + } in.CommonConfigReloaderParams.DeepCopyInto(&out.CommonConfigReloaderParams) in.CommonAppsParams.DeepCopyInto(&out.CommonAppsParams) } @@ -7342,6 +7357,11 @@ func (in *VMSingleSpec) DeepCopyInto(out *VMSingleSpec) { *out = new(APIServerConfig) (*in).DeepCopyInto(*out) } + if in.VPA != nil { + in, out := &in.VPA, &out.VPA + *out = new(EmbeddedVPA) + (*in).DeepCopyInto(*out) + } in.CommonRelabelParams.DeepCopyInto(&out.CommonRelabelParams) in.CommonScrapeParams.DeepCopyInto(&out.CommonScrapeParams) in.CommonConfigReloaderParams.DeepCopyInto(&out.CommonConfigReloaderParams) diff --git a/config/crd/overlay/crd.descriptionless.yaml b/config/crd/overlay/crd.descriptionless.yaml index 07049ef1d..76530bf18 100644 --- a/config/crd/overlay/crd.descriptionless.yaml +++ b/config/crd/overlay/crd.descriptionless.yaml @@ -1078,6 +1078,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object required: - remoteWrite type: object @@ -4088,6 +4228,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object type: object status: properties: @@ -7186,6 +7466,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object required: - remoteWrite type: object @@ -11091,6 +11511,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object webConfig: properties: basic_auth_users: @@ -12259,6 +12819,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object required: - datasource type: object @@ -13518,6 +14218,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object writer: properties: basicAuth: @@ -44341,6 +45181,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object type: object status: properties: @@ -48099,6 +49079,146 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + properties: + recommenders: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + resourcePolicy: + properties: + containerPolicies: + items: + properties: + containerName: + type: string + controlledResources: + items: + type: string + type: array + controlledValues: + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + memoryAggregationIntervalCount: + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + mode: + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + properties: + cpu: + properties: + durationSeconds: + format: int32 + type: integer + factor: + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + properties: + evictAfterOOMSeconds: + format: int32 + minimum: 1 + type: integer + evictionRequirements: + items: + properties: + changeRequirement: + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + items: + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + format: int32 + type: integer + updateMode: + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object type: object status: properties: diff --git a/config/crd/overlay/crd.yaml b/config/crd/overlay/crd.yaml index 4d2340746..ea5ee03a5 100644 --- a/config/crd/overlay/crd.yaml +++ b/config/crd/overlay/crd.yaml @@ -2265,6 +2265,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object required: - remoteWrite type: object @@ -8010,6 +8251,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object type: object status: description: VLSingleStatus defines the observed state of VLSingle @@ -14317,6 +14799,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object required: - remoteWrite type: object @@ -21679,6 +22402,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object webConfig: description: |- WebConfig defines configuration for webserver @@ -23907,6 +24871,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object required: - datasource type: object @@ -26476,6 +27681,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: VPA defines configuration for the VerticalPodAutoscaler. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object writer: description: |- Metrics destination for VMAnomaly @@ -88513,6 +89959,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object type: object status: description: VMSingleStatus defines the observed state of VMSingle @@ -95555,6 +97242,247 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true type: array + vpa: + description: Configures vertical pod autoscaling. + properties: + recommenders: + description: Recommenders specifies custom VPA recommender names. + items: + description: |- + VerticalPodAutoscalerRecommenderSelector points to a specific Vertical Pod Autoscaler recommender. + In the future it might pass parameters to the recommender. + properties: + name: + description: Name of the recommender responsible for generating + recommendation for this object. + type: string + required: + - name + type: object + type: array + resourcePolicy: + description: ResourcePolicy controls how the autoscaler computes + recommended resources per container. + properties: + containerPolicies: + description: Per-container resource policies. + items: + description: |- + ContainerResourcePolicy controls how autoscaler computes the recommended + resources for a specific container. + properties: + containerName: + description: |- + Name of the container or DefaultContainerResourcePolicy, in which + case the policy is used by the containers that don't have their own + policy specified. + type: string + controlledResources: + description: |- + Specifies the type of recommendations that will be computed + (and possibly applied) by VPA. + If not specified, the default of [ResourceCPU, ResourceMemory] will be used. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + controlledValues: + description: |- + Specifies which resource values should be controlled. + The default is "RequestsAndLimits". + enum: + - RequestsAndLimits + - RequestsOnly + type: string + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the maximum amount of resources that will be recommended + for the container. The default is no maximum. + type: object + memoryAggregationIntervalCount: + description: |- + memoryAggregationIntervalCount is the number of consecutive + memoryAggregationIntervals which make up the memory aggregation window. + The total window length is: + MemoryAggregationIntervalSeconds * MemoryAggregationIntervalCount. + format: int64 + minimum: 1 + type: integer + memoryAggregationIntervalSeconds: + description: |- + memoryAggregationIntervalSeconds is the length of a single interval + (in seconds) for which the peak memory usage is computed. + Memory usage peaks are aggregated in multiples of this interval. + In other words, there is one memory usage sample per interval + (the maximum usage over that interval). + format: int32 + minimum: 1 + type: integer + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Specifies the minimal amount of resources that will be recommended + for the container. The default is no minimum. + type: object + mode: + description: Whether autoscaler is enabled for the container. + The default is "Auto". + enum: + - Auto + - "Off" + type: string + oomBumpUpRatio: + anyOf: + - type: integer + - type: string + description: oomBumpUpRatio is the ratio to increase + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + oomMinBumpUp: + anyOf: + - type: integer + - type: string + description: oomMinBumpUp is the minimum increase in + memory when OOM is detected. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + startupBoost: + description: |- + startupBoost specifies the startup boost policy for the container. + This overrides any pod-level startup boost policy. + The startup boost policy takes precedence over the rest of the fields in + this struct, except for ContainerName and ControlledValues. + properties: + cpu: + description: |- + cpu specifies the CPU startup boost policy. + If this field is not set, no startup boost is applied. + properties: + durationSeconds: + description: |- + durationSeconds indicates for how long to keep the pod boosted after it goes to Ready. + Defaults to 0. + format: int32 + type: integer + factor: + description: |- + factor specifies the factor to apply to the resource request. + This field is required when Type is "Factor". + format: int32 + type: integer + quantity: + anyOf: + - type: integer + - type: string + description: |- + quantity specifies the absolute resource quantity to be used as the + resource request and limit during the boost phase. + This field is required when Type is "Quantity". + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: |- + type specifies the kind of boost to apply. + Supported values are: "Factor", "Quantity". + No startupboost will be applied for unrecognized values. + enum: + - Factor + - Quantity + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: factor is required when type is Factor + and forbidden otherwise + rule: (self.type == 'Factor') == has(self.factor) + - message: quantity is required when type is Quantity + and forbidden otherwise + rule: (self.type == 'Quantity') == has(self.quantity) + type: object + type: object + type: array + type: object + updatePolicy: + description: UpdatePolicy controls how the autoscaler applies + changes to pod resources. + properties: + evictAfterOOMSeconds: + description: |- + evictAfterOOMSeconds specifies the time in seconds to wait after an OOM event before + considering the pod for eviction. Pods that have OOMed in less than this time + since start will be evicted. + format: int32 + minimum: 1 + type: integer + evictionRequirements: + description: |- + EvictionRequirements is a list of EvictionRequirements that need to + evaluate to true in order for a Pod to be evicted. If more than one + EvictionRequirement is specified, all of them need to be fulfilled to allow eviction. + items: + description: |- + EvictionRequirement defines a single condition which needs to be true in + order to evict a Pod + properties: + changeRequirement: + description: EvictionChangeRequirement refers to the + relationship between the new target recommendation + for a Pod and its current requests, what kind of change + is necessary for the Pod to be evicted + enum: + - TargetHigherThanRequests + - TargetLowerThanRequests + type: string + resources: + description: |- + Resources is a list of one or more resources that the condition applies + to. If more than one resource is given, the EvictionRequirement is fulfilled + if at least one resource meets `changeRequirement`. + items: + description: ResourceName is the name identifying + various resources in a ResourceList. + type: string + type: array + required: + - changeRequirement + - resources + type: object + type: array + minReplicas: + description: |- + Minimal number of replicas which need to be alive for Updater to attempt + pod eviction (pending other checks like PDB). Only positive values are + allowed. Overrides global '--min-replicas' flag. + format: int32 + type: integer + updateMode: + description: |- + Controls when autoscaler applies changes to the pod resources. + The default is 'Recreate'. + enum: + - "Off" + - Initial + - Recreate + - InPlaceOrRecreate + - InPlace + - Auto + type: string + type: object + type: object type: object status: description: VTSingleStatus defines the observed state of VTSingle diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 4ae6bad2e..e98f4105f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -31,8 +31,8 @@ aliases: * FEATURE: [vmoperator](https://docs.victoriametrics.com/operator/): add validating webhooks for Prometheus Operator CRDs (`ServiceMonitor`, `PodMonitor`, `PrometheusRule`, `Probe`, `ScrapeConfig`, `AlertmanagerConfig`). Each object is converted to its VM equivalent and validated when webhooks are enabled. See [#2270](https://github.com/VictoriaMetrics/operator/issues/2270). * FEATURE: [vmscrapeconfig](https://docs.victoriametrics.com/operator/resources/vmscrapeconfig/): add support for `consulAgentSDConfigs`, `dockerSDConfigs`, `dockerSwarmSDConfigs`, `marathonSDConfigs`, and `yandexCloudSDConfigs` service discovery types, bringing `VMScrapeConfig` to full parity with VictoriaMetrics [sd_configs](https://docs.victoriametrics.com/victoriametrics/sd_configs/). See [#2265](https://github.com/VictoriaMetrics/operator/issues/2265). +* FEATURE: [vmagent](https://docs.victoriametrics.com/operator/resources/vmagent/), [vmalert](https://docs.victoriametrics.com/operator/resources/vmalert/), [vmalertmanager](https://docs.victoriametrics.com/operator/resources/vmalertmanager/), [vmsingle](https://docs.victoriametrics.com/operator/resources/vmsingle/), [vlsingle](https://docs.victoriametrics.com/operator/resources/vlsingle/), [vtsingle](https://docs.victoriametrics.com/operator/resources/vtsingle/), [vlagent](https://docs.victoriametrics.com/operator/resources/vlagent/): add `spec.vpa` field to support [VerticalPodAutoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler). See [#2252](https://github.com/VictoriaMetrics/operator/issues/2252). * FEATURE: [vmalert](https://docs.victoriametrics.com/operator/resources/vmalert/): rule ConfigMaps now store gzip-compressed rule files in `binaryData`, allowing larger rule sets within Kubernetes object size limits. An init container decompresses the rules before VMAlert starts. -* FEATURE: [vmscrapeconfig](https://docs.victoriametrics.com/operator/resources/vmscrapeconfig/): add support for `consulAgentSDConfigs`, `dockerSDConfigs`, `dockerSwarmSDConfigs`, `marathonSDConfigs`, and `yandexCloudSDConfigs` service discovery types, bringing `VMScrapeConfig` to full parity with VictoriaMetrics [sd_configs](https://docs.victoriametrics.com/victoriametrics/sd_configs/). See [#2265](https://github.com/VictoriaMetrics/operator/issues/2265). * FEATURE: [vmoperator](https://docs.victoriametrics.com/operator/): add `victoriametrics_app=true` label to all metrics scraped by the operator. See [#2261](https://github.com/VictoriaMetrics/operator/issues/2261). * BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): skip reconciliation only for CRs with genuine spec parse errors; CRs whose `ParsingSpecError` is caused solely by unknown fields (e.g. after an operator downgrade) are now reconciled normally instead of being silently skipped. diff --git a/docs/api.md b/docs/api.md index d6365fdcd..9778f472c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -268,6 +268,7 @@ Appears in: [VLAgent](#vlagent) | useStrictSecurity#
_boolean_ | _(Optional)_
UseStrictSecurity enables strict security mode for component
it restricts disk writes access
uses non-root user out of the box
drops not needed security permissions | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | #### VLCluster @@ -506,6 +507,7 @@ Appears in: [VLSingle](#vlsingle) | useStrictSecurity#
_boolean_ | _(Optional)_
UseStrictSecurity enables strict security mode for component
it restricts disk writes access
uses non-root user out of the box
drops not needed security permissions | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | #### VLStorage @@ -781,6 +783,7 @@ Appears in: [VMAnomaly](#vmanomaly) | useStrictSecurity#
_boolean_ | _(Optional)_
UseStrictSecurity enables strict security mode for component
it restricts disk writes access
uses non-root user out of the box
drops not needed security permissions | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
VPA defines configuration for the VerticalPodAutoscaler. | | writer#
_[VMAnomalyWritersSpec](#vmanomalywritersspec)_ | _(Required)_
Metrics destination for VMAnomaly
See https://docs.victoriametrics.com/anomaly-detection/components/writer/ | #### VMAnomalyVMWriterMetricFormatSpec @@ -1046,6 +1049,7 @@ Appears in: [VTSingle](#vtsingle) | useStrictSecurity#
_boolean_ | _(Optional)_
UseStrictSecurity enables strict security mode for component
it restricts disk writes access
uses non-root user out of the box
drops not needed security permissions | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | #### VTStorage @@ -2018,7 +2022,7 @@ Appears in: [VLAgentSpec](#vlagentspec), [VLInsert](#vlinsert), [VLSelect](#vlse EmbeddedVPA embeds VerticalPodAutoscaler spec v1. https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler -Appears in: [VLInsert](#vlinsert), [VLSelect](#vlselect), [VLStorage](#vlstorage), [VMAuthSpec](#vmauthspec), [VMInsert](#vminsert), [VMSelect](#vmselect), [VMStorage](#vmstorage), [VTInsert](#vtinsert), [VTSelect](#vtselect), [VTStorage](#vtstorage) +Appears in: [VLAgentSpec](#vlagentspec), [VLInsert](#vlinsert), [VLSelect](#vlselect), [VLSingleSpec](#vlsinglespec), [VLStorage](#vlstorage), [VMAgentSpec](#vmagentspec), [VMAlertSpec](#vmalertspec), [VMAlertmanagerSpec](#vmalertmanagerspec), [VMAnomalySpec](#vmanomalyspec), [VMAuthSpec](#vmauthspec), [VMInsert](#vminsert), [VMSelect](#vmselect), [VMSingleSpec](#vmsinglespec), [VMStorage](#vmstorage), [VTInsert](#vtinsert), [VTSelect](#vtselect), [VTSingleSpec](#vtsinglespec), [VTStorage](#vtstorage) | Field | Description | | --- | --- | @@ -3785,6 +3789,7 @@ Appears in: [VMAgent](#vmagent) | vmAgentExternalLabelName#
_string_ | _(Optional)_
VMAgentExternalLabelName Name of vmAgent external label used to denote vmAgent instance
name. Defaults to the value of `prometheus`. External label will
_not_ be added when value is set to empty string (`""`).
Deprecated: since version v0.67.0 will be removed in v0.69.0 use externalLabelName instead
| | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | #### VMAlert @@ -3940,6 +3945,7 @@ Appears in: [VMAlert](#vmalert) | useVMConfigReloader#
_boolean_ | _(Optional)_
UseVMConfigReloader replaces prometheus-like config-reloader
with vm one. It uses secrets watch instead of file watch
which greatly increases speed of config updates
Removed since v0.67.0: this property is ignored and no longer needed | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | #### VMAlertmanager @@ -4090,6 +4096,7 @@ Appears in: [VMAlertmanager](#vmalertmanager) | useVMConfigReloader#
_boolean_ | _(Optional)_
UseVMConfigReloader replaces prometheus-like config-reloader
with vm one. It uses secrets watch instead of file watch
which greatly increases speed of config updates
Removed since v0.67.0: this property is ignored and no longer needed | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | | webConfig#
_[VMAlertmanagerWebConfig](#vmalertmanagerwebconfig)_ | _(Optional)_
WebConfig defines configuration for webserver
https://github.com/prometheus/alertmanager/blob/main/docs/https.md | #### VMAlertmanagerTracingConfig @@ -5001,6 +5008,7 @@ Appears in: [VMSingle](#vmsingle) | vmBackup#
_[VMBackup](#vmbackup)_ | _(Optional)_
VMBackup configuration for backup | | volumeMounts#
_[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | _(Optional)_
VolumeMounts allows configuration of additional VolumeMounts on the output Deployment/StatefulSet definition.
VolumeMounts specified will be appended to other VolumeMounts in the Application container | | volumes#
_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | _(Optional)_
Volumes allows configuration of additional volumes on the output Deployment/StatefulSet definition.
Volumes specified will be appended to other volumes that are generated. | +| vpa#
_[EmbeddedVPA](#embeddedvpa)_ | _(Optional)_
Configures vertical pod autoscaling. | #### VMStaticScrape diff --git a/internal/controller/operator/factory/build/vpa.go b/internal/controller/operator/factory/build/vpa.go index a0aee7ed0..7887706b2 100644 --- a/internal/controller/operator/factory/build/vpa.go +++ b/internal/controller/operator/factory/build/vpa.go @@ -1,6 +1,8 @@ package build import ( + "fmt" + autoscalingv1 "k8s.io/api/autoscaling/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" @@ -26,3 +28,14 @@ func VPA(opts builderOpts, targetRef autoscalingv1.CrossVersionObjectReference, }, } } + +// ShardVPA creates a VerticalPodAutoscaler targeting the workload for the given shard number +func ShardVPA(opts builderOpts, spec *vmv1beta1.EmbeddedVPA, workloadKind vmv1beta1.WorkloadKind, shardNum int32) *vpav1.VerticalPodAutoscaler { + name := fmt.Sprintf("%s-%d", opts.PrefixedName(), shardNum) + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: name, + Kind: string(workloadKind), + APIVersion: "apps/v1", + } + return VPA(opts, targetRef, spec) +} diff --git a/internal/controller/operator/factory/vlagent/vlagent.go b/internal/controller/operator/factory/vlagent/vlagent.go index b1e970fc6..8db009ffe 100644 --- a/internal/controller/operator/factory/vlagent/vlagent.go +++ b/internal/controller/operator/factory/vlagent/vlagent.go @@ -10,12 +10,14 @@ import ( "strings" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -132,6 +134,13 @@ func CreateOrUpdate(ctx context.Context, cr *vmv1.VLAgent, rclient client.Client return fmt.Errorf("cannot update pod disruption budget for vlagent: %w", err) } } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot create or update vpa for vlagent: %w", err) + } return createOrUpdateDeploy(ctx, rclient, cr, prevCR) } @@ -694,6 +703,29 @@ func buildRemoteWriteArgs(cr *vmv1.VLAgent) ([]string, error) { return args, nil } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1.VLAgent) error { + if cr.Spec.VPA == nil { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(cr.WorkloadKind()), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil { + prevTargetRef := autoscalingv1.CrossVersionObjectReference{ + Name: prevCR.PrefixedName(), + Kind: string(prevCR.WorkloadKind()), + APIVersion: "apps/v1", + } + prevVPA = build.VPA(prevCR, prevTargetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1.VLAgent) error { svcName := cr.PrefixedName() keepServices := sets.New(svcName) @@ -716,6 +748,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1.VLAgent if cr.Spec.PodDisruptionBudget == nil { objsToRemove = append(objsToRemove, &policyv1.PodDisruptionBudget{ObjectMeta: objMeta}) } + if config.MustGetBaseConfig().VPAAPIEnabled && cr.Spec.VPA == nil { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) if !cr.Spec.K8sCollector.Enabled && config.IsClusterWideAccessAllowed() { diff --git a/internal/controller/operator/factory/vlsingle/vlsingle.go b/internal/controller/operator/factory/vlsingle/vlsingle.go index 16ef130f9..6813f4283 100644 --- a/internal/controller/operator/factory/vlsingle/vlsingle.go +++ b/internal/controller/operator/factory/vlsingle/vlsingle.go @@ -7,11 +7,13 @@ import ( "sort" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -96,6 +98,13 @@ func CreateOrUpdate(ctx context.Context, rclient client.Client, cr *vmv1.VLSingl if err := createOrUpdateService(ctx, rclient, cr, prevCR); err != nil { return err } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot create or update vpa for vlsingle: %w", err) + } var prevDeploy *appsv1.Deployment if prevCR != nil { @@ -114,6 +123,24 @@ func CreateOrUpdate(ctx context.Context, rclient client.Client, cr *vmv1.VLSingl return reconcile.Deployment(ctx, rclient, newDeploy, prevDeploy, &owner, nil) } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1.VLSingle) error { + if cr.Spec.VPA == nil { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindDeployment), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil { + prevVPA = build.VPA(prevCR, targetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func newDeployment(r *vmv1.VLSingle) (*appsv1.Deployment, error) { podSpec, err := makePodSpec(r) if err != nil { @@ -351,6 +378,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1.VLSingl var objsToRemove []client.Object objMeta := metav1.ObjectMeta{Name: cr.PrefixedName(), Namespace: cr.Namespace} + if config.MustGetBaseConfig().VPAAPIEnabled && cr.Spec.VPA == nil { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) } diff --git a/internal/controller/operator/factory/vmagent/vmagent.go b/internal/controller/operator/factory/vmagent/vmagent.go index b9ce4c4e1..c8e846488 100644 --- a/internal/controller/operator/factory/vmagent/vmagent.go +++ b/internal/controller/operator/factory/vmagent/vmagent.go @@ -12,6 +12,7 @@ import ( "gopkg.in/yaml.v2" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" @@ -19,6 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -151,6 +153,13 @@ func CreateOrUpdate(ctx context.Context, cr *vmv1beta1.VMAgent, rclient client.C if err := createOrUpdateHPA(ctx, rclient, cr, prevCR); err != nil { return err } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return err + } ac := getAssetsCache(ctx, rclient, cr) extraCount, err := createOrUpdateScrapeConfig(ctx, rclient, cr, prevCR, nil, ac) @@ -188,6 +197,7 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v deploymentToKeep := sets.New[string]() stsToKeep := sets.New[string]() pdbToKeep := sets.New[string]() + vpaToKeep := sets.New[string]() shardCount := cr.GetShardCount() prevShardCount := prevCR.GetShardCount() @@ -207,6 +217,7 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v type returnValue struct { deploymentName string stsName string + vpaName string err error } rtCh := make(chan *returnValue) @@ -230,6 +241,19 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v } } + if cr.IsSharded() && cr.Spec.VPA != nil && !cr.Spec.DaemonSetMode { + newVPA := build.ShardVPA(cr, cr.Spec.VPA, cr.WorkloadKind(), shardNum) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.IsSharded() && prevCR.Spec.VPA != nil { + prevVPA = build.ShardVPA(prevCR, prevCR.Spec.VPA, prevCR.WorkloadKind(), shardNum) + } + if err := reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner); err != nil { + rv.err = fmt.Errorf("cannot reconcile VPA for vmagent shard(%d): %w", shardNum, err) + return + } + rv.vpaName = newVPA.Name + } + switch newAppTpl := newAppTpl.(type) { case *appsv1.Deployment: newApp := newAppTpl @@ -352,6 +376,15 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v pdbToKeep.Insert(rt.stsName) } } + if rt.vpaName != "" { + vpaToKeep.Insert(rt.vpaName) + } + } + + // For non-sharded mode the single VPA is managed by createOrUpdateVPA; include + // it in keepNames so RemoveOrphanedVPAs doesn't accidentally delete it. + if !cr.IsSharded() && cr.Spec.VPA != nil { + vpaToKeep.Insert(cr.PrefixedName()) } if err := finalize.RemoveOrphanedPDBs(ctx, rclient, cr, pdbToKeep, true); err != nil { @@ -363,6 +396,9 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v if err := finalize.RemoveOrphanedSTSs(ctx, rclient, cr, stsToKeep, true); err != nil { return err } + if err := finalize.RemoveOrphanedVPAs(ctx, rclient, cr, vpaToKeep, true); err != nil { + return err + } return nil } @@ -1242,6 +1278,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VM if cr.Spec.HPA == nil { objsToRemove = append(objsToRemove, &autoscalingv2.HorizontalPodAutoscaler{ObjectMeta: objMeta}) } + if config.MustGetBaseConfig().VPAAPIEnabled && (cr.Spec.VPA == nil || cr.Spec.DaemonSetMode || cr.IsSharded()) { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) rbacMeta := metav1.ObjectMeta{Name: cr.GetRBACName()} @@ -1433,3 +1472,26 @@ func createOrUpdateHPA(ctx context.Context, rclient client.Client, cr, prevCR *v owner := cr.AsOwner() return reconcile.HPA(ctx, rclient, newHPA, prevHPA, &owner) } + +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1beta1.VMAgent) error { + if cr.Spec.VPA == nil || cr.Spec.DaemonSetMode || cr.IsSharded() { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(cr.WorkloadKind()), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil && !prevCR.Spec.DaemonSetMode && !prevCR.IsSharded() { + prevTargetRef := autoscalingv1.CrossVersionObjectReference{ + Name: prevCR.PrefixedName(), + Kind: string(prevCR.WorkloadKind()), + APIVersion: "apps/v1", + } + prevVPA = build.VPA(prevCR, prevTargetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} diff --git a/internal/controller/operator/factory/vmalert/vmalert.go b/internal/controller/operator/factory/vmalert/vmalert.go index f51f1f8b6..1152c2294 100644 --- a/internal/controller/operator/factory/vmalert/vmalert.go +++ b/internal/controller/operator/factory/vmalert/vmalert.go @@ -9,11 +9,13 @@ import ( "strings" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -139,6 +141,13 @@ func CreateOrUpdate(ctx context.Context, cr *vmv1beta1.VMAlert, rclient client.C return fmt.Errorf("cannot update pod disruption budget for vmalert: %w", err) } } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot create or update vpa for vmalert: %w", err) + } var prevDeploy *appsv1.Deployment if prevCR != nil { @@ -769,6 +778,24 @@ func discoverNotifiersIfNeeded(ctx context.Context, rclient client.Client, cr *v return nil } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1beta1.VMAlert) error { + if cr.Spec.VPA == nil { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindDeployment), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil { + prevVPA = build.VPA(prevCR, targetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VMAlert) error { svcName := cr.PrefixedName() keepServices := sets.New(svcName) @@ -792,6 +819,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VM if cr.Spec.PodDisruptionBudget == nil { objsToRemove = append(objsToRemove, &policyv1.PodDisruptionBudget{ObjectMeta: objMeta}) } + if config.MustGetBaseConfig().VPAAPIEnabled && cr.Spec.VPA == nil { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) } diff --git a/internal/controller/operator/factory/vmalertmanager/alertmanager.go b/internal/controller/operator/factory/vmalertmanager/alertmanager.go index 93f4372d3..02a34ce43 100644 --- a/internal/controller/operator/factory/vmalertmanager/alertmanager.go +++ b/internal/controller/operator/factory/vmalertmanager/alertmanager.go @@ -5,14 +5,17 @@ import ( "fmt" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" vmv1beta1 "github.com/VictoriaMetrics/operator/api/operator/v1beta1" + "github.com/VictoriaMetrics/operator/internal/config" "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/build" "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/finalize" "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/reconcile" @@ -60,6 +63,13 @@ func CreateOrUpdateAlertManager(ctx context.Context, cr *vmv1beta1.VMAlertmanage return err } } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot create or update vpa for vmalertmanager: %w", err) + } var prevSts *appsv1.StatefulSet if prevCR != nil { var err error @@ -79,6 +89,24 @@ func CreateOrUpdateAlertManager(ctx context.Context, cr *vmv1beta1.VMAlertmanage return reconcile.StatefulSet(ctx, rclient, newSts, prevSts, &owner, &o) } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1beta1.VMAlertmanager) error { + if cr.Spec.VPA == nil { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindStatefulSet), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil { + prevVPA = build.VPA(prevCR, targetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VMAlertmanager) error { svcName := cr.PrefixedName() keepServices := sets.New(svcName) @@ -102,6 +130,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VM if cr.Spec.PodDisruptionBudget == nil { objsToRemove = append(objsToRemove, &policyv1.PodDisruptionBudget{ObjectMeta: objMeta}) } + if config.MustGetBaseConfig().VPAAPIEnabled && cr.Spec.VPA == nil { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) } diff --git a/internal/controller/operator/factory/vmanomaly/statefulset.go b/internal/controller/operator/factory/vmanomaly/statefulset.go index fe31571d6..cdcb5b071 100644 --- a/internal/controller/operator/factory/vmanomaly/statefulset.go +++ b/internal/controller/operator/factory/vmanomaly/statefulset.go @@ -7,16 +7,19 @@ import ( "sync" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" vmv1 "github.com/VictoriaMetrics/operator/api/operator/v1" vmv1beta1 "github.com/VictoriaMetrics/operator/api/operator/v1beta1" + "github.com/VictoriaMetrics/operator/internal/config" "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/build" "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/finalize" "github.com/VictoriaMetrics/operator/internal/controller/operator/factory/logger" @@ -78,6 +81,14 @@ func CreateOrUpdate(ctx context.Context, cr *vmv1.VMAnomaly, rclient client.Clie } } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot reconcile VPA for vmanomaly: %w", err) + } + ac := getAssetsCache(ctx, rclient, cr) if err := createOrUpdateConfig(ctx, rclient, cr, prevCR, nil, ac); err != nil { return err @@ -170,6 +181,29 @@ func newK8sApp(cr *vmv1.VMAnomaly, ac *build.AssetsCache) (*appsv1.StatefulSet, return app, nil } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1.VMAnomaly) error { + if cr.Spec.VPA == nil || cr.IsSharded() { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindStatefulSet), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil && !prevCR.IsSharded() { + prevTargetRef := autoscalingv1.CrossVersionObjectReference{ + Name: prevCR.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindStatefulSet), + APIVersion: "apps/v1", + } + prevVPA = build.VPA(prevCR, prevTargetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1.VMAnomaly) error { keepPodScrapes := sets.New[string]() if !ptr.Deref(cr.Spec.DisableSelfServiceScrape, false) { @@ -184,12 +218,16 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1.VMAnoma if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) } + if config.MustGetBaseConfig().VPAAPIEnabled && (cr.Spec.VPA == nil || cr.IsSharded()) { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } return finalize.SafeDeleteWithFinalizer(ctx, rclient, objsToRemove, cr) } func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *vmv1.VMAnomaly, newAppTpl, prevAppTpl *appsv1.StatefulSet) error { stsToKeep := sets.New[string]() pdbToKeep := sets.New[string]() + vpaToKeep := sets.New[string]() shardCount := cr.GetShardCount() prevShardCount := prevCR.GetShardCount() @@ -206,8 +244,9 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v var wg sync.WaitGroup type returnValue struct { - name string - err error + name string + vpaName string + err error } rtCh := make(chan *returnValue) shardCtx, cancel := context.WithCancel(ctx) @@ -229,6 +268,18 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v return } } + if cr.IsSharded() && cr.Spec.VPA != nil { + newVPA := build.ShardVPA(cr, cr.Spec.VPA, vmv1beta1.WorkloadKindStatefulSet, num) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.IsSharded() && prevCR.Spec.VPA != nil { + prevVPA = build.ShardVPA(prevCR, prevCR.Spec.VPA, vmv1beta1.WorkloadKindStatefulSet, num) + } + if err := reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner); err != nil { + rv.err = fmt.Errorf("cannot reconcile VPA for vmanomaly shard(%d): %w", num, err) + return + } + rv.vpaName = newVPA.Name + } newApp, err := getShard(cr, newAppTpl, num) if err != nil { rv.err = fmt.Errorf("failed to get new StatefulSet: %w", err) @@ -270,16 +321,27 @@ func createOrUpdateApp(ctx context.Context, rclient client.Client, cr, prevCR *v pdbToKeep.Insert(r.name) } } + if r.vpaName != "" { + vpaToKeep.Insert(r.vpaName) + } } if err := utilerrors.NewAggregate(errs); err != nil { return err } + // For non-sharded mode the single VPA is managed by createOrUpdateVPA; include + // it in keepNames so RemoveOrphanedVPAs doesn't accidentally delete it. + if !cr.IsSharded() && cr.Spec.VPA != nil { + vpaToKeep.Insert(cr.PrefixedName()) + } if err := finalize.RemoveOrphanedPDBs(ctx, rclient, cr, pdbToKeep, true); err != nil { return err } if err := finalize.RemoveOrphanedSTSs(ctx, rclient, cr, stsToKeep, true); err != nil { return err } + if err := finalize.RemoveOrphanedVPAs(ctx, rclient, cr, vpaToKeep, true); err != nil { + return err + } return nil } diff --git a/internal/controller/operator/factory/vmsingle/vmsingle.go b/internal/controller/operator/factory/vmsingle/vmsingle.go index 0d2d70781..32d8d10bc 100644 --- a/internal/controller/operator/factory/vmsingle/vmsingle.go +++ b/internal/controller/operator/factory/vmsingle/vmsingle.go @@ -8,12 +8,14 @@ import ( "gopkg.in/yaml.v2" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -110,6 +112,13 @@ func CreateOrUpdate(ctx context.Context, cr *vmv1beta1.VMSingle, rclient client. if err := createOrUpdateService(ctx, rclient, cr, prevCR); err != nil { return err } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot create or update vpa for vmsingle: %w", err) + } ac := getAssetsCache(ctx, rclient, cr) extraCount, err := createOrUpdateScrapeConfig(ctx, rclient, cr, prevCR, nil, ac) @@ -649,6 +658,24 @@ func createOrUpdateStreamAggrConfig(ctx context.Context, rclient client.Client, return err } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1beta1.VMSingle) error { + if cr.Spec.VPA == nil { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindDeployment), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil { + prevVPA = build.VPA(prevCR, targetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VMSingle) error { // TODO check storage for nil @@ -681,6 +708,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1beta1.VM objMeta := metav1.ObjectMeta{Name: cr.PrefixedName(), Namespace: cr.Namespace} var objsToRemove []client.Object + if config.MustGetBaseConfig().VPAAPIEnabled && cr.Spec.VPA == nil { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) rbacMeta := metav1.ObjectMeta{Name: cr.GetRBACName()} diff --git a/internal/controller/operator/factory/vtsingle/vtsingle.go b/internal/controller/operator/factory/vtsingle/vtsingle.go index 89488d8d0..86a107c3b 100644 --- a/internal/controller/operator/factory/vtsingle/vtsingle.go +++ b/internal/controller/operator/factory/vtsingle/vtsingle.go @@ -7,11 +7,13 @@ import ( "sort" appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" + vpav1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -96,6 +98,13 @@ func CreateOrUpdate(ctx context.Context, rclient client.Client, cr *vmv1.VTSingl if err := createOrUpdateService(ctx, rclient, cr, prevCR); err != nil { return err } + cfg := config.MustGetBaseConfig() + if cr.Spec.VPA != nil && !cfg.VPAAPIEnabled { + return fmt.Errorf("spec.vpa is set but VM_VPA_API_ENABLED=true env var was not provided") + } + if err := createOrUpdateVPA(ctx, rclient, cr, prevCR); err != nil { + return fmt.Errorf("cannot create or update vpa for vtsingle: %w", err) + } var prevDeploy *appsv1.Deployment if prevCR != nil { @@ -114,6 +123,24 @@ func CreateOrUpdate(ctx context.Context, rclient client.Client, cr *vmv1.VTSingl return reconcile.Deployment(ctx, rclient, newDeploy, prevDeploy, &owner, nil) } +func createOrUpdateVPA(ctx context.Context, rclient client.Client, cr, prevCR *vmv1.VTSingle) error { + if cr.Spec.VPA == nil { + return nil + } + targetRef := autoscalingv1.CrossVersionObjectReference{ + Name: cr.PrefixedName(), + Kind: string(vmv1beta1.WorkloadKindDeployment), + APIVersion: "apps/v1", + } + newVPA := build.VPA(cr, targetRef, cr.Spec.VPA) + var prevVPA *vpav1.VerticalPodAutoscaler + if prevCR != nil && prevCR.Spec.VPA != nil { + prevVPA = build.VPA(prevCR, targetRef, prevCR.Spec.VPA) + } + owner := cr.AsOwner() + return reconcile.VPA(ctx, rclient, newVPA, prevVPA, &owner) +} + func newDeployment(r *vmv1.VTSingle) (*appsv1.Deployment, error) { podSpec, err := makePodSpec(r) if err != nil { @@ -337,6 +364,9 @@ func deleteOrphaned(ctx context.Context, rclient client.Client, cr *vmv1.VTSingl objMeta := metav1.ObjectMeta{Name: cr.PrefixedName(), Namespace: cr.Namespace} var objsToRemove []client.Object + if config.MustGetBaseConfig().VPAAPIEnabled && cr.Spec.VPA == nil { + objsToRemove = append(objsToRemove, &vpav1.VerticalPodAutoscaler{ObjectMeta: objMeta}) + } if !cr.IsOwnsServiceAccount() { objsToRemove = append(objsToRemove, &corev1.ServiceAccount{ObjectMeta: objMeta}) }