diff --git a/docs/examples/deployment-rollout/README.md b/docs/examples/deployment-rollout/README.md index 2904c600d..89c712923 100644 --- a/docs/examples/deployment-rollout/README.md +++ b/docs/examples/deployment-rollout/README.md @@ -18,13 +18,11 @@ Wait for the application's status to be "running" ```shell kubectl apply -f docs/examples/deployment-rollout/app-source-prep.yaml ``` -Wait for the applicationConfiguration "test-rolling-v1" `Rolling Status` to be "RollingTemplated" 4. Modify the application image and apply ```shell kubectl apply -f docs/examples/deployment-rollout/app-target.yaml ``` -Wait for the applicationConfiguration "test-rolling-v2" `Rolling Status` to be "RollingTemplated" 5. Mark the application as normal ```shell @@ -33,14 +31,14 @@ kubectl apply -f docs/examples/deployment-rollout/app-target-done.yaml 6. Apply the application deployment with pause ```shell -kubectl apply -f docs/examples/deployment-rollout/app-deploy-pause.yaml +kubectl apply -f docs/examples/deployment-rollout/app-rollout-pause.yaml ``` -Check the status of the ApplicationDeployment and see the step by step rolling out. +Check the status of the ApplicationRollout and see the step by step rolling out. This rollout will pause after the second batch. 7. Apply the application deployment that completes the rollout ```shell -kubectl apply -f docs/examples/deployment-rollout/app-deploy-finish.yaml +kubectl apply -f docs/examples/deployment-rollout/app-rollout-finish.yaml ``` -Check the status of the ApplicationDeployment and see the rollout completes, and the -applicationDeployment's "Rolling State" becomes `rolloutSucceed` \ No newline at end of file +Check the status of the ApplicationRollout and see the rollout completes, and the +ApplicationRollout's "Rolling State" becomes `rolloutSucceed` \ No newline at end of file diff --git a/docs/examples/deployment-rollout/app-deploy-finish.yaml b/docs/examples/deployment-rollout/app-rollout-finish.yaml similarity index 100% rename from docs/examples/deployment-rollout/app-deploy-finish.yaml rename to docs/examples/deployment-rollout/app-rollout-finish.yaml diff --git a/docs/examples/deployment-rollout/app-deploy-pause.yaml b/docs/examples/deployment-rollout/app-rollout-pause.yaml similarity index 100% rename from docs/examples/deployment-rollout/app-deploy-pause.yaml rename to docs/examples/deployment-rollout/app-rollout-pause.yaml diff --git a/docs/examples/rollout/README.md b/docs/examples/rollout/README.md index 698877e70..327958ff7 100644 --- a/docs/examples/rollout/README.md +++ b/docs/examples/rollout/README.md @@ -1,50 +1,43 @@ # Rollout Example -Here is an example of how to rollout an application with a component of type CloneSet. + +Here is an example of how to rollout an application with a component of type CloneSet. ## Install Kruise + ```shell helm install kruise https://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz ``` ## Rollout steps + 1. Install CloneSet based workloadDefinition + ```shell kubectl apply -f docs/examples/rollout/clonesetDefinition.yaml ``` -2. Apply an application -```shell -kubectl apply -f docs/examples/rollout/app-source.yaml -``` -Wait for the application's status to be "running" - -3. Prepare the application for rolling out +2. Apply an application for rolling out ```shell kubectl apply -f docs/examples/rollout/app-source-prep.yaml ``` -Wait for the applicationConfiguration "test-rolling-v1" `Rolling Status` to be "RollingTemplated" -4. Modify the application image and apply +3. Modify the application image and apply ```shell kubectl apply -f docs/examples/rollout/app-target.yaml ``` -Wait for the applicationConfiguration "test-rolling-v2" `Rolling Status` to be "RollingTemplated" -5. Mark the application as normal +4. Apply the application rollout that stops at the second batch and mrk the application as normal ```shell +kubectl apply -f docs/examples/rollout/app-rollout-pause.yaml kubectl apply -f docs/examples/rollout/app-target-done.yaml ``` +Check the status of the ApplicationRollout and see the step by step rolling out. This rollout +will pause after the second batch. -6. Apply the application deployment with pause +5. Apply the application rollout that completes the rollout ```shell -kubectl apply -f docs/examples/rollout/app-deploy-pause.yaml +kubectl apply -f docs/examples/rollout/app-rollout-finish.yaml ``` -Check the status of the ApplicationDeployment and see the step by step rolling out. -This rollout will pause after the second batch. -7. Apply the application deployment that completes the rollout -```shell -kubectl apply -f docs/examples/rollout/app-deploy-finish.yaml -``` -Check the status of the ApplicationDeployment and see the rollout completes, and the -applicationDeployment's "Rolling State" becomes `rolloutSucceed` \ No newline at end of file +Check the status of the ApplicationRollout and see the rollout completes, and the +ApplicationRollout's "Rolling State" becomes `rolloutSucceed` \ No newline at end of file diff --git a/docs/examples/rollout/app-deploy-revert.yaml b/docs/examples/rollout/app-deploy-revert.yaml deleted file mode 100644 index 14ff86916..000000000 --- a/docs/examples/rollout/app-deploy-revert.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: core.oam.dev/v1alpha2 -kind: AppRollout -metadata: - name: rolling-test -spec: - # application (revision) reference - targetAppRevisionName: test-rolling-v3 - sourceAppRevisionName: test-rolling-v2 - # HPA reference (optional) - componentList: - - metrics-provider - rolloutPlan: - rolloutStrategy: "IncreaseFirst" - rolloutBatches: - - replicas: 20% - - replicas: 30% - - replicas: 50% \ No newline at end of file diff --git a/docs/examples/rollout/app-deploy-finish.yaml b/docs/examples/rollout/app-rollout-finish.yaml similarity index 100% rename from docs/examples/rollout/app-deploy-finish.yaml rename to docs/examples/rollout/app-rollout-finish.yaml diff --git a/docs/examples/rollout/app-deploy-pause.yaml b/docs/examples/rollout/app-rollout-pause.yaml similarity index 100% rename from docs/examples/rollout/app-deploy-pause.yaml rename to docs/examples/rollout/app-rollout-pause.yaml diff --git a/docs/examples/deployment-rollout/app-deploy-revert.yaml b/docs/examples/rollout/app-rollout-revert.yaml similarity index 100% rename from docs/examples/deployment-rollout/app-deploy-revert.yaml rename to docs/examples/rollout/app-rollout-revert.yaml diff --git a/pkg/controller/common/rollout/workloads/deployment_controller.go b/pkg/controller/common/rollout/workloads/deployment_controller.go index a7ee2c4c8..c4425c25d 100644 --- a/pkg/controller/common/rollout/workloads/deployment_controller.go +++ b/pkg/controller/common/rollout/workloads/deployment_controller.go @@ -170,7 +170,7 @@ func (c *DeploymentController) RolloutOneBatchPods(ctx context.Context) (bool, e klog.InfoS("upgraded one batch", "current batch", c.rolloutStatus.CurrentBatch, "target deployment size", targetSize) c.recorder.Event(c.parentController, event.Normal("Batch Rollout", - fmt.Sprintf("Submitted upgrade quests for batch %d", c.rolloutStatus.CurrentBatch))) + fmt.Sprintf("Finished submiting all upgrade quests for batch %d", c.rolloutStatus.CurrentBatch))) c.rolloutStatus.UpgradedReplicas = targetSize return true, nil } @@ -330,21 +330,24 @@ func (c *DeploymentController) claimDeployment(ctx context.Context, deploy *apps } func (c *DeploymentController) rolloutBatchFirstHalf(ctx context.Context, rolloutStrategy v1alpha1.RolloutStrategyType) error { - var err error if rolloutStrategy == v1alpha1.IncreaseFirstRolloutStrategyType { // set the target replica first which should increase its size - if err = c.patchDeployment(ctx, c.calculateCurrentTarget(c.rolloutStatus.RolloutTargetTotalSize), + if err := c.patchDeployment(ctx, c.calculateCurrentTarget(c.rolloutStatus.RolloutTargetTotalSize), &c.targetDeploy); err != nil { c.rolloutStatus.RolloutRetry(err.Error()) } + c.recorder.Event(c.parentController, event.Normal("Batch Rollout", + fmt.Sprintf("Submitted the increase part of upgrade quests for batch %d", c.rolloutStatus.CurrentBatch))) return nil } if rolloutStrategy == v1alpha1.DecreaseFirstRolloutStrategyType { // set the source replicas first which should shrink its size - if err = c.patchDeployment(ctx, c.calculateCurrentSource(c.rolloutStatus.RolloutTargetTotalSize), + if err := c.patchDeployment(ctx, c.calculateCurrentSource(c.rolloutStatus.RolloutTargetTotalSize), &c.sourceDeploy); err != nil { c.rolloutStatus.RolloutRetry(err.Error()) } + c.recorder.Event(c.parentController, event.Normal("Batch Rollout", + fmt.Sprintf("Submitted the decrease part of upgrade quests for batch %d", c.rolloutStatus.CurrentBatch))) return nil } return fmt.Errorf("encountered an unknown rolloutStrategy `%s`", rolloutStrategy) diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go index c9ae22adf..ec8804f82 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go @@ -74,29 +74,67 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (res reconcile.Result, retErr e // TODO: check if the target/source has changed r.handleFinalizer(&appRollout) + targetAppName := appRollout.Spec.TargetAppRevisionName + sourceAppName := appRollout.Spec.SourceAppRevisionName ctx = oamutil.SetNamespaceInCtx(ctx, appRollout.Namespace) + if appRollout.Status.RollingState == v1alpha1.RolloutSucceedState || + appRollout.Status.RollingState == v1alpha1.RolloutFailedState { + if appRollout.Status.LastUpgradedTargetAppRevision == appRollout.Spec.TargetAppRevisionName && + appRollout.Status.LastSourceAppRevision == appRollout.Spec.SourceAppRevisionName { + klog.InfoS("rollout terminated, no need to reconcile", "source", sourceAppName, + "target", targetAppName) + return ctrl.Result{}, nil + } + klog.InfoS("rollout target changed, restart the rollout", "source", sourceAppName, + "target", targetAppName) + appRollout.Status.StateTransition(v1alpha1.WorkloadModifiedEvent) + } + // Get the target application var targetApp oamv1alpha2.ApplicationConfiguration sourceApp := &oamv1alpha2.ApplicationConfiguration{} - targetAppName := appRollout.Spec.TargetAppRevisionName if err := r.Get(ctx, ktypes.NamespacedName{Namespace: req.Namespace, Name: targetAppName}, &targetApp); err != nil { - klog.ErrorS(err, "cannot locate target application", "target application", + if apierrors.IsNotFound(err) { + klog.ErrorS(err, "target application revision not exist", "target application revision", + klog.KRef(req.Namespace, targetAppName)) + return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + } + klog.ErrorS(err, "cannot locate target application revision", "target application revision", klog.KRef(req.Namespace, targetAppName)) return ctrl.Result{}, err } - + // check if the app is templated + if targetApp.Status.RollingStatus != oamv1alpha2.RollingTemplated { + klog.Info("target app revision is not ready for rolling yet", "application revision", targetAppName) + r.record.Event(&appRollout, event.Normal("Rollout Paused", + "target app revision is not ready for rolling yet", "application revision", targetAppName)) + return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + } // Get the source application - sourceAppName := appRollout.Spec.SourceAppRevisionName if sourceAppName == "" { klog.Info("source app fields not filled, we assume it is deployed for the first time") sourceApp = nil - } else if err := r.Get(ctx, ktypes.NamespacedName{Namespace: req.Namespace, Name: sourceAppName}, sourceApp); err != nil { - klog.ErrorS(err, "cannot locate source application", "source application", klog.KRef(req.Namespace, - sourceAppName)) - return ctrl.Result{}, err + } else { + if err := r.Get(ctx, ktypes.NamespacedName{Namespace: req.Namespace, Name: sourceAppName}, sourceApp); err != nil { + if apierrors.IsNotFound(err) { + klog.ErrorS(err, "target application revision not exist", "source application revision", + klog.KRef(req.Namespace, sourceAppName)) + return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + } + klog.ErrorS(err, "cannot locate source application revision", "source application revision", + klog.KRef(req.Namespace, sourceAppName)) + return ctrl.Result{}, err + } + // check if the app is templated + if sourceApp.Status.RollingStatus != oamv1alpha2.RollingTemplated { + klog.Info("source app revision is not ready for rolling yet", "application revision", sourceAppName) + r.record.Event(&appRollout, event.Normal("Rollout Paused", + "source app revision is not ready for rolling yet", "application revision", sourceAppName)) + return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + } } targetWorkload, sourceWorkload, err := r.extractWorkloads(ctx, appRollout.Spec.ComponentList, &targetApp, sourceApp) @@ -112,19 +150,6 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (res reconcile.Result, retErr e klog.InfoS("get the source workload we need to work on", "sourceWorkload", klog.KObj(sourceWorkload)) } - if appRollout.Status.RollingState == v1alpha1.RolloutSucceedState || - appRollout.Status.RollingState == v1alpha1.RolloutFailedState { - if appRollout.Status.LastUpgradedTargetAppRevision == appRollout.Spec.TargetAppRevisionName && - appRollout.Status.LastSourceAppRevision == appRollout.Spec.SourceAppRevisionName { - klog.InfoS("rollout terminated, no need to reconcile", "source", sourceAppName, - "target", targetAppName) - return ctrl.Result{}, nil - } - klog.InfoS("rollout target changed, restart the rollout", "source", sourceAppName, - "target", targetAppName) - appRollout.Status.StateTransition(v1alpha1.WorkloadModifiedEvent) - } - // reconcile the rollout part of the spec given the target and source workload rolloutPlanController := rollout.NewRolloutPlanController(r, &appRollout, r.record, &appRollout.Spec.RolloutPlan, &appRollout.Status.RolloutStatus, targetWorkload, sourceWorkload)