Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HorizontalPortrait: Introduce external generator mechanism #82

Merged
merged 2 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 38 additions & 30 deletions apis/autoscaling/v1alpha1/horizontalportrait_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
k8sautoscalingv2 "k8s.io/api/autoscaling/v2"
batchv1 "k8s.io/api/batch/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

//+kubebuilder:object:root=true
Expand All @@ -46,9 +47,16 @@ type HorizontalPortraitSpec struct {

// PortraitSpec defines general specs of portrait.
type PortraitSpec struct {
// PortraitType is the type of portrait. Different type has different portrait generating logic.
// PortraitType is the type of portrait.
// Different type has different semantics with different portrait generating logic.
PortraitType PortraitType `json:"portraitType"`

// ExternalGeneratorName is the identifier of external controller which shall generate this portrait.
// External controllers should use this field to filter portraits to generate.
// Kapacity's built-in portrait generators would ignore portraits with this field set.
// +optional
ExternalGeneratorName string `json:"externalGeneratorName,omitempty"`

// Metrics contains the specifications for which to use to generate the portrait.
// +optional
Metrics []MetricSpec `json:"metrics,omitempty"`
Expand Down Expand Up @@ -121,10 +129,10 @@ type PortraitAlgorithm struct {
KubeHPA *KubeHPAPortraitAlgorithm `json:"kubeHPA,omitempty"`

// Config is the general configuration data for arbitrary algorithm those
// used by external user-defined portraits.
// TODO: consider if we can make it structural
// used by external portrait generators.
// +optional
Config map[string]string `json:"config,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
Config *runtime.RawExtension `json:"config,omitempty"`
}

type PortraitAlgorithmType string
Expand All @@ -137,32 +145,6 @@ const (
KubeHPAPortraitAlgorithmType PortraitAlgorithmType = "KubeHPA"
)

// KubeHPAPortraitAlgorithm defines parameters of KubeHPA algorithm.
type KubeHPAPortraitAlgorithm struct {
// SyncPeriod is the period for syncing the portrait.
// +optional
// +kubebuilder:default="15s"
SyncPeriod metav1.Duration `json:"syncPeriod"`

// Tolerance is the tolerance for when resource usage suggests upscaling/downscaling.
// Should be a string formatted float64 number.
// +optional
// +kubebuilder:default="0.1"
Tolerance string `json:"tolerance"`

// CPUInitializationPeriod is the period after pod start when CPU samples might be skipped.
// +optional
// +kubebuilder:default="5m"
CPUInitializationPeriod metav1.Duration `json:"cpuInitializationPeriod"`

// InitialReadinessDelay is period after pod start during which readiness changes
// are treated as readiness being set for the first time. The only effect of this is that
// HPA will disregard CPU samples from unready pods that had last readiness change during that period.
// +optional
// +kubebuilder:default="30s"
InitialReadinessDelay metav1.Duration `json:"initialReadinessDelay"`
}

// ExternalJobPortraitAlgorithm defines configurations of ExternalJob algorithm.
type ExternalJobPortraitAlgorithm struct {
// Job is the external job that runs the algorithm.
Expand Down Expand Up @@ -226,6 +208,32 @@ const (
// ConfigMapPortraitAlgorithmResultSource defines configurations of ConfigMap result source.
type ConfigMapPortraitAlgorithmResultSource struct{}

// KubeHPAPortraitAlgorithm defines parameters of KubeHPA algorithm.
type KubeHPAPortraitAlgorithm struct {
// SyncPeriod is the period for syncing the portrait.
// +optional
// +kubebuilder:default="15s"
SyncPeriod metav1.Duration `json:"syncPeriod"`

// Tolerance is the tolerance for when resource usage suggests upscaling/downscaling.
// Should be a string formatted float64 number.
// +optional
// +kubebuilder:default="0.1"
Tolerance string `json:"tolerance"`

// CPUInitializationPeriod is the period after pod start when CPU samples might be skipped.
// +optional
// +kubebuilder:default="5m"
CPUInitializationPeriod metav1.Duration `json:"cpuInitializationPeriod"`

// InitialReadinessDelay is period after pod start during which readiness changes
// are treated as readiness being set for the first time. The only effect of this is that
// HPA will disregard CPU samples from unready pods that had last readiness change during that period.
// +optional
// +kubebuilder:default="30s"
InitialReadinessDelay metav1.Duration `json:"initialReadinessDelay"`
}

// HorizontalPortraitStatus defines the observed state of HorizontalPortrait.
type HorizontalPortraitStatus struct {
// PortraitData is the data of generated portrait.
Expand Down
8 changes: 3 additions & 5 deletions apis/autoscaling/v1alpha1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,10 @@ spec:
the portrait.
properties:
config:
additionalProperties:
type: string
description: 'Config is the general configuration data for arbitrary
algorithm those used by external user-defined portraits. TODO:
consider if we can make it structural'
description: Config is the general configuration data for arbitrary
algorithm those used by external portrait generators.
type: object
x-kubernetes-preserve-unknown-fields: true
externalJob:
description: ExternalJob is the configuration for ExternalJob
algorithm.
Expand Down Expand Up @@ -15937,6 +15935,12 @@ spec:
required:
- type
type: object
externalGeneratorName:
description: ExternalGeneratorName is the identifier of external controller
which shall generate this portrait. External controllers should
use this field to filter portraits to generate. Kapacity's built-in
portrait generators would ignore portraits with this field set.
type: string
metrics:
description: Metrics contains the specifications for which to use
to generate the portrait.
Expand Down Expand Up @@ -16423,7 +16427,7 @@ spec:
type: array
portraitType:
description: PortraitType is the type of portrait. Different type
has different portrait generating logic.
has different semantics with different portrait generating logic.
type: string
scaleTargetRef:
description: ScaleTargetRef points to the target resource to scale.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,11 @@ spec:
to generate the portrait.
properties:
config:
additionalProperties:
type: string
description: 'Config is the general configuration data
for arbitrary algorithm those used by external user-defined
portraits. TODO: consider if we can make it structural'
description: Config is the general configuration data
for arbitrary algorithm those used by external portrait
generators.
type: object
x-kubernetes-preserve-unknown-fields: true
externalJob:
description: ExternalJob is the configuration for ExternalJob
algorithm.
Expand Down Expand Up @@ -25277,6 +25276,13 @@ spec:
required:
- type
type: object
externalGeneratorName:
description: ExternalGeneratorName is the identifier of
external controller which shall generate this portrait.
External controllers should use this field to filter portraits
to generate. Kapacity's built-in portrait generators would
ignore portraits with this field set.
type: string
metrics:
description: Metrics contains the specifications for which
to use to generate the portrait.
Expand Down Expand Up @@ -25800,7 +25806,8 @@ spec:
type: array
portraitType:
description: PortraitType is the type of portrait. Different
type has different portrait generating logic.
type has different semantics with different portrait generating
logic.
type: string
required:
- algorithm
Expand Down
16 changes: 6 additions & 10 deletions controllers/autoscaling/horizontalportrait_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,11 @@ func (r *HorizontalPortraitReconciler) Reconcile(ctx context.Context, req ctrl.R

portraitGenerator, ok := r.PortraitGenerators[hp.Spec.PortraitType]
if !ok {
// this should not happen because we have watch predicates
l.Info("unknown portrait type, ignore", "portraitType", hp.Spec.PortraitType)
err := fmt.Errorf("unknown portrait type %q", hp.Spec.PortraitType)
l.Error(err, "failed to get portrait generator")
r.errorOut(ctx, hp, hpStatusOriginal, autoscalingv1alpha1.PortraitGenerated, metav1.ConditionFalse,
"FailedGetPortraitGenerator", fmt.Sprintf("failed to get portrait generator: %v", err))
// do not requeue because it won't help
return ctrl.Result{}, nil
}

Expand Down Expand Up @@ -190,14 +193,7 @@ func (r *HorizontalPortraitReconciler) SetupWithManager(mgr ctrl.Manager) error
if !ok {
return false
}
switch hp.Spec.PortraitType {
case autoscalingv1alpha1.ReactivePortraitType:
case autoscalingv1alpha1.PredictivePortraitType:
case autoscalingv1alpha1.BurstPortraitType:
default:
return false
}
return true
return hp.Spec.ExternalGeneratorName == ""
}),
)).
Watches(&source.Channel{Source: r.EventTrigger}, &handler.EnqueueRequestForObject{}).
Expand Down