Skip to content

Commit

Permalink
feat(spd): support ihpa
Browse files Browse the repository at this point in the history
  • Loading branch information
kapybar4 committed Jul 4, 2024
1 parent 7e559fd commit 3e5b09f
Show file tree
Hide file tree
Showing 23 changed files with 2,530 additions and 39 deletions.
57 changes: 57 additions & 0 deletions cmd/katalyst-controller/app/controller/ihpa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2022 The Katalyst Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package controller

import (
"context"
"fmt"

"k8s.io/klog/v2"

katalyst "github.com/kubewharf/katalyst-core/cmd/base"
"github.com/kubewharf/katalyst-core/pkg/config"
"github.com/kubewharf/katalyst-core/pkg/controller/ihpa"
)

const (
IHPAControllerName = "ihpa"
)

func StartIHPAController(ctx context.Context, controlCtx *katalyst.GenericContext,
conf *config.Configuration, extraConf interface{}, _ string,
) (bool, error) {
if controlCtx == nil || conf == nil {
err := fmt.Errorf("controlCtx and controllerConf can't be nil")
klog.Error(err.Error())
return false, err
}

ihpaController, err := ihpa.NewIHPAController(ctx,
controlCtx,
conf.GenericConfiguration,
conf.GenericControllerConfiguration,
conf.ControllersConfiguration.IHPAConfig,
conf.QoSConfiguration,
extraConf)
if err != nil {
klog.Errorf("failed to new ihpa controller")
return false, err
}

go ihpaController.Run()
return true, nil
}
1 change: 1 addition & 0 deletions cmd/katalyst-controller/app/enablecontrollers.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ var ControllersDisabledByDefault = sets.NewString()
var controllerInitializers sync.Map

func init() {
controllerInitializers.Store(controller.IHPAControllerName, ControllerStarter{Starter: controller.StartIHPAController})
controllerInitializers.Store(controller.VPAControllerName, ControllerStarter{Starter: controller.StartVPAController})
controllerInitializers.Store(controller.KCCControllerName, ControllerStarter{Starter: controller.StartKCCController})
controllerInitializers.Store(controller.SPDControllerName, ControllerStarter{Starter: controller.StartSPDController})
Expand Down
4 changes: 4 additions & 0 deletions cmd/katalyst-controller/app/options/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
)

type ControllersOptions struct {
*IHPAOptions
*VPAOptions
*KCCOptions
*SPDOptions
Expand All @@ -35,6 +36,7 @@ type ControllersOptions struct {

func NewControllersOptions() *ControllersOptions {
return &ControllersOptions{
IHPAOptions: NewIHPAOptions(),
VPAOptions: NewVPAOptions(),
KCCOptions: NewKCCOptions(),
SPDOptions: NewSPDOptions(),
Expand All @@ -46,6 +48,7 @@ func NewControllersOptions() *ControllersOptions {
}

func (o *ControllersOptions) AddFlags(fss *cliflag.NamedFlagSets) {
o.IHPAOptions.AddFlags(fss)
o.VPAOptions.AddFlags(fss)
o.KCCOptions.AddFlags(fss)
o.SPDOptions.AddFlags(fss)
Expand All @@ -59,6 +62,7 @@ func (o *ControllersOptions) AddFlags(fss *cliflag.NamedFlagSets) {
func (o *ControllersOptions) ApplyTo(c *controllerconfig.ControllersConfiguration) error {
var errList []error

errList = append(errList, o.IHPAOptions.ApplyTo(c.IHPAConfig))
errList = append(errList, o.VPAOptions.ApplyTo(c.VPAConfig))
errList = append(errList, o.KCCOptions.ApplyTo(c.KCCConfig))
errList = append(errList, o.SPDOptions.ApplyTo(c.SPDConfig))
Expand Down
55 changes: 55 additions & 0 deletions cmd/katalyst-controller/app/options/ihpa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2022 The Katalyst Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package options

import (
"fmt"
"time"

cliflag "k8s.io/component-base/cli/flag"

"github.com/kubewharf/katalyst-core/pkg/config/controller"
)

const (
defaultIhpaSyncWorkers = 1
defaultIhpaResyncPeriod = 30 * time.Second
)

type IHPAOptions struct {
SyncWorkers int
ResyncPeriod time.Duration
}

func NewIHPAOptions() *IHPAOptions {
return &IHPAOptions{}
}

func (o *IHPAOptions) AddFlags(fss *cliflag.NamedFlagSets) {
fs := fss.FlagSet("ihpa")

fs.IntVar(&o.SyncWorkers, "ihpa-sync-workers", defaultIhpaSyncWorkers, fmt.Sprintf(""+
"num of goroutines to sync ihpas"))
fs.DurationVar(&o.ResyncPeriod, "ihpa-resync-period", defaultIhpaResyncPeriod, fmt.Sprintf(""+
"Period for ihpa controller to resync"))
}

func (o *IHPAOptions) ApplyTo(c *controller.IHPAConfig) error {
c.SyncWorkers = o.SyncWorkers
c.ResyncPeriod = o.ResyncPeriod
return nil
}
3 changes: 3 additions & 0 deletions cmd/katalyst-metric/app/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/kubewharf/katalyst-core/pkg/consts"
"github.com/kubewharf/katalyst-core/pkg/custom-metric/mock"
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store"
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/custom"
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/local"
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/remote"
"github.com/kubewharf/katalyst-core/pkg/metrics"
Expand Down Expand Up @@ -157,6 +158,8 @@ func initStore(ctx context.Context, baseCtx *katalystbase.GenericContext, conf *
return local.NewLocalMemoryMetricStore(ctx, baseCtx, conf.GenericMetricConfiguration, conf.StoreConfiguration)
case remote.MetricStoreNameRemoteMemory:
return remote.NewRemoteMemoryMetricStore(ctx, baseCtx, conf.GenericMetricConfiguration, conf.StoreConfiguration)
case custom.SPDCustomMetricStore:
return custom.NewSPDMetricStore(ctx, baseCtx, conf.GenericMetricConfiguration, conf.StoreConfiguration)
}

return nil, fmt.Errorf("unsupported store name: %v", conf.CustomMetricConfiguration.StoreConfiguration.StoreName)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/prometheus/client_golang v1.14.0
github.com/prometheus/client_model v0.3.0
github.com/prometheus/common v0.37.0
github.com/robfig/cron/v3 v3.0.1
github.com/samber/lo v1.39.0
github.com/slok/kubewebhook v0.11.0
github.com/spf13/cobra v1.6.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:r
github.com/quobyte/api v0.1.8/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
Expand Down
165 changes: 165 additions & 0 deletions pkg/client/control/ihpa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
Copyright 2022 The Katalyst Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package control

import (
"context"
"encoding/json"
"fmt"

autoscaling "k8s.io/api/autoscaling/v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes"

apis "github.com/kubewharf/katalyst-api/pkg/apis/autoscaling/v1alpha2"
clientset "github.com/kubewharf/katalyst-api/pkg/client/clientset/versioned"
"github.com/kubewharf/katalyst-core/pkg/util/general"
)

type HPAManager interface {
Create(ctx context.Context, new *autoscaling.HorizontalPodAutoscaler, opts metav1.CreateOptions) (*autoscaling.HorizontalPodAutoscaler, error)
Patch(ctx context.Context, old, new *autoscaling.HorizontalPodAutoscaler, opts metav1.PatchOptions) (*autoscaling.HorizontalPodAutoscaler, error)
}

type HPAManageImpl struct {
client kubernetes.Interface
}

func NewHPAManager(client kubernetes.Interface) HPAManager {
return &HPAManageImpl{
client: client,
}
}

func (h *HPAManageImpl) Create(ctx context.Context,
new *autoscaling.HorizontalPodAutoscaler, opts metav1.CreateOptions,
) (*autoscaling.HorizontalPodAutoscaler, error) {
if new == nil {
return nil, fmt.Errorf("can't create a nil HPA")
}
return h.client.AutoscalingV2().HorizontalPodAutoscalers(new.Namespace).Create(ctx, new, opts)
}

func (h *HPAManageImpl) Patch(ctx context.Context, old,
new *autoscaling.HorizontalPodAutoscaler, opts metav1.PatchOptions,
) (*autoscaling.HorizontalPodAutoscaler, error) {
if old == nil || new == nil {
return nil, fmt.Errorf("can't patch a nil HPA")
}

oldData, err := json.Marshal(old)
if err != nil {
return nil, err
}

newData, err := json.Marshal(new)
if err != nil {
return nil, err
}

patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &autoscaling.HorizontalPodAutoscaler{})
if err != nil {
return nil, fmt.Errorf("failed to create merge patch for hpa %q/%q: %v", old.Namespace, old.Name, err)
} else if general.JsonPathEmpty(patchBytes) {
return nil, nil
}

return h.client.AutoscalingV2().HorizontalPodAutoscalers(old.Namespace).Patch(ctx, old.Name, types.StrategicMergePatchType, patchBytes, opts)
}

type IHPAUpdater interface {
Update(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler,
opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error)
UpdateStatus(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler,
opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error)
}

type IHPAUpdateImpl struct {
client clientset.Interface
}

func NewIHPAUpdater(client clientset.Interface) IHPAUpdater {
return &IHPAUpdateImpl{
client: client,
}
}

func (i *IHPAUpdateImpl) Update(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler, opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error) {
if ihpa == nil {
return nil, fmt.Errorf("can't update a nil ihpa")
}

return i.client.AutoscalingV1alpha2().IntelligentHorizontalPodAutoscalers(ihpa.Namespace).Update(
ctx, ihpa, opts)
}

func (i *IHPAUpdateImpl) UpdateStatus(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler, opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error) {
if ihpa == nil {
return nil, fmt.Errorf("can't update a nil ihpa's status")
}

return i.client.AutoscalingV1alpha2().IntelligentHorizontalPodAutoscalers(ihpa.Namespace).UpdateStatus(
ctx, ihpa, opts)
}

type VirtualWorkloadManager interface {
Create(ctx context.Context, vw *apis.VirtualWorkload,
opts metav1.CreateOptions) (*apis.VirtualWorkload, error)
Update(ctx context.Context, vw *apis.VirtualWorkload,
opts metav1.UpdateOptions) (*apis.VirtualWorkload, error)
UpdateStatus(ctx context.Context, vw *apis.VirtualWorkload,
opts metav1.UpdateOptions) (*apis.VirtualWorkload, error)
}

type vmManageImpl struct {
client clientset.Interface
}

func NewVirtualWorkloadManager(client clientset.Interface) VirtualWorkloadManager {
return &vmManageImpl{
client: client,
}
}

func (i *vmManageImpl) Create(ctx context.Context, vw *apis.VirtualWorkload, opts metav1.CreateOptions) (*apis.VirtualWorkload, error) {
if vw == nil {
return nil, fmt.Errorf("can't create a nil vw")
}

return i.client.AutoscalingV1alpha2().VirtualWorkloads(vw.Namespace).Create(
ctx, vw, opts)
}

func (i *vmManageImpl) Update(ctx context.Context, vw *apis.VirtualWorkload, opts metav1.UpdateOptions) (*apis.VirtualWorkload, error) {
if vw == nil {
return nil, fmt.Errorf("can't update a nil vw")
}

return i.client.AutoscalingV1alpha2().VirtualWorkloads(vw.Namespace).Update(
ctx, vw, opts)
}

func (i *vmManageImpl) UpdateStatus(ctx context.Context, vw *apis.VirtualWorkload, opts metav1.UpdateOptions) (*apis.VirtualWorkload, error) {
if vw == nil {
return nil, fmt.Errorf("can't update a nil vw's status")
}

return i.client.AutoscalingV1alpha2().VirtualWorkloads(vw.Namespace).UpdateStatus(
ctx, vw, opts)
}
Loading

0 comments on commit 3e5b09f

Please sign in to comment.