diff --git a/cmd/main.go b/cmd/main.go index 04b3340c..f2fd19b3 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -23,6 +23,7 @@ import ( "os" "time" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" "k8s.io/klog/v2" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) @@ -119,6 +120,10 @@ func main() { os.Exit(1) } + if err := k8sutils.GetKubernetesVersion(); err != nil { + setupLog.Error(err, "unable to get kubernetes version, continue to start manager") + } + setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { setupLog.Error(err, "problem running manager") diff --git a/config/crd/bases/starrocks.com_starrocksclusters.yaml b/config/crd/bases/starrocks.com_starrocksclusters.yaml index f8369f07..020ea947 100644 --- a/config/crd/bases/starrocks.com_starrocksclusters.yaml +++ b/config/crd/bases/starrocks.com_starrocksclusters.yaml @@ -2872,7 +2872,6 @@ spec: format: int32 type: integer version: - default: v2beta2 description: version represents the autoscaler version for cn service. only support v1,v2beta2,v2 type: string diff --git a/deploy/starrocks.com_starrocksclusters.yaml b/deploy/starrocks.com_starrocksclusters.yaml index 1f74e2de..e3069b56 100644 --- a/deploy/starrocks.com_starrocksclusters.yaml +++ b/deploy/starrocks.com_starrocksclusters.yaml @@ -1312,7 +1312,6 @@ spec: format: int32 type: integer version: - default: v2beta2 type: string required: - maxReplicas diff --git a/pkg/apis/starrocks/v1/auto_scale.go b/pkg/apis/starrocks/v1/auto_scale.go index c2352d4d..a7aca9f7 100644 --- a/pkg/apis/starrocks/v1/auto_scale.go +++ b/pkg/apis/starrocks/v1/auto_scale.go @@ -17,6 +17,8 @@ limitations under the License. package v1 import ( + "strconv" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,7 +30,7 @@ type AutoScalingPolicy struct { HPAPolicy *HPAPolicy `json:"hpaPolicy,omitempty"` // version represents the autoscaler version for cn service. only support v1,v2beta2,v2 - // +kubebuilder:default:="v2beta2" + // +optional Version AutoScalerVersion `json:"version,omitempty"` // MinReplicas is the lower limit for the number of replicas to which the autoscaler @@ -54,6 +56,28 @@ const ( AutoScalerV2 AutoScalerVersion = "v2" ) +// Complete() completes the default value of AutoScalerVersion +func (version AutoScalerVersion) Complete(major, minor string) AutoScalerVersion { + if version != "" { + return version + } + // operator choose a proper default hpa version by checking ths kubernetes version + // if the minor version of kubernetes version >= 26, use v2 version + if major == "1" { + minorNumber, err := strconv.Atoi(minor) + if err != nil { + // keep backward compatibility + return AutoScalerV2Beta2 + } + if minorNumber >= 26 { + return AutoScalerV2 + } else { + return AutoScalerV2Beta2 + } + } + return AutoScalerV2 +} + type HPAPolicy struct { // +optional // Metrics specifies how to scale based on a single metric diff --git a/pkg/apis/starrocks/v1/auto_scale_test.go b/pkg/apis/starrocks/v1/auto_scale_test.go new file mode 100644 index 00000000..d2b0e66b --- /dev/null +++ b/pkg/apis/starrocks/v1/auto_scale_test.go @@ -0,0 +1,69 @@ +package v1 + +import "testing" + +func TestAutoScalerVersion_Complete(t *testing.T) { + type args struct { + major string + minor string + } + tests := []struct { + name string + version AutoScalerVersion + args args + want AutoScalerVersion + }{ + { + name: "test for version v1", + version: AutoScalerV1, + args: args{}, + want: AutoScalerV1, + }, + { + name: "test for version v2", + version: AutoScalerV2, + args: args{}, + want: AutoScalerV2, + }, + { + name: "test for version v2beta2", + version: AutoScalerV2Beta2, + args: args{}, + want: AutoScalerV2Beta2, + }, + { + name: "test for empty version", + version: "", + args: args{ + major: "1", + minor: "26", + }, + want: AutoScalerV2, + }, + { + name: "test for empty version2", + version: "", + args: args{ + major: "1", + minor: "25", + }, + want: AutoScalerV2Beta2, + }, + { + name: "test for empty version3", + version: "", + args: args{ + major: "1", + minor: "23", + }, + want: AutoScalerV2Beta2, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.version.Complete(tt.args.major, tt.args.minor); got != tt.want { + t.Errorf("Complete() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/common/resource_utils/autoscaler.go b/pkg/common/resource_utils/autoscaler.go index 06c7239f..3b972acd 100644 --- a/pkg/common/resource_utils/autoscaler.go +++ b/pkg/common/resource_utils/autoscaler.go @@ -20,6 +20,7 @@ import ( "unsafe" srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1" + "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils" appv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/autoscaling/v1" v2 "k8s.io/api/autoscaling/v2" @@ -45,14 +46,17 @@ type PodAutoscalerParams struct { } func BuildHorizontalPodAutoscaler(pap *PodAutoscalerParams) client.Object { - switch pap.AutoscalerType { + t := pap.AutoscalerType.Complete(k8sutils.KUBE_MAJOR_VERSION, k8sutils.KUBE_MINOR_VERSION) + switch t { case srapi.AutoScalerV1: return buildAutoscalerV1(pap) case srapi.AutoScalerV2: return buildAutoscalerV2(pap) - default: + case srapi.AutoScalerV2Beta2: return buildAutoscalerV2beta2(pap) } + // can not reach here + return buildAutoscalerV2beta2(pap) } // build v1 autoscaler diff --git a/pkg/k8sutils/k8sutils.go b/pkg/k8sutils/k8sutils.go index 956138f5..d7810cfb 100644 --- a/pkg/k8sutils/k8sutils.go +++ b/pkg/k8sutils/k8sutils.go @@ -30,6 +30,9 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -287,3 +290,36 @@ func GetConfigMap(ctx context.Context, k8scient client.Client, namespace, name s return &configMap, nil } + +var ( + KUBE_MAJOR_VERSION string + KUBE_MINOR_VERSION string +) + +// GetKubernetesVersion get kubernetes version. It should not be executed concurrently. +// The global variable KUBE_MAJOR_VERSION and KUBE_MINOR_VERSION will be set. +func GetKubernetesVersion() error { + config, err := clientcmd.BuildConfigFromFlags("", "~/.kube/config") + if err != nil { + config, err = rest.InClusterConfig() + if err != nil { + return err + } + } + + // create a discovery.DiscoveryClient object to query the metadata of the API server + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) + if err != nil { + return err + } + + // query the version information of the API server + version, err := discoveryClient.ServerVersion() + if err != nil { + return err + } + + KUBE_MAJOR_VERSION = version.Major + KUBE_MINOR_VERSION = version.Minor + return nil +} diff --git a/pkg/sub_controller/cn/cn_controller.go b/pkg/sub_controller/cn/cn_controller.go index 2bf83ace..561b52ab 100644 --- a/pkg/sub_controller/cn/cn_controller.go +++ b/pkg/sub_controller/cn/cn_controller.go @@ -206,7 +206,8 @@ func (cc *CnController) UpdateStatus(src *srapi.StarRocksCluster) error { if cnSpec.AutoScalingPolicy != nil { cs.HorizontalScaler.Name = cc.generateAutoScalerName(src) - cs.HorizontalScaler.Version = cnSpec.AutoScalingPolicy.Version + cs.HorizontalScaler.Version = cnSpec.AutoScalingPolicy.Version.Complete(k8sutils.KUBE_MAJOR_VERSION, + k8sutils.KUBE_MINOR_VERSION) } else { cs.HorizontalScaler = srapi.HorizontalScaler{} }