From 3815ec64365b613b09301754dd32d0b27bd51dfb Mon Sep 17 00:00:00 2001 From: charlie Date: Sat, 19 Aug 2023 15:28:25 +0800 Subject: [PATCH] feat: support batch deploy --- .../controller/moduledeployment_controller.go | 105 ++++++++++++++++-- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/module-controller/internal/controller/moduledeployment_controller.go b/module-controller/internal/controller/moduledeployment_controller.go index 730867a39..4eb971488 100644 --- a/module-controller/internal/controller/moduledeployment_controller.go +++ b/module-controller/internal/controller/moduledeployment_controller.go @@ -19,9 +19,9 @@ package controller import ( "context" "fmt" - moduledeploymentv1alpha1 "github.com/sofastack/sofa-serverless/api/v1alpha1" - "github.com/sofastack/sofa-serverless/internal/controller/utils" + v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -31,6 +31,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" + + moduledeploymentv1alpha1 "github.com/sofastack/sofa-serverless/api/v1alpha1" + "github.com/sofastack/sofa-serverless/internal/controller/utils" ) const ( @@ -142,17 +145,53 @@ func (r *ModuleDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Req } } + if moduleDeployment.Spec.Pause { + log.Log.Info(fmt.Sprintf("the moduleDeployment(%v) is paused", moduleDeployment.Name)) + return ctrl.Result{}, nil + } + // create moduleReplicaSet moduleReplicaSet, err := r.createOrGetModuleReplicas(moduleDeployment) if err != nil { return ctrl.Result{}, err } - // update moduleReplicaSet - err = r.updateModuleReplicas(moduleDeployment, moduleReplicaSet) - if err != nil { - return ctrl.Result{}, err + if moduleDeployment.Status.ReleaseStatus == nil { + moduleDeployment.Status.ReleaseStatus = &moduledeploymentv1alpha1.ReleaseStatus{ + CurrentBatch: 0, + Progress: moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressInit, + LastTransitionTime: metav1.Now(), + } } + releaseStatus := moduleDeployment.Status.ReleaseStatus + switch releaseStatus.Progress { + case moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressInit: + moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting + if err := r.Status().Update(ctx, moduleDeployment); err != nil { + return ctrl.Result{}, err + } + case moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting: + // update moduleReplicaSet + if err := r.updateModuleReplicaSet(moduleDeployment, moduleReplicaSet); err != nil { + return ctrl.Result{}, err + } + case moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressWaitingForConfirmation: + moduleDeployment.Spec.Pause = true + moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressPaused + if err := r.Status().Update(ctx, moduleDeployment); err != nil { + return ctrl.Result{}, err + } + case moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressPaused: + if !moduleDeployment.Spec.Pause { + moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting + if err := r.Status().Update(ctx, moduleDeployment); err != nil { + return ctrl.Result{}, err + } + } + case moduledeploymentv1alpha1.CafeDeploymentReleaseProgressCompleted: + // todo + } + return ctrl.Result{}, nil } @@ -196,11 +235,10 @@ func (r *ModuleDeploymentReconciler) createOrGetModuleReplicas(moduleDeployment return moduleReplicaSet, err } -func (r *ModuleDeploymentReconciler) updateModuleReplicas(moduleDeployment *moduledeploymentv1alpha1.ModuleDeployment, moduleReplicaSet *moduledeploymentv1alpha1.ModuleReplicaSet) error { - moduleSpec := moduleDeployment.Spec.Template.Spec - if moduleDeployment.Spec.Replicas != moduleReplicaSet.Spec.Replicas || isModuleChanges(moduleSpec.Module, moduleReplicaSet.Spec.Template.Spec.Module) { +func (r *ModuleDeploymentReconciler) updateModuleReplicas(moduleReplicaSet *moduledeploymentv1alpha1.ModuleReplicaSet, replicas int32, moduleSpec moduledeploymentv1alpha1.ModuleSpec) error { + if replicas != moduleReplicaSet.Spec.Replicas || isModuleChanges(moduleSpec.Module, moduleReplicaSet.Spec.Template.Spec.Module) { log.Log.Info("prepare to update moduleReplicaSet", "moduleReplicaSetName", moduleReplicaSet.Name) - moduleReplicaSet.Spec.Replicas = moduleDeployment.Spec.Replicas + moduleReplicaSet.Spec.Replicas = replicas moduleReplicaSet.Spec.Template.Spec.Module = moduleSpec.Module err := r.Client.Update(context.TODO(), moduleReplicaSet) if err != nil { @@ -212,6 +250,53 @@ func (r *ModuleDeploymentReconciler) updateModuleReplicas(moduleDeployment *modu return nil } +func (r *ModuleDeploymentReconciler) updateModuleReplicaSet(moduleDeployment *moduledeploymentv1alpha1.ModuleDeployment, moduleReplicaSet *moduledeploymentv1alpha1.ModuleReplicaSet) error { + var ( + ctx = context.TODO() + + batchCount = moduleDeployment.Spec.Strategy.BatchCount + curBatch = moduleDeployment.Status.ReleaseStatus.CurrentBatch + isBatchDeploy = batchCount > 1 + ) + + if curBatch >= batchCount { + moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.CafeDeploymentReleaseProgressCompleted + moduleDeployment.Status.ReleaseStatus.LastTransitionTime = metav1.Now() + moduleDeployment.Status.Conditions = append(moduleDeployment.Status.Conditions, moduledeploymentv1alpha1.ModuleDeploymentCondition{ + Type: moduledeploymentv1alpha1.DeploymentAvailable, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Message: "deployment release progress completed", + }) + return r.Status().Update(ctx, moduleDeployment) + } + + replicas := moduleDeployment.Spec.Replicas + if curBatch != batchCount-1 { // is not the last batch + replicas = (curBatch + 1) * (moduleDeployment.Spec.Replicas / batchCount) + } + + err := r.updateModuleReplicas(moduleReplicaSet, replicas, moduleDeployment.Spec.Template.Spec) + if err != nil { + return err + } + + if isBatchDeploy { + moduleDeployment.Status.ReleaseStatus.CurrentBatch += 1 + moduleDeployment.Status.ReleaseStatus.Progress = moduledeploymentv1alpha1.ModuleDeploymentReleaseProgressExecuting + moduleDeployment.Status.ReleaseStatus.LastTransitionTime = metav1.Now() + moduleDeployment.Status.Conditions = append(moduleDeployment.Status.Conditions, moduledeploymentv1alpha1.ModuleDeploymentCondition{ + Type: moduledeploymentv1alpha1.DeploymentProgressing, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Message: fmt.Sprintf("deployment release: curbatch %v, batchCount %v", curBatch, batchCount), + }) + return r.Status().Update(ctx, moduleDeployment) + } + + return nil +} + func (r *ModuleDeploymentReconciler) generateModuleReplicas(moduleDeployment *moduledeploymentv1alpha1.ModuleDeployment, deployment *v1.Deployment) *moduledeploymentv1alpha1.ModuleReplicaSet { newLabels := moduleDeployment.Labels newLabels[moduledeploymentv1alpha1.ModuleNameLabel] = moduleDeployment.Spec.Template.Spec.Module.Name