Skip to content

Commit 62045cf

Browse files
authored
Merge pull request #630 from kapybar4/feat-ihpa
feat(spd): support ihpa
2 parents aaa141b + bb6fbbd commit 62045cf

File tree

28 files changed

+2688
-40
lines changed

28 files changed

+2688
-40
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2022 The Katalyst Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package controller
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
"k8s.io/klog/v2"
24+
25+
katalyst "github.com/kubewharf/katalyst-core/cmd/base"
26+
"github.com/kubewharf/katalyst-core/pkg/config"
27+
"github.com/kubewharf/katalyst-core/pkg/controller/ihpa"
28+
)
29+
30+
const (
31+
IHPAControllerName = "ihpa"
32+
)
33+
34+
func StartIHPAController(ctx context.Context, controlCtx *katalyst.GenericContext,
35+
conf *config.Configuration, extraConf interface{}, _ string,
36+
) (bool, error) {
37+
if controlCtx == nil || conf == nil {
38+
err := fmt.Errorf("controlCtx and controllerConf can't be nil")
39+
klog.Error(err.Error())
40+
return false, err
41+
}
42+
43+
ihpaController, err := ihpa.NewIHPAController(ctx,
44+
controlCtx,
45+
conf.GenericConfiguration,
46+
conf.GenericControllerConfiguration,
47+
conf.ControllersConfiguration.IHPAConfig,
48+
conf.QoSConfiguration,
49+
extraConf)
50+
if err != nil {
51+
klog.Errorf("failed to new ihpa controller")
52+
return false, err
53+
}
54+
55+
go ihpaController.Run()
56+
return true, nil
57+
}

cmd/katalyst-controller/app/enablecontrollers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ var ControllersDisabledByDefault = sets.NewString()
4747
var controllerInitializers sync.Map
4848

4949
func init() {
50+
controllerInitializers.Store(controller.IHPAControllerName, ControllerStarter{Starter: controller.StartIHPAController})
5051
controllerInitializers.Store(controller.VPAControllerName, ControllerStarter{Starter: controller.StartVPAController})
5152
controllerInitializers.Store(controller.KCCControllerName, ControllerStarter{Starter: controller.StartKCCController})
5253
controllerInitializers.Store(controller.SPDControllerName, ControllerStarter{Starter: controller.StartSPDController})

cmd/katalyst-controller/app/options/controller.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
)
2525

2626
type ControllersOptions struct {
27+
*IHPAOptions
2728
*VPAOptions
2829
*KCCOptions
2930
*SPDOptions
@@ -35,6 +36,7 @@ type ControllersOptions struct {
3536

3637
func NewControllersOptions() *ControllersOptions {
3738
return &ControllersOptions{
39+
IHPAOptions: NewIHPAOptions(),
3840
VPAOptions: NewVPAOptions(),
3941
KCCOptions: NewKCCOptions(),
4042
SPDOptions: NewSPDOptions(),
@@ -46,6 +48,7 @@ func NewControllersOptions() *ControllersOptions {
4648
}
4749

4850
func (o *ControllersOptions) AddFlags(fss *cliflag.NamedFlagSets) {
51+
o.IHPAOptions.AddFlags(fss)
4952
o.VPAOptions.AddFlags(fss)
5053
o.KCCOptions.AddFlags(fss)
5154
o.SPDOptions.AddFlags(fss)
@@ -59,6 +62,7 @@ func (o *ControllersOptions) AddFlags(fss *cliflag.NamedFlagSets) {
5962
func (o *ControllersOptions) ApplyTo(c *controllerconfig.ControllersConfiguration) error {
6063
var errList []error
6164

65+
errList = append(errList, o.IHPAOptions.ApplyTo(c.IHPAConfig))
6266
errList = append(errList, o.VPAOptions.ApplyTo(c.VPAConfig))
6367
errList = append(errList, o.KCCOptions.ApplyTo(c.KCCConfig))
6468
errList = append(errList, o.SPDOptions.ApplyTo(c.SPDConfig))
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
Copyright 2022 The Katalyst Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package options
18+
19+
import (
20+
"fmt"
21+
"time"
22+
23+
cliflag "k8s.io/component-base/cli/flag"
24+
25+
"github.com/kubewharf/katalyst-core/pkg/config/controller"
26+
)
27+
28+
const (
29+
defaultIhpaSyncWorkers = 1
30+
defaultIhpaResyncPeriod = 30 * time.Second
31+
)
32+
33+
type IHPAOptions struct {
34+
SyncWorkers int
35+
ResyncPeriod time.Duration
36+
}
37+
38+
func NewIHPAOptions() *IHPAOptions {
39+
return &IHPAOptions{}
40+
}
41+
42+
func (o *IHPAOptions) AddFlags(fss *cliflag.NamedFlagSets) {
43+
fs := fss.FlagSet("ihpa")
44+
45+
fs.IntVar(&o.SyncWorkers, "ihpa-sync-workers", defaultIhpaSyncWorkers, fmt.Sprintf(""+
46+
"num of goroutines to sync ihpas"))
47+
fs.DurationVar(&o.ResyncPeriod, "ihpa-resync-period", defaultIhpaResyncPeriod, fmt.Sprintf(""+
48+
"Period for ihpa controller to resync"))
49+
}
50+
51+
func (o *IHPAOptions) ApplyTo(c *controller.IHPAConfig) error {
52+
c.SyncWorkers = o.SyncWorkers
53+
c.ResyncPeriod = o.ResyncPeriod
54+
return nil
55+
}

cmd/katalyst-metric/app/metric.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/kubewharf/katalyst-core/pkg/consts"
3434
"github.com/kubewharf/katalyst-core/pkg/custom-metric/mock"
3535
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store"
36+
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/custom"
3637
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/local"
3738
"github.com/kubewharf/katalyst-core/pkg/custom-metric/store/remote"
3839
"github.com/kubewharf/katalyst-core/pkg/metrics"
@@ -157,6 +158,8 @@ func initStore(ctx context.Context, baseCtx *katalystbase.GenericContext, conf *
157158
return local.NewLocalMemoryMetricStore(ctx, baseCtx, conf.GenericMetricConfiguration, conf.StoreConfiguration)
158159
case remote.MetricStoreNameRemoteMemory:
159160
return remote.NewRemoteMemoryMetricStore(ctx, baseCtx, conf.GenericMetricConfiguration, conf.StoreConfiguration)
161+
case custom.SPDCustomMetricStore:
162+
return custom.NewSPDMetricStore(ctx, baseCtx, conf.GenericMetricConfiguration, conf.StoreConfiguration)
160163
}
161164

162165
return nil, fmt.Errorf("unsupported store name: %v", conf.CustomMetricConfiguration.StoreConfiguration.StoreName)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ require (
2626
github.com/prometheus/client_golang v1.14.0
2727
github.com/prometheus/client_model v0.3.0
2828
github.com/prometheus/common v0.37.0
29+
github.com/robfig/cron/v3 v3.0.1
2930
github.com/samber/lo v1.39.0
3031
github.com/slok/kubewebhook v0.11.0
3132
github.com/spf13/cobra v1.6.0

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:r
785785
github.com/quobyte/api v0.1.8/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
786786
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
787787
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
788+
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
788789
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
789790
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
790791
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=

pkg/client/control/ihpa.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
Copyright 2022 The Katalyst Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package control
18+
19+
import (
20+
"context"
21+
"encoding/json"
22+
"fmt"
23+
24+
autoscaling "k8s.io/api/autoscaling/v2"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/types"
27+
"k8s.io/apimachinery/pkg/util/strategicpatch"
28+
"k8s.io/client-go/kubernetes"
29+
30+
apis "github.com/kubewharf/katalyst-api/pkg/apis/autoscaling/v1alpha2"
31+
clientset "github.com/kubewharf/katalyst-api/pkg/client/clientset/versioned"
32+
"github.com/kubewharf/katalyst-core/pkg/util/general"
33+
)
34+
35+
type HPAManager interface {
36+
Create(ctx context.Context, new *autoscaling.HorizontalPodAutoscaler, opts metav1.CreateOptions) (*autoscaling.HorizontalPodAutoscaler, error)
37+
Patch(ctx context.Context, old, new *autoscaling.HorizontalPodAutoscaler, opts metav1.PatchOptions) (*autoscaling.HorizontalPodAutoscaler, error)
38+
}
39+
40+
type HPAManageImpl struct {
41+
client kubernetes.Interface
42+
}
43+
44+
func NewHPAManager(client kubernetes.Interface) HPAManager {
45+
return &HPAManageImpl{
46+
client: client,
47+
}
48+
}
49+
50+
func (h *HPAManageImpl) Create(ctx context.Context,
51+
new *autoscaling.HorizontalPodAutoscaler, opts metav1.CreateOptions,
52+
) (*autoscaling.HorizontalPodAutoscaler, error) {
53+
if new == nil {
54+
return nil, fmt.Errorf("can't create a nil HPA")
55+
}
56+
return h.client.AutoscalingV2().HorizontalPodAutoscalers(new.Namespace).Create(ctx, new, opts)
57+
}
58+
59+
func (h *HPAManageImpl) Patch(ctx context.Context, old,
60+
new *autoscaling.HorizontalPodAutoscaler, opts metav1.PatchOptions,
61+
) (*autoscaling.HorizontalPodAutoscaler, error) {
62+
if old == nil || new == nil {
63+
return nil, fmt.Errorf("can't patch a nil HPA")
64+
}
65+
66+
oldData, err := json.Marshal(old)
67+
if err != nil {
68+
return nil, err
69+
}
70+
71+
newData, err := json.Marshal(new)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &autoscaling.HorizontalPodAutoscaler{})
77+
if err != nil {
78+
return nil, fmt.Errorf("failed to create merge patch for hpa %q/%q: %v", old.Namespace, old.Name, err)
79+
} else if general.JsonPathEmpty(patchBytes) {
80+
return nil, nil
81+
}
82+
83+
return h.client.AutoscalingV2().HorizontalPodAutoscalers(old.Namespace).Patch(ctx, old.Name, types.StrategicMergePatchType, patchBytes, opts)
84+
}
85+
86+
type IHPAUpdater interface {
87+
Update(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler,
88+
opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error)
89+
UpdateStatus(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler,
90+
opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error)
91+
}
92+
93+
type IHPAUpdateImpl struct {
94+
client clientset.Interface
95+
}
96+
97+
func NewIHPAUpdater(client clientset.Interface) IHPAUpdater {
98+
return &IHPAUpdateImpl{
99+
client: client,
100+
}
101+
}
102+
103+
func (i *IHPAUpdateImpl) Update(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler, opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error) {
104+
if ihpa == nil {
105+
return nil, fmt.Errorf("can't update a nil ihpa")
106+
}
107+
108+
return i.client.AutoscalingV1alpha2().IntelligentHorizontalPodAutoscalers(ihpa.Namespace).Update(
109+
ctx, ihpa, opts)
110+
}
111+
112+
func (i *IHPAUpdateImpl) UpdateStatus(ctx context.Context, ihpa *apis.IntelligentHorizontalPodAutoscaler, opts metav1.UpdateOptions) (*apis.IntelligentHorizontalPodAutoscaler, error) {
113+
if ihpa == nil {
114+
return nil, fmt.Errorf("can't update a nil ihpa's status")
115+
}
116+
117+
return i.client.AutoscalingV1alpha2().IntelligentHorizontalPodAutoscalers(ihpa.Namespace).UpdateStatus(
118+
ctx, ihpa, opts)
119+
}
120+
121+
type VirtualWorkloadManager interface {
122+
Create(ctx context.Context, vw *apis.VirtualWorkload,
123+
opts metav1.CreateOptions) (*apis.VirtualWorkload, error)
124+
Update(ctx context.Context, vw *apis.VirtualWorkload,
125+
opts metav1.UpdateOptions) (*apis.VirtualWorkload, error)
126+
UpdateStatus(ctx context.Context, vw *apis.VirtualWorkload,
127+
opts metav1.UpdateOptions) (*apis.VirtualWorkload, error)
128+
}
129+
130+
type vmManageImpl struct {
131+
client clientset.Interface
132+
}
133+
134+
func NewVirtualWorkloadManager(client clientset.Interface) VirtualWorkloadManager {
135+
return &vmManageImpl{
136+
client: client,
137+
}
138+
}
139+
140+
func (i *vmManageImpl) Create(ctx context.Context, vw *apis.VirtualWorkload, opts metav1.CreateOptions) (*apis.VirtualWorkload, error) {
141+
if vw == nil {
142+
return nil, fmt.Errorf("can't create a nil vw")
143+
}
144+
145+
return i.client.AutoscalingV1alpha2().VirtualWorkloads(vw.Namespace).Create(
146+
ctx, vw, opts)
147+
}
148+
149+
func (i *vmManageImpl) Update(ctx context.Context, vw *apis.VirtualWorkload, opts metav1.UpdateOptions) (*apis.VirtualWorkload, error) {
150+
if vw == nil {
151+
return nil, fmt.Errorf("can't update a nil vw")
152+
}
153+
154+
return i.client.AutoscalingV1alpha2().VirtualWorkloads(vw.Namespace).Update(
155+
ctx, vw, opts)
156+
}
157+
158+
func (i *vmManageImpl) UpdateStatus(ctx context.Context, vw *apis.VirtualWorkload, opts metav1.UpdateOptions) (*apis.VirtualWorkload, error) {
159+
if vw == nil {
160+
return nil, fmt.Errorf("can't update a nil vw's status")
161+
}
162+
163+
return i.client.AutoscalingV1alpha2().VirtualWorkloads(vw.Namespace).UpdateStatus(
164+
ctx, vw, opts)
165+
}

0 commit comments

Comments
 (0)