From 3f5ba3f21b9e813cd18dbc30bf9d3d72d39a6f6a Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Wed, 28 Feb 2024 17:34:40 +0900 Subject: [PATCH 01/13] init commit for scheduled scaling --- .gitignore | 3 + PROJECT | 9 + api/v1alpha1/groupversion_info.go | 45 +++++ api/v1alpha1/scheduledscaling_types.go | 166 ++++++++++++++++++ api/v1alpha1/zz_generated.deepcopy.go | 123 +++++++++++++ config/crd/kustomization.yaml | 3 + .../cainjection_in_scheduledscalings.yaml | 7 + .../patches/webhook_in_scheduledscalings.yaml | 16 ++ config/rbac/scheduledscaling_editor_role.yaml | 31 ++++ config/rbac/scheduledscaling_viewer_role.yaml | 27 +++ ...autoscaling_v1alpha1_scheduledscaling.yaml | 12 ++ controllers/scheduledscaling_controller.go | 71 ++++++++ controllers/suite_test.go | 3 + main.go | 8 + 14 files changed, 524 insertions(+) create mode 100644 api/v1alpha1/groupversion_info.go create mode 100644 api/v1alpha1/scheduledscaling_types.go create mode 100644 api/v1alpha1/zz_generated.deepcopy.go create mode 100644 config/crd/patches/cainjection_in_scheduledscalings.yaml create mode 100644 config/crd/patches/webhook_in_scheduledscalings.yaml create mode 100644 config/rbac/scheduledscaling_editor_role.yaml create mode 100644 config/rbac/scheduledscaling_viewer_role.yaml create mode 100644 config/samples/autoscaling_v1alpha1_scheduledscaling.yaml create mode 100644 controllers/scheduledscaling_controller.go diff --git a/.gitignore b/.gitignore index c0a7a54c..ab6c373e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ testbin/* *.swp *.swo *~ + +# kubebuilder +kubebuilder \ No newline at end of file diff --git a/PROJECT b/PROJECT index 5fc2fe1f..93e37839 100644 --- a/PROJECT +++ b/PROJECT @@ -28,4 +28,13 @@ resources: webhooks: defaulting: true webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: mercari.com + group: autoscaling + kind: ScheduledScaling + path: github.com/mercari/tortoise/api/v1alpha1 + version: v1alpha1 version: "3" diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go new file mode 100644 index 00000000..c771cf72 --- /dev/null +++ b/api/v1alpha1/groupversion_info.go @@ -0,0 +1,45 @@ +/* +MIT License + +Copyright (c) 2023 mercari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// Package v1alpha1 contains API Schema definitions for the autoscaling v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=autoscaling.mercari.com +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "autoscaling.mercari.com", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1alpha1/scheduledscaling_types.go b/api/v1alpha1/scheduledscaling_types.go new file mode 100644 index 00000000..3c0ca3d0 --- /dev/null +++ b/api/v1alpha1/scheduledscaling_types.go @@ -0,0 +1,166 @@ +/* +MIT License + +Copyright (c) 2023 mercari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// ScheduledScalingSpec defines the desired state of ScheduledScaling +type ScheduledScalingSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + /// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + Schedule Schedule `json:"schedule" protobuf:"bytes,1,name=schedule"` + + //TargetRef is the targets that need to be scheduled + TargetRefs TargetRefs `json:"targetRefs" protobuf:"bytes,2,name=targetRefs"` + + //Currently only static, might implement others(?) + Strategy Strategy `json:"strategy" protobuf:"bytes,3,name=strategy"` +} + +// ScheduledScalingStatus defines the observed state of ScheduledScaling +type ScheduledScalingStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + //Target tortoise phase + TortoisePhase TortoisePhase `json:"tortoisePhase" protobuf:"bytes,1,name=tortoisePhase"` + + //unsure if needed + ScheduledScalingPhase ScheduledScalingPhase `json:"scheduledScalingPhase" protobuf:"bytes,1,name=scheduledScalingPhase"` + + // AutoscalingPolicy contains the policy how this tortoise actually scales each resource. + // It should basically be the same as .spec.autoscalingPolicy. + // But, if .spec.autoscalingPolicy is empty, tortoise manages/generates + // the policies generated based on HPA and the target deployment. + //Commenting this just in case there is a need for separate autoscaling policy in schedule + //AutoscalingPolicy []ContainerAutoscalingPolicy `json:"autoscalingPolicy,omitempty" protobuf:"bytes,6,opt,name=autoscalingPolicy"` +} + +// Unsure if needed +type ScheduledScalingPhase string + +type TortoisePhase string + +const ( + // TortoisePhaseInitializing means tortoise is just created and initializing some components (HPA and VPA), + // and wait for those components to be ready. + TortoisePhaseInitializing TortoisePhase = "Initializing" + // TortoisePhaseGatheringData means tortoise is now gathering data and cannot make the accurate recommendations. + TortoisePhaseGatheringData TortoisePhase = "GatheringData" + // TortoisePhaseWorking means tortoise is making the recommendations, + // and applying the recommendation values. + TortoisePhaseWorking TortoisePhase = "Working" + // TortoisePhasePartlyWorking means tortoise has maxReplicas and minReplicas recommendations ready, + // and applying the recommendation values. + // But, some of the resources are not scaled due to some reasons. (probably still gathering data) + TortoisePhasePartlyWorking TortoisePhase = "PartlyWorking" + // TortoisePhaseEmergency means tortoise is in the emergency mode. + TortoisePhaseEmergency TortoisePhase = "Emergency" + // TortoisePhaseBackToNormal means tortoise was in the emergency mode, and now it's coming back to the normal operation. + // During TortoisePhaseBackToNormal, the number of replicas of workloads are gradually reduced to the usual value. + TortoisePhaseBackToNormal TortoisePhase = "BackToNormal" +) + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// ScheduledScaling is the Schema for the scheduledscalings API +type ScheduledScaling struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ScheduledScalingSpec `json:"spec,omitempty"` + Status ScheduledScalingStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ScheduledScalingList contains a list of ScheduledScaling +type ScheduledScalingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ScheduledScaling `json:"items"` +} + +type TargetRefs struct { + // ScaleTargetRef is the target of scaling. + // It should be the same as the target of HPA. + ScaleTargetRef CrossVersionObjectReference `json:"scaleTargetRef" protobuf:"bytes,1,name=scaleTargetRef"` + //Tortoise to be targeted for scheduled scaling + TortoiseName *string `json:"tortoiseName,omitempty" protobuf:"bytes,2,name=tortoiseName"` +} + +// CrossVersionObjectReference contains enough information toet identify the referred resource. +type CrossVersionObjectReference struct { + // kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"` + + // name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + Name string `json:"name" protobuf:"bytes,2,opt,name=name"` + + // apiVersion is the API version of the referent + // +optional + APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"` +} + +type Schedule struct { + /// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + //start of schedule + StartAt string `json:"startAt" protobuf:"bytes,1,name=startAt"` + //end of schedule + FinishAt string `json:"finishAt" protobuf:"bytes,2,name=finishAt"` +} + +type Strategy struct { + //Resource scaling requirements + Static Static `json:"static" protobuf: "bytes,1,name=static"` +} + +type Static struct { + //Min replicas to be deployed on schedule + MinReplicas int `json:"minReplica" protobuf:"bytes,1,name=minReplica"` + //Resources requested per container + MinAllocatedResources []ContainerResourceRequests `json:"minAllocatedResources" protobuf:"bytes,2,name=minAllocatedResources"` +} + +// Not sure if I need this here, duplicated code from tortoise types +type ContainerResourceRequests struct { + // ContainerName is the name of target container. + ContainerName string `json:"containerName" protobuf:"bytes,1,name=containerName"` + Resource v1.ResourceList `json:"resource" protobuf:"bytes,2,name=resource"` +} + +func init() { + SchemeBuilder.Register(&ScheduledScaling{}, &ScheduledScalingList{}) +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000..3f47d9c9 --- /dev/null +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,123 @@ +//go:build !ignore_autogenerated + +/* +MIT License + +Copyright (c) 2023 mercari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledScaling) DeepCopyInto(out *ScheduledScaling) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledScaling. +func (in *ScheduledScaling) DeepCopy() *ScheduledScaling { + if in == nil { + return nil + } + out := new(ScheduledScaling) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ScheduledScaling) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledScalingList) DeepCopyInto(out *ScheduledScalingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ScheduledScaling, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledScalingList. +func (in *ScheduledScalingList) DeepCopy() *ScheduledScalingList { + if in == nil { + return nil + } + out := new(ScheduledScalingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ScheduledScalingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledScalingSpec) DeepCopyInto(out *ScheduledScalingSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledScalingSpec. +func (in *ScheduledScalingSpec) DeepCopy() *ScheduledScalingSpec { + if in == nil { + return nil + } + out := new(ScheduledScalingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledScalingStatus) DeepCopyInto(out *ScheduledScalingStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledScalingStatus. +func (in *ScheduledScalingStatus) DeepCopy() *ScheduledScalingStatus { + if in == nil { + return nil + } + out := new(ScheduledScalingStatus) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 2307667d..0ac52374 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -3,6 +3,7 @@ # It should be run by config/default resources: - bases/autoscaling.mercari.com_tortoises.yaml +- bases/autoscaling.mercari.com_scheduledscalings.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -10,12 +11,14 @@ patchesStrategicMerge: # patches here are for enabling the conversion webhook for each CRD - patches/webhook_in_tortoises.yaml #- patches/webhook_in_tortoises.yaml +#- patches/webhook_in_scheduledscalings.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD - patches/cainjection_in_tortoises.yaml #- patches/cainjection_in_tortoises.yaml +#- patches/cainjection_in_scheduledscalings.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_scheduledscalings.yaml b/config/crd/patches/cainjection_in_scheduledscalings.yaml new file mode 100644 index 00000000..6f18016a --- /dev/null +++ b/config/crd/patches/cainjection_in_scheduledscalings.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: scheduledscalings.autoscaling.mercari.com diff --git a/config/crd/patches/webhook_in_scheduledscalings.yaml b/config/crd/patches/webhook_in_scheduledscalings.yaml new file mode 100644 index 00000000..915eedb2 --- /dev/null +++ b/config/crd/patches/webhook_in_scheduledscalings.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: scheduledscalings.autoscaling.mercari.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/scheduledscaling_editor_role.yaml b/config/rbac/scheduledscaling_editor_role.yaml new file mode 100644 index 00000000..38e04028 --- /dev/null +++ b/config/rbac/scheduledscaling_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit scheduledscalings. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: scheduledscaling-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: tortoise + app.kubernetes.io/part-of: tortoise + app.kubernetes.io/managed-by: kustomize + name: scheduledscaling-editor-role +rules: +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings/status + verbs: + - get diff --git a/config/rbac/scheduledscaling_viewer_role.yaml b/config/rbac/scheduledscaling_viewer_role.yaml new file mode 100644 index 00000000..f8db1911 --- /dev/null +++ b/config/rbac/scheduledscaling_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view scheduledscalings. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: scheduledscaling-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: tortoise + app.kubernetes.io/part-of: tortoise + app.kubernetes.io/managed-by: kustomize + name: scheduledscaling-viewer-role +rules: +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings + verbs: + - get + - list + - watch +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings/status + verbs: + - get diff --git a/config/samples/autoscaling_v1alpha1_scheduledscaling.yaml b/config/samples/autoscaling_v1alpha1_scheduledscaling.yaml new file mode 100644 index 00000000..0c97abc7 --- /dev/null +++ b/config/samples/autoscaling_v1alpha1_scheduledscaling.yaml @@ -0,0 +1,12 @@ +apiVersion: autoscaling.mercari.com/v1alpha1 +kind: ScheduledScaling +metadata: + labels: + app.kubernetes.io/name: scheduledscaling + app.kubernetes.io/instance: scheduledscaling-sample + app.kubernetes.io/part-of: tortoise + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: tortoise + name: scheduledscaling-sample +spec: + # TODO(user): Add fields here diff --git a/controllers/scheduledscaling_controller.go b/controllers/scheduledscaling_controller.go new file mode 100644 index 00000000..1d7c582f --- /dev/null +++ b/controllers/scheduledscaling_controller.go @@ -0,0 +1,71 @@ +/* +MIT License + +Copyright (c) 2023 mercari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +package controllers + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + autoscalingv1alpha1 "github.com/mercari/tortoise/api/v1alpha1" +) + +// ScheduledScalingReconciler reconciles a ScheduledScaling object +type ScheduledScalingReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +//+kubebuilder:rbac:groups=autoscaling.mercari.com,resources=scheduledscalings,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=autoscaling.mercari.com,resources=scheduledscalings/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=autoscaling.mercari.com,resources=scheduledscalings/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the ScheduledScaling object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile +func (r *ScheduledScalingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = log.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ScheduledScalingReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&autoscalingv1alpha1.ScheduledScaling{}). + Complete(r) +} diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 652ed475..a5c8b313 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -92,6 +92,9 @@ var _ = BeforeSuite(func() { err = v2.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) + err = autoscalingv1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) diff --git a/main.go b/main.go index fda64907..7f01633a 100644 --- a/main.go +++ b/main.go @@ -72,6 +72,7 @@ func init() { utilruntime.Must(autoscalingv1beta3.AddToScheme(scheme)) utilruntime.Must(autoscalingv1beta3.AddToScheme(scheme)) + utilruntime.Must(autoscalingv1alpha1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -196,6 +197,13 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "Tortoise") os.Exit(1) } + if err = (&controllers.ScheduledScalingReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "ScheduledScaling") + os.Exit(1) + } //+kubebuilder:scaffold:builder hpaWebhook := autoscalingv2.New(tortoiseService, hpaService) From 19dd498b2e6056d10dbd23be3c6e4fa2fb9c5800 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Wed, 28 Feb 2024 17:45:25 +0900 Subject: [PATCH 02/13] make manifests --- ...scaling.mercari.com_scheduledscalings.yaml | 141 ++++++++++++++++++ config/rbac/role.yaml | 26 ++++ ...duledscalings.autoscaling.mercari.com.yaml | 130 ++++++++++++++++ ...duledscalings.autoscaling.mercari.com.yaml | 130 ++++++++++++++++ ..._v1_clusterrole_tortoise-manager-role.yaml | 26 ++++ 5 files changed, 453 insertions(+) create mode 100644 config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml create mode 100644 manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml create mode 100644 manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml diff --git a/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml b/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml new file mode 100644 index 00000000..2bf684b4 --- /dev/null +++ b/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml @@ -0,0 +1,141 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: scheduledscalings.autoscaling.mercari.com +spec: + group: autoscaling.mercari.com + names: + kind: ScheduledScaling + listKind: ScheduledScalingList + plural: scheduledscalings + singular: scheduledscaling + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ScheduledScaling is the Schema for the scheduledscalings API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ScheduledScalingSpec defines the desired state of ScheduledScaling + properties: + schedule: + description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + properties: + finishAt: + description: end of schedule + type: string + startAt: + description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + start of schedule + type: string + required: + - finishAt + - startAt + type: object + strategy: + description: Currently only static, might implement others(?) + properties: + static: + description: Resource scaling requirements + properties: + minAllocatedResources: + description: Resources requested per container + items: + description: Not sure if I need this here, duplicated code + from tortoise types + properties: + containerName: + description: ContainerName is the name of target container. + type: string + resource: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: ResourceList is a set of (resource name, + quantity) pairs. + type: object + required: + - containerName + - resource + type: object + type: array + minReplica: + description: Min replicas to be deployed on schedule + type: integer + required: + - minAllocatedResources + - minReplica + type: object + required: + - static + type: object + targetRefs: + description: TargetRef is the targets that need to be scheduled + properties: + scaleTargetRef: + description: ScaleTargetRef is the target of scaling. It should + be the same as the target of HPA. + properties: + apiVersion: + description: apiVersion is the API version of the referent + type: string + kind: + description: 'kind is the kind of the referent; More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'name is the name of the referent; More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + required: + - kind + - name + type: object + tortoiseName: + description: Tortoise to be targeted for scheduled scaling + type: string + required: + - scaleTargetRef + type: object + required: + - schedule + - strategy + - targetRefs + type: object + status: + description: ScheduledScalingStatus defines the observed state of ScheduledScaling + properties: + scheduledScalingPhase: + description: unsure if needed + type: string + tortoisePhase: + description: Target tortoise phase + type: string + required: + - scheduledScalingPhase + - tortoisePhase + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index fe3e7558..0ba16255 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -76,6 +76,32 @@ rules: - patch - update - watch +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings/finalizers + verbs: + - update +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings/status + verbs: + - get + - patch + - update - apiGroups: - autoscaling.mercari.com resources: diff --git a/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml b/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml new file mode 100644 index 00000000..1ff5b2f4 --- /dev/null +++ b/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml @@ -0,0 +1,130 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: scheduledscalings.autoscaling.mercari.com +spec: + group: autoscaling.mercari.com + names: + kind: ScheduledScaling + listKind: ScheduledScalingList + plural: scheduledscalings + singular: scheduledscaling + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ScheduledScaling is the Schema for the scheduledscalings API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ScheduledScalingSpec defines the desired state of ScheduledScaling + properties: + schedule: + description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + properties: + finishAt: + description: end of schedule + type: string + startAt: + description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule + type: string + required: + - finishAt + - startAt + type: object + strategy: + description: Currently only static, might implement others(?) + properties: + static: + description: Resource scaling requirements + properties: + minAllocatedResources: + description: Resources requested per container + items: + description: Not sure if I need this here, duplicated code from tortoise types + properties: + containerName: + description: ContainerName is the name of target container. + type: string + resource: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: ResourceList is a set of (resource name, quantity) pairs. + type: object + required: + - containerName + - resource + type: object + type: array + minReplica: + description: Min replicas to be deployed on schedule + type: integer + required: + - minAllocatedResources + - minReplica + type: object + required: + - static + type: object + targetRefs: + description: TargetRef is the targets that need to be scheduled + properties: + scaleTargetRef: + description: ScaleTargetRef is the target of scaling. It should be the same as the target of HPA. + properties: + apiVersion: + description: apiVersion is the API version of the referent + type: string + kind: + description: 'kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + required: + - kind + - name + type: object + tortoiseName: + description: Tortoise to be targeted for scheduled scaling + type: string + required: + - scaleTargetRef + type: object + required: + - schedule + - strategy + - targetRefs + type: object + status: + description: ScheduledScalingStatus defines the observed state of ScheduledScaling + properties: + scheduledScalingPhase: + description: unsure if needed + type: string + tortoisePhase: + description: Target tortoise phase + type: string + required: + - scheduledScalingPhase + - tortoisePhase + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml b/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml new file mode 100644 index 00000000..1ff5b2f4 --- /dev/null +++ b/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml @@ -0,0 +1,130 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: scheduledscalings.autoscaling.mercari.com +spec: + group: autoscaling.mercari.com + names: + kind: ScheduledScaling + listKind: ScheduledScalingList + plural: scheduledscalings + singular: scheduledscaling + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ScheduledScaling is the Schema for the scheduledscalings API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ScheduledScalingSpec defines the desired state of ScheduledScaling + properties: + schedule: + description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + properties: + finishAt: + description: end of schedule + type: string + startAt: + description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule + type: string + required: + - finishAt + - startAt + type: object + strategy: + description: Currently only static, might implement others(?) + properties: + static: + description: Resource scaling requirements + properties: + minAllocatedResources: + description: Resources requested per container + items: + description: Not sure if I need this here, duplicated code from tortoise types + properties: + containerName: + description: ContainerName is the name of target container. + type: string + resource: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: ResourceList is a set of (resource name, quantity) pairs. + type: object + required: + - containerName + - resource + type: object + type: array + minReplica: + description: Min replicas to be deployed on schedule + type: integer + required: + - minAllocatedResources + - minReplica + type: object + required: + - static + type: object + targetRefs: + description: TargetRef is the targets that need to be scheduled + properties: + scaleTargetRef: + description: ScaleTargetRef is the target of scaling. It should be the same as the target of HPA. + properties: + apiVersion: + description: apiVersion is the API version of the referent + type: string + kind: + description: 'kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + required: + - kind + - name + type: object + tortoiseName: + description: Tortoise to be targeted for scheduled scaling + type: string + required: + - scaleTargetRef + type: object + required: + - schedule + - strategy + - targetRefs + type: object + status: + description: ScheduledScalingStatus defines the observed state of ScheduledScaling + properties: + scheduledScalingPhase: + description: unsure if needed + type: string + tortoisePhase: + description: Target tortoise phase + type: string + required: + - scheduledScalingPhase + - tortoisePhase + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/manifests/default/rbac.authorization.k8s.io_v1_clusterrole_tortoise-manager-role.yaml b/manifests/default/rbac.authorization.k8s.io_v1_clusterrole_tortoise-manager-role.yaml index e17fbc50..2fd14d72 100644 --- a/manifests/default/rbac.authorization.k8s.io_v1_clusterrole_tortoise-manager-role.yaml +++ b/manifests/default/rbac.authorization.k8s.io_v1_clusterrole_tortoise-manager-role.yaml @@ -75,6 +75,32 @@ rules: - patch - update - watch +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings/finalizers + verbs: + - update +- apiGroups: + - autoscaling.mercari.com + resources: + - scheduledscalings/status + verbs: + - get + - patch + - update - apiGroups: - autoscaling.mercari.com resources: From d62ede650903320a197c09dd7781fdb3443936cc Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Tue, 5 Mar 2024 16:53:51 +0900 Subject: [PATCH 03/13] make manifests --- api/v1alpha1/scheduledscaling_types.go | 64 ++++++-------------------- 1 file changed, 15 insertions(+), 49 deletions(-) diff --git a/api/v1alpha1/scheduledscaling_types.go b/api/v1alpha1/scheduledscaling_types.go index 3c0ca3d0..df308bac 100644 --- a/api/v1alpha1/scheduledscaling_types.go +++ b/api/v1alpha1/scheduledscaling_types.go @@ -41,10 +41,10 @@ type ScheduledScalingSpec struct { /// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. Schedule Schedule `json:"schedule" protobuf:"bytes,1,name=schedule"` - //TargetRef is the targets that need to be scheduled + // TargetRef is the targets that need to be scheduled TargetRefs TargetRefs `json:"targetRefs" protobuf:"bytes,2,name=targetRefs"` - //Currently only static, might implement others(?) + // Currently only static, might implement others(?) Strategy Strategy `json:"strategy" protobuf:"bytes,3,name=strategy"` } @@ -53,45 +53,11 @@ type ScheduledScalingStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file - //Target tortoise phase - TortoisePhase TortoisePhase `json:"tortoisePhase" protobuf:"bytes,1,name=tortoisePhase"` - - //unsure if needed ScheduledScalingPhase ScheduledScalingPhase `json:"scheduledScalingPhase" protobuf:"bytes,1,name=scheduledScalingPhase"` - - // AutoscalingPolicy contains the policy how this tortoise actually scales each resource. - // It should basically be the same as .spec.autoscalingPolicy. - // But, if .spec.autoscalingPolicy is empty, tortoise manages/generates - // the policies generated based on HPA and the target deployment. - //Commenting this just in case there is a need for separate autoscaling policy in schedule - //AutoscalingPolicy []ContainerAutoscalingPolicy `json:"autoscalingPolicy,omitempty" protobuf:"bytes,6,opt,name=autoscalingPolicy"` } -// Unsure if needed type ScheduledScalingPhase string -type TortoisePhase string - -const ( - // TortoisePhaseInitializing means tortoise is just created and initializing some components (HPA and VPA), - // and wait for those components to be ready. - TortoisePhaseInitializing TortoisePhase = "Initializing" - // TortoisePhaseGatheringData means tortoise is now gathering data and cannot make the accurate recommendations. - TortoisePhaseGatheringData TortoisePhase = "GatheringData" - // TortoisePhaseWorking means tortoise is making the recommendations, - // and applying the recommendation values. - TortoisePhaseWorking TortoisePhase = "Working" - // TortoisePhasePartlyWorking means tortoise has maxReplicas and minReplicas recommendations ready, - // and applying the recommendation values. - // But, some of the resources are not scaled due to some reasons. (probably still gathering data) - TortoisePhasePartlyWorking TortoisePhase = "PartlyWorking" - // TortoisePhaseEmergency means tortoise is in the emergency mode. - TortoisePhaseEmergency TortoisePhase = "Emergency" - // TortoisePhaseBackToNormal means tortoise was in the emergency mode, and now it's coming back to the normal operation. - // During TortoisePhaseBackToNormal, the number of replicas of workloads are gradually reduced to the usual value. - TortoisePhaseBackToNormal TortoisePhase = "BackToNormal" -) - //+kubebuilder:object:root=true //+kubebuilder:subresource:status @@ -124,34 +90,34 @@ type TargetRefs struct { // CrossVersionObjectReference contains enough information toet identify the referred resource. type CrossVersionObjectReference struct { // kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"` + Kind *string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` // name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - Name string `json:"name" protobuf:"bytes,2,opt,name=name"` + Name *string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"` // apiVersion is the API version of the referent // +optional - APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"` + APIVersion *string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"` } type Schedule struct { /// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. - //start of schedule - StartAt string `json:"startAt" protobuf:"bytes,1,name=startAt"` - //end of schedule - FinishAt string `json:"finishAt" protobuf:"bytes,2,name=finishAt"` + // start of schedule + StartAt *string `json:"startAt,omitempty" protobuf:"bytes,1,opt,name=startAt"` + // end of schedule + FinishAt *string `json:"finishAt,omitempty" protobuf:"bytes,2,name=finishAt"` } type Strategy struct { - //Resource scaling requirements - Static Static `json:"static" protobuf: "bytes,1,name=static"` + // Resource scaling requirements + Static *Static `json:"static,omitempty" protobuf:"bytes,1,opt,name=static"` } type Static struct { - //Min replicas to be deployed on schedule - MinReplicas int `json:"minReplica" protobuf:"bytes,1,name=minReplica"` - //Resources requested per container - MinAllocatedResources []ContainerResourceRequests `json:"minAllocatedResources" protobuf:"bytes,2,name=minAllocatedResources"` + // Min replicas to be deployed on schedule + MinimumMinReplicas *int `json:"minimumMinReplica,omitempty" protobuf:"bytes,1,opt,name=minimumMinReplica"` + // Resources requested per container + MinAllocatedResources []ContainerResourceRequests `json:"minAllocatedResourcesomitempty,omitempty" protobuf:"bytes,2,opt,name=minAllocatedResources"` } // Not sure if I need this here, duplicated code from tortoise types From 9c39e80a2049aa68780a9512a8cd1225e1940516 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Tue, 5 Mar 2024 16:53:55 +0900 Subject: [PATCH 04/13] make manifests --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index ab6c373e..c0a7a54c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,3 @@ testbin/* *.swp *.swo *~ - -# kubebuilder -kubebuilder \ No newline at end of file From 29ed82d8bef23e2cfdca02e84c75bc78eb600304 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Tue, 5 Mar 2024 16:54:20 +0900 Subject: [PATCH 05/13] make manifests --- ...scaling.mercari.com_scheduledscalings.yaml | 20 ++----------------- ...duledscalings.autoscaling.mercari.com.yaml | 20 ++----------------- ...duledscalings.autoscaling.mercari.com.yaml | 20 ++----------------- 3 files changed, 6 insertions(+), 54 deletions(-) diff --git a/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml b/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml index 2bf684b4..c2ff01fd 100644 --- a/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml +++ b/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml @@ -44,9 +44,6 @@ spec: description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule type: string - required: - - finishAt - - startAt type: object strategy: description: Currently only static, might implement others(?) @@ -54,7 +51,7 @@ spec: static: description: Resource scaling requirements properties: - minAllocatedResources: + minAllocatedResourcesomitempty: description: Resources requested per container items: description: Not sure if I need this here, duplicated code @@ -78,15 +75,10 @@ spec: - resource type: object type: array - minReplica: + minimumMinReplica: description: Min replicas to be deployed on schedule type: integer - required: - - minAllocatedResources - - minReplica type: object - required: - - static type: object targetRefs: description: TargetRef is the targets that need to be scheduled @@ -106,9 +98,6 @@ spec: description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string - required: - - kind - - name type: object tortoiseName: description: Tortoise to be targeted for scheduled scaling @@ -125,14 +114,9 @@ spec: description: ScheduledScalingStatus defines the observed state of ScheduledScaling properties: scheduledScalingPhase: - description: unsure if needed - type: string - tortoisePhase: - description: Target tortoise phase type: string required: - scheduledScalingPhase - - tortoisePhase type: object type: object served: true diff --git a/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml b/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml index 1ff5b2f4..e5b17302 100644 --- a/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml +++ b/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml @@ -38,9 +38,6 @@ spec: startAt: description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule type: string - required: - - finishAt - - startAt type: object strategy: description: Currently only static, might implement others(?) @@ -48,7 +45,7 @@ spec: static: description: Resource scaling requirements properties: - minAllocatedResources: + minAllocatedResourcesomitempty: description: Resources requested per container items: description: Not sure if I need this here, duplicated code from tortoise types @@ -70,15 +67,10 @@ spec: - resource type: object type: array - minReplica: + minimumMinReplica: description: Min replicas to be deployed on schedule type: integer - required: - - minAllocatedResources - - minReplica type: object - required: - - static type: object targetRefs: description: TargetRef is the targets that need to be scheduled @@ -95,9 +87,6 @@ spec: name: description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string - required: - - kind - - name type: object tortoiseName: description: Tortoise to be targeted for scheduled scaling @@ -114,14 +103,9 @@ spec: description: ScheduledScalingStatus defines the observed state of ScheduledScaling properties: scheduledScalingPhase: - description: unsure if needed - type: string - tortoisePhase: - description: Target tortoise phase type: string required: - scheduledScalingPhase - - tortoisePhase type: object type: object served: true diff --git a/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml b/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml index 1ff5b2f4..e5b17302 100644 --- a/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml +++ b/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml @@ -38,9 +38,6 @@ spec: startAt: description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule type: string - required: - - finishAt - - startAt type: object strategy: description: Currently only static, might implement others(?) @@ -48,7 +45,7 @@ spec: static: description: Resource scaling requirements properties: - minAllocatedResources: + minAllocatedResourcesomitempty: description: Resources requested per container items: description: Not sure if I need this here, duplicated code from tortoise types @@ -70,15 +67,10 @@ spec: - resource type: object type: array - minReplica: + minimumMinReplica: description: Min replicas to be deployed on schedule type: integer - required: - - minAllocatedResources - - minReplica type: object - required: - - static type: object targetRefs: description: TargetRef is the targets that need to be scheduled @@ -95,9 +87,6 @@ spec: name: description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string - required: - - kind - - name type: object tortoiseName: description: Tortoise to be targeted for scheduled scaling @@ -114,14 +103,9 @@ spec: description: ScheduledScalingStatus defines the observed state of ScheduledScaling properties: scheduledScalingPhase: - description: unsure if needed - type: string - tortoisePhase: - description: Target tortoise phase type: string required: - scheduledScalingPhase - - tortoisePhase type: object type: object served: true From 976bcd12c10891c64e8a2ed9aed76042e6b72007 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Tue, 5 Mar 2024 17:23:05 +0900 Subject: [PATCH 06/13] go import --- go.mod | 11 ++++++----- go.sum | 12 ++++++++++++ main.go | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index be38279f..04c8d57c 100644 --- a/go.mod +++ b/go.mod @@ -59,13 +59,14 @@ require ( github.com/stretchr/testify v1.8.3 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/mod v0.16.0 // indirect + golang.org/x/net v0.22.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.4.0 // indirect - golang.org/x/tools v0.9.1 // indirect + golang.org/x/tools v0.19.0 // indirect gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect diff --git a/go.sum b/go.sum index 36149e0f..9562aee4 100644 --- a/go.sum +++ b/go.sum @@ -137,6 +137,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -146,6 +148,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -163,14 +167,20 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -181,6 +191,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/main.go b/main.go index f99c59b2..8881a70f 100644 --- a/main.go +++ b/main.go @@ -139,6 +139,7 @@ func main() { // after the manager stops then its usage might be unsafe. LeaderElectionReleaseOnCancel: true, }) + if err != nil { setupLog.Error(err, "unable to start manager") os.Exit(1) From fb215a634e4f4ce4165c7ae2925ad42ecb87f37e Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Tue, 5 Mar 2024 17:33:18 +0900 Subject: [PATCH 07/13] manual import --- controllers/suite_test.go | 1 + main.go | 1 + 2 files changed, 2 insertions(+) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index a5c8b313..f47b1f55 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -44,6 +44,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + autoscalingv1alpha1 "github.com/mercari/tortoise/api/v1alpha1" autoscalingv1beta3 "github.com/mercari/tortoise/api/v1beta3" . "github.com/onsi/ginkgo/v2" diff --git a/main.go b/main.go index 8881a70f..14a0b30f 100644 --- a/main.go +++ b/main.go @@ -47,6 +47,7 @@ import ( autoscalingv2 "github.com/mercari/tortoise/api/autoscaling/v2" v1 "github.com/mercari/tortoise/api/core/v1" + autoscalingv1alpha1 "github.com/mercari/tortoise/api/v1alpha1" autoscalingv1beta3 "github.com/mercari/tortoise/api/v1beta3" "github.com/mercari/tortoise/controllers" "github.com/mercari/tortoise/pkg/config" From 4a5215c63741037d2ab46cbeebeff6ad0127fefd Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Tue, 5 Mar 2024 17:36:56 +0900 Subject: [PATCH 08/13] fix test --- controllers/suite_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index f47b1f55..ab9db268 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -93,7 +93,7 @@ var _ = BeforeSuite(func() { err = v2.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) - err = autoscalingv1alpha1.AddToScheme(scheme.Scheme) + err = autoscalingv1alpha1.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) //+kubebuilder:scaffold:scheme From de18d63bfe002a31030e430ff44610a5b4db0650 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Wed, 6 Mar 2024 04:22:34 +0900 Subject: [PATCH 09/13] fix comments --- api/v1alpha1/scheduledscaling_types.go | 44 ++++++++------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/api/v1alpha1/scheduledscaling_types.go b/api/v1alpha1/scheduledscaling_types.go index df308bac..8961f224 100644 --- a/api/v1alpha1/scheduledscaling_types.go +++ b/api/v1alpha1/scheduledscaling_types.go @@ -26,7 +26,7 @@ SOFTWARE. package v1alpha1 import ( - v1 "k8s.io/api/core/v1" + autoscalingv1beta3 "github.com/mercari/tortoise/api/v1beta3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -38,13 +38,14 @@ type ScheduledScalingSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - /// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + /// Schedule RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" Schedule Schedule `json:"schedule" protobuf:"bytes,1,name=schedule"` // TargetRef is the targets that need to be scheduled TargetRefs TargetRefs `json:"targetRefs" protobuf:"bytes,2,name=targetRefs"` - // Currently only static, might implement others(?) + // Strategy describes how this ScheduledScaling scales the target workload. + // Currently, it only supports the static strategy. Strategy Strategy `json:"strategy" protobuf:"bytes,3,name=strategy"` } @@ -80,28 +81,12 @@ type ScheduledScalingList struct { } type TargetRefs struct { - // ScaleTargetRef is the target of scaling. - // It should be the same as the target of HPA. - ScaleTargetRef CrossVersionObjectReference `json:"scaleTargetRef" protobuf:"bytes,1,name=scaleTargetRef"` //Tortoise to be targeted for scheduled scaling TortoiseName *string `json:"tortoiseName,omitempty" protobuf:"bytes,2,name=tortoiseName"` } -// CrossVersionObjectReference contains enough information toet identify the referred resource. -type CrossVersionObjectReference struct { - // kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - Kind *string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` - - // name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - Name *string `json:"name,omitempty" protobuf:"bytes,2,opt,name=name"` - - // apiVersion is the API version of the referent - // +optional - APIVersion *string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"` -} - type Schedule struct { - /// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + /// RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" // start of schedule StartAt *string `json:"startAt,omitempty" protobuf:"bytes,1,opt,name=startAt"` // end of schedule @@ -110,21 +95,20 @@ type Schedule struct { type Strategy struct { // Resource scaling requirements + // Static strategy receives the static value of the replica number and resource requests + // that users want to give to Pods during this ScheduledScaling is valid. + // This field is optional for the future when we add another strategy here though, + // until then this strategy is the only supported strategy + // you must set this. + // +optional Static *Static `json:"static,omitempty" protobuf:"bytes,1,opt,name=static"` } type Static struct { - // Min replicas to be deployed on schedule + // MinimumMinReplicas means the minimum MinReplicas that Tortoise gives to HPA during this ScheduledScaling is valid. MinimumMinReplicas *int `json:"minimumMinReplica,omitempty" protobuf:"bytes,1,opt,name=minimumMinReplica"` - // Resources requested per container - MinAllocatedResources []ContainerResourceRequests `json:"minAllocatedResourcesomitempty,omitempty" protobuf:"bytes,2,opt,name=minAllocatedResources"` -} - -// Not sure if I need this here, duplicated code from tortoise types -type ContainerResourceRequests struct { - // ContainerName is the name of target container. - ContainerName string `json:"containerName" protobuf:"bytes,1,name=containerName"` - Resource v1.ResourceList `json:"resource" protobuf:"bytes,2,name=resource"` + // MinAllowedResources means the minimum resource requests that Tortoise gives to each container. + MinAllocatedResources []autoscalingv1beta3.ContainerResourceRequests `json:"minAllocatedResourcesomitempty,omitempty" protobuf:"bytes,2,opt,name=minAllocatedResources"` } func init() { From 0ea2f8c3132fa8917e89a6d7f90f72b0ebdaddf9 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Wed, 6 Mar 2024 11:46:11 +0900 Subject: [PATCH 10/13] make manifests --- ...scaling.mercari.com_scheduledscalings.yaml | 41 +++++++------------ ...duledscalings.autoscaling.mercari.com.yaml | 28 +++---------- ...duledscalings.autoscaling.mercari.com.yaml | 28 +++---------- 3 files changed, 27 insertions(+), 70 deletions(-) diff --git a/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml b/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml index c2ff01fd..de780d58 100644 --- a/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml +++ b/config/crd/bases/autoscaling.mercari.com_scheduledscalings.yaml @@ -35,27 +35,32 @@ spec: description: ScheduledScalingSpec defines the desired state of ScheduledScaling properties: schedule: - description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + description: / Schedule RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" properties: finishAt: description: end of schedule type: string startAt: - description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + description: / RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" start of schedule type: string type: object strategy: - description: Currently only static, might implement others(?) + description: Strategy describes how this ScheduledScaling scales the + target workload. Currently, it only supports the static strategy. properties: static: - description: Resource scaling requirements + description: Resource scaling requirements Static strategy receives + the static value of the replica number and resource requests + that users want to give to Pods during this ScheduledScaling + is valid. This field is optional for the future when we add + another strategy here though, until then this strategy is the + only supported strategy you must set this. properties: minAllocatedResourcesomitempty: - description: Resources requested per container + description: MinAllowedResources means the minimum resource + requests that Tortoise gives to each container. items: - description: Not sure if I need this here, duplicated code - from tortoise types properties: containerName: description: ContainerName is the name of target container. @@ -76,34 +81,18 @@ spec: type: object type: array minimumMinReplica: - description: Min replicas to be deployed on schedule + description: MinimumMinReplicas means the minimum MinReplicas + that Tortoise gives to HPA during this ScheduledScaling + is valid. type: integer type: object type: object targetRefs: description: TargetRef is the targets that need to be scheduled properties: - scaleTargetRef: - description: ScaleTargetRef is the target of scaling. It should - be the same as the target of HPA. - properties: - apiVersion: - description: apiVersion is the API version of the referent - type: string - kind: - description: 'kind is the kind of the referent; More info: - https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - name: - description: 'name is the name of the referent; More info: - https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - type: object tortoiseName: description: Tortoise to be targeted for scheduled scaling type: string - required: - - scaleTargetRef type: object required: - schedule diff --git a/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml b/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml index e5b17302..1690afd6 100644 --- a/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml +++ b/manifests/crd/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml @@ -30,25 +30,24 @@ spec: description: ScheduledScalingSpec defines the desired state of ScheduledScaling properties: schedule: - description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + description: / Schedule RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" properties: finishAt: description: end of schedule type: string startAt: - description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule + description: / RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" start of schedule type: string type: object strategy: - description: Currently only static, might implement others(?) + description: Strategy describes how this ScheduledScaling scales the target workload. Currently, it only supports the static strategy. properties: static: - description: Resource scaling requirements + description: Resource scaling requirements Static strategy receives the static value of the replica number and resource requests that users want to give to Pods during this ScheduledScaling is valid. This field is optional for the future when we add another strategy here though, until then this strategy is the only supported strategy you must set this. properties: minAllocatedResourcesomitempty: - description: Resources requested per container + description: MinAllowedResources means the minimum resource requests that Tortoise gives to each container. items: - description: Not sure if I need this here, duplicated code from tortoise types properties: containerName: description: ContainerName is the name of target container. @@ -68,31 +67,16 @@ spec: type: object type: array minimumMinReplica: - description: Min replicas to be deployed on schedule + description: MinimumMinReplicas means the minimum MinReplicas that Tortoise gives to HPA during this ScheduledScaling is valid. type: integer type: object type: object targetRefs: description: TargetRef is the targets that need to be scheduled properties: - scaleTargetRef: - description: ScaleTargetRef is the target of scaling. It should be the same as the target of HPA. - properties: - apiVersion: - description: apiVersion is the API version of the referent - type: string - kind: - description: 'kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - name: - description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - type: object tortoiseName: description: Tortoise to be targeted for scheduled scaling type: string - required: - - scaleTargetRef type: object required: - schedule diff --git a/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml b/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml index e5b17302..1690afd6 100644 --- a/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml +++ b/manifests/default/apiextensions.k8s.io_v1_customresourcedefinition_scheduledscalings.autoscaling.mercari.com.yaml @@ -30,25 +30,24 @@ spec: description: ScheduledScalingSpec defines the desired state of ScheduledScaling properties: schedule: - description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + description: / Schedule RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" properties: finishAt: description: end of schedule type: string startAt: - description: / The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. start of schedule + description: / RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" start of schedule type: string type: object strategy: - description: Currently only static, might implement others(?) + description: Strategy describes how this ScheduledScaling scales the target workload. Currently, it only supports the static strategy. properties: static: - description: Resource scaling requirements + description: Resource scaling requirements Static strategy receives the static value of the replica number and resource requests that users want to give to Pods during this ScheduledScaling is valid. This field is optional for the future when we add another strategy here though, until then this strategy is the only supported strategy you must set this. properties: minAllocatedResourcesomitempty: - description: Resources requested per container + description: MinAllowedResources means the minimum resource requests that Tortoise gives to each container. items: - description: Not sure if I need this here, duplicated code from tortoise types properties: containerName: description: ContainerName is the name of target container. @@ -68,31 +67,16 @@ spec: type: object type: array minimumMinReplica: - description: Min replicas to be deployed on schedule + description: MinimumMinReplicas means the minimum MinReplicas that Tortoise gives to HPA during this ScheduledScaling is valid. type: integer type: object type: object targetRefs: description: TargetRef is the targets that need to be scheduled properties: - scaleTargetRef: - description: ScaleTargetRef is the target of scaling. It should be the same as the target of HPA. - properties: - apiVersion: - description: apiVersion is the API version of the referent - type: string - kind: - description: 'kind is the kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - name: - description: 'name is the name of the referent; More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' - type: string - type: object tortoiseName: description: Tortoise to be targeted for scheduled scaling type: string - required: - - scaleTargetRef type: object required: - schedule From 045cd29f677dbccb5cca0c17065765e676dbd588 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Wed, 6 Mar 2024 13:07:49 +0900 Subject: [PATCH 11/13] lint --- api/v1alpha1/scheduledscaling_types.go | 3 +- api/v1alpha1/zz_generated.deepcopy.go | 99 +++++++++++++++++++++++++- go.mod | 1 - go.sum | 14 ---- 4 files changed, 100 insertions(+), 17 deletions(-) diff --git a/api/v1alpha1/scheduledscaling_types.go b/api/v1alpha1/scheduledscaling_types.go index 8961f224..027e1440 100644 --- a/api/v1alpha1/scheduledscaling_types.go +++ b/api/v1alpha1/scheduledscaling_types.go @@ -26,8 +26,9 @@ SOFTWARE. package v1alpha1 import ( - autoscalingv1beta3 "github.com/mercari/tortoise/api/v1beta3" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + autoscalingv1beta3 "github.com/mercari/tortoise/api/v1beta3" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 3f47d9c9..733d24fc 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -31,14 +31,41 @@ package v1alpha1 import ( runtime "k8s.io/apimachinery/pkg/runtime" + + "github.com/mercari/tortoise/api/v1beta3" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Schedule) DeepCopyInto(out *Schedule) { + *out = *in + if in.StartAt != nil { + in, out := &in.StartAt, &out.StartAt + *out = new(string) + **out = **in + } + if in.FinishAt != nil { + in, out := &in.FinishAt, &out.FinishAt + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Schedule. +func (in *Schedule) DeepCopy() *Schedule { + if in == nil { + return nil + } + out := new(Schedule) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScheduledScaling) DeepCopyInto(out *ScheduledScaling) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status } @@ -95,6 +122,9 @@ func (in *ScheduledScalingList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScheduledScalingSpec) DeepCopyInto(out *ScheduledScalingSpec) { *out = *in + in.Schedule.DeepCopyInto(&out.Schedule) + in.TargetRefs.DeepCopyInto(&out.TargetRefs) + in.Strategy.DeepCopyInto(&out.Strategy) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledScalingSpec. @@ -121,3 +151,70 @@ func (in *ScheduledScalingStatus) DeepCopy() *ScheduledScalingStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Static) DeepCopyInto(out *Static) { + *out = *in + if in.MinimumMinReplicas != nil { + in, out := &in.MinimumMinReplicas, &out.MinimumMinReplicas + *out = new(int) + **out = **in + } + if in.MinAllocatedResources != nil { + in, out := &in.MinAllocatedResources, &out.MinAllocatedResources + *out = make([]v1beta3.ContainerResourceRequests, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Static. +func (in *Static) DeepCopy() *Static { + if in == nil { + return nil + } + out := new(Static) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Strategy) DeepCopyInto(out *Strategy) { + *out = *in + if in.Static != nil { + in, out := &in.Static, &out.Static + *out = new(Static) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Strategy. +func (in *Strategy) DeepCopy() *Strategy { + if in == nil { + return nil + } + out := new(Strategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetRefs) DeepCopyInto(out *TargetRefs) { + *out = *in + if in.TortoiseName != nil { + in, out := &in.TortoiseName, &out.TortoiseName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetRefs. +func (in *TargetRefs) DeepCopy() *TargetRefs { + if in == nil { + return nil + } + out := new(TargetRefs) + in.DeepCopyInto(out) + return out +} diff --git a/go.mod b/go.mod index 04c8d57c..b8c99451 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,6 @@ require ( github.com/stretchr/testify v1.8.3 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.16.0 // indirect golang.org/x/net v0.22.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/sys v0.18.0 // indirect diff --git a/go.sum b/go.sum index 9562aee4..ff8cef63 100644 --- a/go.sum +++ b/go.sum @@ -135,10 +135,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -146,8 +142,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= @@ -165,20 +159,14 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= @@ -189,8 +177,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From bff5b462e9d7d3a9598264985071f88fb561170e Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Mon, 15 Apr 2024 17:53:06 +0900 Subject: [PATCH 12/13] fix comment --- api/v1alpha1/scheduledscaling_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1alpha1/scheduledscaling_types.go b/api/v1alpha1/scheduledscaling_types.go index 027e1440..3d0f29e3 100644 --- a/api/v1alpha1/scheduledscaling_types.go +++ b/api/v1alpha1/scheduledscaling_types.go @@ -89,7 +89,7 @@ type TargetRefs struct { type Schedule struct { /// RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" // start of schedule - StartAt *string `json:"startAt,omitempty" protobuf:"bytes,1,opt,name=startAt"` + StartAt *string `json:"startAt,omitempty" protobuf:"bytes,1,name=startAt"` // end of schedule FinishAt *string `json:"finishAt,omitempty" protobuf:"bytes,2,name=finishAt"` } From 48cdfa13b367ba013c4b4ed07e1c71556c02a094 Mon Sep 17 00:00:00 2001 From: randytqwjp Date: Fri, 26 Apr 2024 05:01:59 +0900 Subject: [PATCH 13/13] fix comment --- api/v1alpha1/scheduledscaling_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/scheduledscaling_types.go b/api/v1alpha1/scheduledscaling_types.go index 3d0f29e3..0cff0502 100644 --- a/api/v1alpha1/scheduledscaling_types.go +++ b/api/v1alpha1/scheduledscaling_types.go @@ -89,9 +89,9 @@ type TargetRefs struct { type Schedule struct { /// RFC3339 format e.g., "2006-01-02T15:04:05Z09:00" // start of schedule - StartAt *string `json:"startAt,omitempty" protobuf:"bytes,1,name=startAt"` + StartAt *string `json:"startAt" protobuf:"bytes,1,name=startAt"` // end of schedule - FinishAt *string `json:"finishAt,omitempty" protobuf:"bytes,2,name=finishAt"` + FinishAt *string `json:"finishAt" protobuf:"bytes,2,name=finishAt"` } type Strategy struct {