From d765df7e1cefcee9cf9aea288777f3769c8c2234 Mon Sep 17 00:00:00 2001 From: shiyan2016 Date: Thu, 5 Jan 2023 17:26:31 +0800 Subject: [PATCH] fix preparingupdate hang when rollback before update Signed-off-by: shiyan2016 --- pkg/controller/cloneset/sync/cloneset_update.go | 15 +++++++++++++-- .../statefulset/stateful_set_control.go | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pkg/controller/cloneset/sync/cloneset_update.go b/pkg/controller/cloneset/sync/cloneset_update.go index 19dd99f85e..c87b4dd38c 100644 --- a/pkg/controller/cloneset/sync/cloneset_update.go +++ b/pkg/controller/cloneset/sync/cloneset_update.go @@ -54,7 +54,7 @@ func (c *realControl) Update(cs *appsv1alpha1.CloneSet, // 1. refresh states for all pods var modified bool for _, pod := range pods { - patchedState, duration, err := c.refreshPodState(cs, coreControl, pod) + patchedState, duration, err := c.refreshPodState(cs, coreControl, pod, updateRevision.Name) if err != nil { return err } else if duration > 0 { @@ -155,7 +155,7 @@ func (c *realControl) Update(cs *appsv1alpha1.CloneSet, return nil } -func (c *realControl) refreshPodState(cs *appsv1alpha1.CloneSet, coreControl clonesetcore.Control, pod *v1.Pod) (bool, time.Duration, error) { +func (c *realControl) refreshPodState(cs *appsv1alpha1.CloneSet, coreControl clonesetcore.Control, pod *v1.Pod, updateRevision string) (bool, time.Duration, error) { opts := coreControl.GetUpdateOptions() opts = inplaceupdate.SetOptionsDefaults(opts) @@ -174,6 +174,17 @@ func (c *realControl) refreshPodState(cs *appsv1alpha1.CloneSet, coreControl clo lifecycle.IsPodAllHooked(cs.Spec.Lifecycle.PreNormal, pod) { state = appspub.LifecycleStateNormal } + case appspub.LifecycleStatePreparingUpdate: + // when pod updated to PreparingUpdate state to wait lifecycle blocker to remove, + // then rollback, do not need update pod inplace since it is the update revision, + // so just update pod lifecycle state. ref: https://github.com/openkruise/kruise/issues/1156 + if clonesetutils.EqualToRevisionHash("", pod, updateRevision) { + if cs.Spec.Lifecycle != nil && !lifecycle.IsPodAllHooked(cs.Spec.Lifecycle.InPlaceUpdate, pod) { + state = appspub.LifecycleStateUpdated + } else { + state = appspub.LifecycleStateNormal + } + } case appspub.LifecycleStateUpdating: if opts.CheckPodUpdateCompleted(pod) == nil { if cs.Spec.Lifecycle != nil && !lifecycle.IsPodAllHooked(cs.Spec.Lifecycle.InPlaceUpdate, pod) { diff --git a/pkg/controller/statefulset/stateful_set_control.go b/pkg/controller/statefulset/stateful_set_control.go index 275cb0d047..426af6bff8 100644 --- a/pkg/controller/statefulset/stateful_set_control.go +++ b/pkg/controller/statefulset/stateful_set_control.go @@ -738,7 +738,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet( // refresh states for all pods var modified bool for _, pod := range pods { - refreshed, duration, err := ssc.refreshPodState(set, pod) + refreshed, duration, err := ssc.refreshPodState(set, pod, updateRevision.Name) if err != nil { return &status, err } else if duration > 0 { @@ -838,7 +838,7 @@ func (ssc *defaultStatefulSetControl) deletePod(set *appsv1beta1.StatefulSet, po return true, nil } -func (ssc *defaultStatefulSetControl) refreshPodState(set *appsv1beta1.StatefulSet, pod *v1.Pod) (bool, time.Duration, error) { +func (ssc *defaultStatefulSetControl) refreshPodState(set *appsv1beta1.StatefulSet, pod *v1.Pod, updateRevision string) (bool, time.Duration, error) { if set.Spec.UpdateStrategy.RollingUpdate == nil { return false, 0, nil } @@ -857,6 +857,17 @@ func (ssc *defaultStatefulSetControl) refreshPodState(set *appsv1beta1.StatefulS var state appspub.LifecycleStateType switch lifecycle.GetPodLifecycleState(pod) { + case appspub.LifecycleStatePreparingUpdate: + // when pod updated to PreparingUpdate state to wait lifecycle blocker to remove, + // then rollback, do not need update pod inplace since it is the update revision, + // so just update pod lifecycle state. ref: https://github.com/openkruise/kruise/issues/1156 + if getPodRevision(pod) == updateRevision { + if set.Spec.Lifecycle != nil && !lifecycle.IsPodAllHooked(set.Spec.Lifecycle.InPlaceUpdate, pod) { + state = appspub.LifecycleStateUpdated + } else { + state = appspub.LifecycleStateNormal + } + } case appspub.LifecycleStateUpdating: if opts.CheckPodUpdateCompleted(pod) == nil { if set.Spec.Lifecycle != nil && !lifecycle.IsPodAllHooked(set.Spec.Lifecycle.InPlaceUpdate, pod) {