From f94ef64e2ce2282de0b4294dbd4ea59430353fb6 Mon Sep 17 00:00:00 2001 From: charlie Date: Wed, 27 Sep 2023 16:14:56 +0800 Subject: [PATCH] fix: grayTime strategy --- .../api/v1alpha1/moduledeployment_types.go | 2 + .../api/v1alpha1/zz_generated.deepcopy.go | 1 + ...rverless.alipay.com_moduledeployments.yaml | 3 + ...nt_v1alpha1_moduledeployment_provider.yaml | 3 +- .../controller/moduledeployment_controller.go | 6 +- .../moduledeployment_controller_suit_test.go | 101 +++++++----------- 6 files changed, 49 insertions(+), 67 deletions(-) diff --git a/module-controller/api/v1alpha1/moduledeployment_types.go b/module-controller/api/v1alpha1/moduledeployment_types.go index 95f47e6e1..cf78ae296 100644 --- a/module-controller/api/v1alpha1/moduledeployment_types.go +++ b/module-controller/api/v1alpha1/moduledeployment_types.go @@ -81,6 +81,8 @@ type ReleaseStatus struct { // Last time the release transitioned from one status to another. LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + + NextReconcileTime metav1.Time `json:"nextReconcileTime,omitempty"` } type ModuleDeploymentCondition struct { diff --git a/module-controller/api/v1alpha1/zz_generated.deepcopy.go b/module-controller/api/v1alpha1/zz_generated.deepcopy.go index 3fcfe8b62..0be76c3d3 100644 --- a/module-controller/api/v1alpha1/zz_generated.deepcopy.go +++ b/module-controller/api/v1alpha1/zz_generated.deepcopy.go @@ -437,6 +437,7 @@ func (in *ModuleTemplateSpec) DeepCopy() *ModuleTemplateSpec { func (in *ReleaseStatus) DeepCopyInto(out *ReleaseStatus) { *out = *in in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + in.NextReconcileTime.DeepCopyInto(&out.NextReconcileTime) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReleaseStatus. diff --git a/module-controller/config/crd/bases/serverless.alipay.com_moduledeployments.yaml b/module-controller/config/crd/bases/serverless.alipay.com_moduledeployments.yaml index bce62898c..8bac35f67 100644 --- a/module-controller/config/crd/bases/serverless.alipay.com_moduledeployments.yaml +++ b/module-controller/config/crd/bases/serverless.alipay.com_moduledeployments.yaml @@ -220,6 +220,9 @@ spec: to another. format: date-time type: string + nextReconcileTime: + format: date-time + type: string progress: description: The phase current release reach type: string diff --git a/module-controller/config/samples/module-deployment_v1alpha1_moduledeployment_provider.yaml b/module-controller/config/samples/module-deployment_v1alpha1_moduledeployment_provider.yaml index 2ae5c59d4..9c4cf9a4d 100644 --- a/module-controller/config/samples/module-deployment_v1alpha1_moduledeployment_provider.yaml +++ b/module-controller/config/samples/module-deployment_v1alpha1_moduledeployment_provider.yaml @@ -18,7 +18,8 @@ spec: url: http://serverless-opensource.oss-cn-shanghai.aliyuncs.com/module-packages/stable/dynamic-provider-1.0.0-ark-biz.jar replicas: 1 operationStrategy: - needConfirm: true + needConfirm: false + grayTimeBetweenBatchSeconds: 120 useBeta: false batchCount: 1 schedulingStrategy: diff --git a/module-controller/internal/controller/moduledeployment_controller.go b/module-controller/internal/controller/moduledeployment_controller.go index c22508004..bbd399a2f 100644 --- a/module-controller/internal/controller/moduledeployment_controller.go +++ b/module-controller/internal/controller/moduledeployment_controller.go @@ -130,7 +130,7 @@ func (r *ModuleDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, err } case moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressPaused: - if !moduleDeployment.Spec.Pause { + if !moduleDeployment.Spec.Pause && time.Since(moduleDeployment.Status.ReleaseStatus.NextReconcileTime.Time) >= 0 { moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting if err := r.Status().Update(ctx, moduleDeployment); err != nil { return ctrl.Result{}, err @@ -363,8 +363,9 @@ func (r *ModuleDeploymentReconciler) updateModuleReplicaSet(moduleDeployment *mo return ctrl.Result{}, err } + now := metav1.Now() moduleDeployment.Status.ReleaseStatus.CurrentBatch += 1 - moduleDeployment.Status.ReleaseStatus.LastTransitionTime = metav1.Now() + moduleDeployment.Status.ReleaseStatus.LastTransitionTime = now moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting var grayTime int @@ -375,6 +376,7 @@ func (r *ModuleDeploymentReconciler) updateModuleReplicaSet(moduleDeployment *mo if curBatch == batchCount { moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting } else { + moduleDeployment.Status.ReleaseStatus.NextReconcileTime = metav1.NewTime(now.Add(time.Duration(grayTime) * time.Second)) moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressPaused } } diff --git a/module-controller/internal/controller/moduledeployment_controller_suit_test.go b/module-controller/internal/controller/moduledeployment_controller_suit_test.go index 1562dbb01..a17f93d93 100644 --- a/module-controller/internal/controller/moduledeployment_controller_suit_test.go +++ b/module-controller/internal/controller/moduledeployment_controller_suit_test.go @@ -99,42 +99,9 @@ var _ = Describe("ModuleDeployment Controller", func() { Expect(k8sClient.Update(context.TODO(), &newModuleDeployment)).Should(Succeed()) Eventually(func() bool { - set := map[string]string{ - label.ModuleDeploymentLabel: moduleDeployment.Name, - } - replicaSetList := &moduledeploymentv1alpha1.ModuleReplicaSetList{} - err := k8sClient.List(context.TODO(), replicaSetList, &client.ListOptions{LabelSelector: labels.SelectorFromSet(set)}, client.InNamespace(moduleDeployment.Namespace)) - if err != nil || len(replicaSetList.Items) == 0 { - return false - } - - maxVersion := 0 - var newRS *moduledeploymentv1alpha1.ModuleReplicaSet - for i := 0; i < len(replicaSetList.Items); i++ { - version, err := getRevision(&replicaSetList.Items[i]) - if err != nil { - return false - } - if version > maxVersion { - maxVersion = version - newRS = &replicaSetList.Items[i] - } - } - - // the replicas of old replicaset must be zero - for i := 0; i < len(replicaSetList.Items); i++ { - if version, _ := getRevision(&replicaSetList.Items[i]); version != maxVersion { - if replicaSetList.Items[i].Spec.Replicas != 0 { - return false - } - } - } - - // the replicas of new replicaset must be equal to newModuleDeployment - return newRS != nil && - newRS.Spec.Template.Spec.Module.Version == "1.0.1" && - newRS.Status.Replicas == newRS.Spec.Replicas && - newRS.Status.Replicas == newModuleDeployment.Spec.Replicas + return checkModuleDeploymentReplicas( + types.NamespacedName{Name: moduleDeploymentName, Namespace: namespace}, + newModuleDeployment.Spec.Replicas) }, timeout, interval).Should(BeTrue()) }) }) @@ -193,7 +160,6 @@ var _ = Describe("ModuleDeployment Controller", func() { }) Context("test batchConfirm strategy", func() { - namespace := "default" moduleDeploymentName := "module-deployment-test-for-batch-confirm" nn := types.NamespacedName{Namespace: namespace, Name: moduleDeploymentName} moduleDeployment := prepareModuleDeployment(namespace, moduleDeploymentName) @@ -203,7 +169,7 @@ var _ = Describe("ModuleDeployment Controller", func() { It("0. prepare 2 pods", func() { Eventually(func() bool { - pod := preparePod("fake-pod-3") + pod := preparePod(namespace, "fake-pod-3") pod.Labels[fmt.Sprintf("%s-%s", label.ModuleNameLabel, "dynamic-provider")] = "1.0.0" if err := k8sClient.Create(context.TODO(), &pod); err != nil { return false @@ -230,32 +196,10 @@ var _ = Describe("ModuleDeployment Controller", func() { return false } - set := map[string]string{ - label.ModuleDeploymentLabel: moduleDeployment.Name, - } - replicaSetList := &moduledeploymentv1alpha1.ModuleReplicaSetList{} - err := k8sClient.List(context.TODO(), replicaSetList, &client.ListOptions{LabelSelector: labels.SelectorFromSet(set)}, client.InNamespace(moduleDeployment.Namespace)) - if err != nil || len(replicaSetList.Items) == 0 { - return false - } - - maxVersion := 0 - var newRS *moduledeploymentv1alpha1.ModuleReplicaSet - for i := 0; i < len(replicaSetList.Items); i++ { - version, err := getRevision(&replicaSetList.Items[i]) - if err != nil { - return false - } - if version > maxVersion { - maxVersion = version - newRS = &replicaSetList.Items[i] - } - } - - // the replicas of new replicaset must be equal to newModuleDeployment - return newRS != nil && - newRS.Status.Replicas == newRS.Spec.Replicas && - newRS.Status.Replicas == 1 + return checkModuleDeploymentReplicas( + types.NamespacedName{ + Name: moduleDeploymentName, + Namespace: moduleDeployment.Namespace}, 1) }, timeout, interval).Should(BeTrue()) }) @@ -311,6 +255,35 @@ var _ = Describe("ModuleDeployment Controller", func() { }) }) +func checkModuleDeploymentReplicas(nn types.NamespacedName, replicas int32) bool { + set := map[string]string{ + label.ModuleDeploymentLabel: nn.Name, + } + replicaSetList := &moduledeploymentv1alpha1.ModuleReplicaSetList{} + err := k8sClient.List(context.TODO(), replicaSetList, &client.ListOptions{LabelSelector: labels.SelectorFromSet(set)}, client.InNamespace(nn.Namespace)) + if err != nil || len(replicaSetList.Items) == 0 { + return false + } + + maxVersion := 0 + var newRS *moduledeploymentv1alpha1.ModuleReplicaSet + for i := 0; i < len(replicaSetList.Items); i++ { + version, err := getRevision(&replicaSetList.Items[i]) + if err != nil { + return false + } + if version > maxVersion { + maxVersion = version + newRS = &replicaSetList.Items[i] + } + } + + // the replicas of new replicaset must be equal to newModuleDeployment + return newRS != nil && + newRS.Status.Replicas == newRS.Spec.Replicas && + newRS.Status.Replicas == replicas +} + func prepareModuleDeployment(namespace, moduleDeploymentName string) v1alpha1.ModuleDeployment { baseDeploymentName := "dynamic-stock-deployment"