This is an automated email from the ASF dual-hosted git repository.

miaoliyao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shardingsphere-on-cloud.git


The following commit(s) were added to refs/heads/main by this push:
     new f9c8ae0  feat: add vpa for AutoScaler
     new 64c54da  Merge pull request #437 from yikuaibro/vpa
f9c8ae0 is described below

commit f9c8ae09801817fa1c51ab4fc31bdb1c50f41357
Author: li <[email protected]>
AuthorDate: Thu Jul 13 22:30:41 2023 +0800

    feat: add vpa for AutoScaler
---
 .../pkg/controllers/auto_scaler_controller.go      | 45 +++++++++++
 .../pkg/kubernetes/resources.go                    |  9 +++
 .../pkg/kubernetes/vpa/builder.go                  | 76 ++++++++++++++++++
 shardingsphere-operator/pkg/kubernetes/vpa/vpa.go  | 92 ++++++++++++++++++++++
 .../pkg/reconcile/autoscaler/auto_scaler.go        |  3 +
 .../pkg/reconcile/autoscaler/vpa.go                | 60 ++++++++++++++
 6 files changed, 285 insertions(+)

diff --git a/shardingsphere-operator/pkg/controllers/auto_scaler_controller.go 
b/shardingsphere-operator/pkg/controllers/auto_scaler_controller.go
index 11aae7a..5dcf6f7 100644
--- a/shardingsphere-operator/pkg/controllers/auto_scaler_controller.go
+++ b/shardingsphere-operator/pkg/controllers/auto_scaler_controller.go
@@ -32,6 +32,7 @@ import (
        "k8s.io/apimachinery/pkg/runtime"
        "k8s.io/apimachinery/pkg/runtime/schema"
        "k8s.io/apimachinery/pkg/types"
+       autoscalingv1 
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
        ctrl "sigs.k8s.io/controller-runtime"
        "sigs.k8s.io/controller-runtime/pkg/client"
 )
@@ -91,6 +92,11 @@ func (r *AutoScalerReconciler) reconcileAutoScaler(ctx 
context.Context, as *v1al
                                return err
                        }
                }
+               if pg.Provider == "KubernetesVPA" && pg.Vertical != nil {
+                       if err := r.reconcileVPA(ctx, &as.ObjectMeta, gvk, 
&pg); err != nil {
+                               return err
+                       }
+               }
        }
 
        return nil
@@ -111,6 +117,7 @@ func (r *AutoScalerReconciler) getHPAByNamespacedName(ctx 
context.Context, names
        return r.Resources.HPA().GetByNamespacedName(ctx, namespacedName)
 }
 
+// nolint:dupl
 func (r *AutoScalerReconciler) updateHPA(ctx context.Context, meta 
*metav1.ObjectMeta, gvk schema.GroupVersionKind, policy 
*v1alpha1.ScalingPolicy, hpa *autoscalingv2beta2.HorizontalPodAutoscaler) error 
{
        exp := r.Builder.BuildHorizontalPodAutoScaler(ctx, meta, gvk, policy)
        exp.ObjectMeta = hpa.ObjectMeta
@@ -131,3 +138,41 @@ func (r *AutoScalerReconciler) createHPA(ctx 
context.Context, meta *metav1.Objec
        }
        return err
 }
+
+func (r *AutoScalerReconciler) reconcileVPA(ctx context.Context, meta 
*metav1.ObjectMeta, gvk schema.GroupVersionKind, policy 
*v1alpha1.ScalingPolicy) error {
+       vpa, err := r.getVPAByNamespacedName(ctx, 
types.NamespacedName{Namespace: meta.Namespace, Name: meta.Name})
+       if err != nil {
+               return err
+       }
+       if vpa != nil {
+               return r.updateVPA(ctx, meta, gvk, policy, vpa)
+       }
+       return r.createVPA(ctx, meta, gvk, policy)
+}
+
+func (r *AutoScalerReconciler) getVPAByNamespacedName(ctx context.Context, 
namespacedName types.NamespacedName) (*autoscalingv1.VerticalPodAutoscaler, 
error) {
+       return r.Resources.VPA().GetByNamespacedName(ctx, namespacedName)
+}
+
+// nolint:dupl
+func (r *AutoScalerReconciler) updateVPA(ctx context.Context, meta 
*metav1.ObjectMeta, gvk schema.GroupVersionKind, policy 
*v1alpha1.ScalingPolicy, vpa *autoscalingv1.VerticalPodAutoscaler) error {
+       exp := r.Builder.BuildVerticalPodAutoscaler(ctx, meta, gvk, policy)
+       exp.ObjectMeta = vpa.ObjectMeta
+       exp.Labels = vpa.Labels
+       exp.Annotations = vpa.Annotations
+
+       if !reflect.DeepEqual(vpa.Spec, exp.Spec) {
+               return r.Resources.VPA().Update(ctx, vpa)
+       }
+       return nil
+}
+
+// nolint:dupl
+func (r *AutoScalerReconciler) createVPA(ctx context.Context, meta 
*metav1.ObjectMeta, gvk schema.GroupVersionKind, policy 
*v1alpha1.ScalingPolicy) error {
+       vpa := r.Builder.BuildVerticalPodAutoscaler(ctx, meta, gvk, policy)
+       err := r.Resources.VPA().Create(ctx, vpa)
+       if err != nil && apierrors.IsAlreadyExists(err) || err == nil {
+               return nil
+       }
+       return err
+}
diff --git a/shardingsphere-operator/pkg/kubernetes/resources.go 
b/shardingsphere-operator/pkg/kubernetes/resources.go
index d8bcdf4..fb0f0d9 100644
--- a/shardingsphere-operator/pkg/kubernetes/resources.go
+++ b/shardingsphere-operator/pkg/kubernetes/resources.go
@@ -24,6 +24,7 @@ import (
        
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/pkg/kubernetes/deployment"
        
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/pkg/kubernetes/hpa"
        
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/pkg/kubernetes/service"
+       
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/pkg/kubernetes/vpa"
 
        "sigs.k8s.io/controller-runtime/pkg/client"
 )
@@ -40,6 +41,7 @@ type KubernetesResources interface {
        Service() service.Service
        ConfigMap() configmap.ConfigMap
        HPA() hpa.HorizontalPodAutoscaler
+       VPA() vpa.VerticalPodAutoscaler
        // Job()
 }
 
@@ -57,6 +59,7 @@ func NewResources(c client.Client) Resources {
                        service:    service.NewServiceClient(c),
                        configmap:  configmap.NewConfigMapClient(c),
                        hpa:        hpa.NewHorizontalPodAutoscalerClient(c),
+                       vpa:        vpa.NewVerticalPodAutoscalerClient(c),
                },
                ExtendedResources: &extended{
                        chaosmesh:     chaosmesh.NewChaos(c),
@@ -77,6 +80,7 @@ type kubernetes struct {
        service    service.Service
        configmap  configmap.ConfigMap
        hpa        hpa.HorizontalPodAutoscaler
+       vpa        vpa.VerticalPodAutoscaler
 }
 
 // Deployment returns a Kubernetes deployment
@@ -99,6 +103,11 @@ func (r *kubernetes) HPA() hpa.HorizontalPodAutoscaler {
        return r.hpa
 }
 
+// VPA returns a Kubernetes VPA
+func (r *kubernetes) VPA() vpa.VerticalPodAutoscaler {
+       return r.vpa
+}
+
 var _ ExtendedResources = &extended{}
 
 type extended struct {
diff --git a/shardingsphere-operator/pkg/kubernetes/vpa/builder.go 
b/shardingsphere-operator/pkg/kubernetes/vpa/builder.go
new file mode 100644
index 0000000..c483b30
--- /dev/null
+++ b/shardingsphere-operator/pkg/kubernetes/vpa/builder.go
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 vpa
+
+import (
+       
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/pkg/kubernetes/metadata"
+       v1 "k8s.io/api/autoscaling/v1"
+       autoscalingv1 
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
+)
+
+// VerticalPodAutoscalerBuilder is a builder for VPA
+type VerticalPodAutoscalerBuilder interface {
+       metadata.MetadataBuilder
+
+       SetTargetRef(ref v1.CrossVersionObjectReference) 
VerticalPodAutoscalerBuilder
+       SetUpdatePolicy(pu *autoscalingv1.PodUpdatePolicy) 
VerticalPodAutoscalerBuilder
+       SetResourcePolicy(pr *autoscalingv1.PodResourcePolicy) 
VerticalPodAutoscalerBuilder
+       SetRecommenders(rs 
[]*autoscalingv1.VerticalPodAutoscalerRecommenderSelector) 
VerticalPodAutoscalerBuilder
+
+       BuildVPA() *autoscalingv1.VerticalPodAutoscaler
+}
+
+// NewVerticalPodAutoscalerBuilder returns a VerticalPodAutoscalerBuilder for 
VPA
+func NewVerticalPodAutoscalerBuilder() VerticalPodAutoscalerBuilder {
+       return &vpaBuilder{}
+}
+
+type vpaBuilder struct {
+       vpa *autoscalingv1.VerticalPodAutoscaler
+       metadata.MetadataBuilder
+}
+
+// SetTargetRef set the scale target
+func (v *vpaBuilder) SetTargetRef(ref v1.CrossVersionObjectReference) 
VerticalPodAutoscalerBuilder {
+       v.vpa.Spec.TargetRef = &ref
+       return v
+}
+
+// SetUpdatePolicy set the rules on how changes are applied to the pods
+func (v *vpaBuilder) SetUpdatePolicy(pu *autoscalingv1.PodUpdatePolicy) 
VerticalPodAutoscalerBuilder {
+       v.vpa.Spec.UpdatePolicy = pu
+       return v
+}
+
+// SetResourcePolicy set how the autoscaler computes recommended resources
+func (v *vpaBuilder) SetResourcePolicy(pr *autoscalingv1.PodResourcePolicy) 
VerticalPodAutoscalerBuilder {
+       v.vpa.Spec.ResourcePolicy = pr
+       return v
+}
+
+// SetRecommenders set the recommenders
+func (v *vpaBuilder) SetRecommenders(rs 
[]*autoscalingv1.VerticalPodAutoscalerRecommenderSelector) 
VerticalPodAutoscalerBuilder {
+       v.vpa.Spec.Recommenders = rs
+       return v
+}
+
+// BuildVPA returns a VPA
+func (v *vpaBuilder) BuildVPA() *autoscalingv1.VerticalPodAutoscaler {
+       v.vpa.ObjectMeta = *v.BuildMetadata()
+       return v.vpa
+}
diff --git a/shardingsphere-operator/pkg/kubernetes/vpa/vpa.go 
b/shardingsphere-operator/pkg/kubernetes/vpa/vpa.go
new file mode 100644
index 0000000..cc4f3f1
--- /dev/null
+++ b/shardingsphere-operator/pkg/kubernetes/vpa/vpa.go
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 vpa
+
+import (
+       "context"
+
+       apierrors "k8s.io/apimachinery/pkg/api/errors"
+       "k8s.io/apimachinery/pkg/types"
+       autoscalingv1 
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+)
+
+// NewVerticalPodAutoscalerClient creates a new VerticalPodAutoscaler
+func NewVerticalPodAutoscalerClient(c client.Client) VerticalPodAutoscaler {
+       return vpaClient{
+               getter: getter{
+                       Client: c,
+               },
+               setter: setter{
+                       Client: c,
+               },
+       }
+}
+
+// VerticalPodAutoscaler interface contains setter and getter
+type VerticalPodAutoscaler interface {
+       Getter
+       Setter
+}
+
+type vpaClient struct {
+       getter
+       setter
+}
+
+// Getter get VerticalPodAutoscaler from different parameters
+type Getter interface {
+       GetByNamespacedName(context.Context, types.NamespacedName) 
(*autoscalingv1.VerticalPodAutoscaler, error)
+}
+
+type getter struct {
+       client.Client
+}
+
+// GetByNamespacedName returns Deployment from given namespaced name
+func (dg getter) GetByNamespacedName(ctx context.Context, namespacedName 
types.NamespacedName) (*autoscalingv1.VerticalPodAutoscaler, error) {
+       hpa := &autoscalingv1.VerticalPodAutoscaler{}
+       if err := dg.Client.Get(ctx, namespacedName, hpa); err != nil {
+               if apierrors.IsNotFound(err) {
+                       return nil, nil
+               }
+               return nil, err
+       } else {
+               return hpa, nil
+       }
+}
+
+// Setter get VerticalPodAutoscaler from different parameters
+type Setter interface {
+       Create(context.Context, *autoscalingv1.VerticalPodAutoscaler) error
+       Update(context.Context, *autoscalingv1.VerticalPodAutoscaler) error
+}
+
+type setter struct {
+       client.Client
+}
+
+// Create creates VerticalPodAutoscaler
+func (ds setter) Create(ctx context.Context, vp 
*autoscalingv1.VerticalPodAutoscaler) error {
+       return ds.Client.Create(ctx, vp)
+}
+
+// Update updates VerticalPodAutoscaler
+func (ds setter) Update(ctx context.Context, vp 
*autoscalingv1.VerticalPodAutoscaler) error {
+       return ds.Client.Update(ctx, vp)
+}
diff --git a/shardingsphere-operator/pkg/reconcile/autoscaler/auto_scaler.go 
b/shardingsphere-operator/pkg/reconcile/autoscaler/auto_scaler.go
index 9950e5e..f945eb7 100644
--- a/shardingsphere-operator/pkg/reconcile/autoscaler/auto_scaler.go
+++ b/shardingsphere-operator/pkg/reconcile/autoscaler/auto_scaler.go
@@ -20,6 +20,8 @@ package autoscaler
 import (
        "context"
 
+       autoscalingv1 
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
+
        
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/api/v1alpha1"
 
        autoscalingv2 "k8s.io/api/autoscaling/v2"
@@ -30,6 +32,7 @@ import (
 // Builder build HPA from given AutoScaler
 type Builder interface {
        BuildHorizontalPodAutoScaler(context.Context, *metav1.ObjectMeta, 
schema.GroupVersionKind, *v1alpha1.ScalingPolicy) 
*autoscalingv2.HorizontalPodAutoscaler
+       BuildVerticalPodAutoscaler(context.Context, *metav1.ObjectMeta, 
schema.GroupVersionKind, *v1alpha1.ScalingPolicy) 
*autoscalingv1.VerticalPodAutoscaler
 }
 
 // NewBulder builds resources needed by AutoScaler
diff --git a/shardingsphere-operator/pkg/reconcile/autoscaler/vpa.go 
b/shardingsphere-operator/pkg/reconcile/autoscaler/vpa.go
new file mode 100644
index 0000000..d28d8d2
--- /dev/null
+++ b/shardingsphere-operator/pkg/reconcile/autoscaler/vpa.go
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 autoscaler
+
+import (
+       "context"
+
+       
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/api/v1alpha1"
+       
"github.com/apache/shardingsphere-on-cloud/shardingsphere-operator/pkg/kubernetes/vpa"
+       v1 "k8s.io/api/autoscaling/v1"
+
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/runtime/schema"
+       autoscalingv1 
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
+)
+
+func (b builder) BuildVerticalPodAutoscaler(ctx context.Context, meta 
*metav1.ObjectMeta, gvk schema.GroupVersionKind, policy 
*v1alpha1.ScalingPolicy) *autoscalingv1.VerticalPodAutoscaler {
+       blder := vpa.NewVerticalPodAutoscalerBuilder()
+       
blder.SetName(meta.Name).SetNamespace(meta.Namespace).SetLabels(meta.Labels).SetAnnotations(meta.Annotations).SetOwnerReferences([]metav1.OwnerReference{
+               *metav1.NewControllerRef(meta.GetObjectMeta(), gvk),
+       })
+
+       blder.SetTargetRef(v1.CrossVersionObjectReference{
+               Kind:       "ComputeNode",
+               Name:       policy.TargetSelector.ObjectRef.Name,
+               APIVersion: "shardingsphere.apache.org/v1alpha1",
+       })
+
+       if policy.Vertical.UpdatePolicy != nil {
+               blder.SetUpdatePolicy(policy.Vertical.UpdatePolicy)
+       }
+       if policy.Vertical.ResourcePolicy != nil {
+               blder.SetResourcePolicy(policy.Vertical.ResourcePolicy)
+       }
+       if policy.Vertical.Recommenders != nil {
+               var r []*autoscalingv1.VerticalPodAutoscalerRecommenderSelector
+               for _, recommender := range policy.Vertical.Recommenders {
+                       recommenderCopy := recommender
+                       r = append(r, &recommenderCopy)
+               }
+               blder.SetRecommenders(r)
+       }
+
+       return blder.BuildVPA()
+}

Reply via email to