@@ -104,34 +104,18 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilder
104104 }
105105
106106 // handle 'RollingUpdate'
107- replicas , maxUnavailable , err := parseReplicasNMaxUnavailable (its . Spec . InstanceUpdateStrategy , len ( oldPodList ) )
107+ rollingUpdateQuota , unavailableQuota , err := r . rollingUpdateQuota (its , oldPodList )
108108 if err != nil {
109109 return kubebuilderx .Continue , err
110110 }
111- currentUnavailable := 0
112- for _ , pod := range oldPodList {
113- if ! intctrlutil .IsPodAvailable (pod , its .Spec .MinReadySeconds ) {
114- currentUnavailable ++
115- }
116- }
117- unavailable := maxUnavailable - currentUnavailable
118111
119- // if it's a roleful InstanceSet, we use updateCount to represent Pods can be updated according to the spec.memberUpdateStrategy.
120- updateCount := len (oldPodList )
121- if len (its .Spec .Roles ) > 0 {
122- plan := NewUpdatePlan (* its , oldPodList , r .isPodOrConfigUpdated )
123- podsToBeUpdated , err := plan .Execute ()
124- if err != nil {
125- return kubebuilderx .Continue , err
126- }
127- updateCount = len (podsToBeUpdated )
112+ // handle 'MemberUpdate'
113+ memberUpdateQuota , err := r .memberUpdateQuota (its , oldPodList )
114+ if err != nil {
115+ return kubebuilderx .Continue , err
128116 }
129117
130- updatingPods := 0
131- updatedPods := 0
132118 priorities := ComposeRolePriorityMap (its .Spec .Roles )
133- isBlocked := false
134- needRetry := false
135119 sortObjects (oldPodList , priorities , false )
136120
137121 // treat old and Pending pod as a special case, as they can be updated without a consequence
@@ -148,38 +132,18 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilder
148132 }
149133 }
150134
151- canBeUpdated := func (pod * corev1.Pod ) bool {
152- if ! isImageMatched (pod ) {
153- tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the pod %s does not have the same image(s) in the status and in the spec" , its .Namespace , its .Name , pod .Name ))
154- return false
155- }
156- if ! intctrlutil .IsPodReady (pod ) {
157- tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the pod %s is not ready" , its .Namespace , its .Name , pod .Name ))
158- return false
159- }
160- if ! intctrlutil .IsPodAvailable (pod , its .Spec .MinReadySeconds ) {
161- tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the pod %s is not available" , its .Namespace , its .Name , pod .Name ))
162- // no pod event will trigger the next reconciliation, so retry it
163- needRetry = true
164- return false
165- }
166- if ! isRoleReady (pod , its .Spec .Roles ) {
167- tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the role of pod %s is not ready" , its .Namespace , its .Name , pod .Name ))
168- return false
169- }
170-
171- return true
172- }
173-
135+ updatingPods := 0
136+ isBlocked := false
137+ needRetry := false
174138 for _ , pod := range oldPodList {
175- if updatingPods >= updateCount || updatingPods >= unavailable {
139+ if updatingPods >= rollingUpdateQuota || updatingPods >= unavailableQuota {
176140 break
177141 }
178- if updatedPods >= replicas {
142+ if updatingPods >= memberUpdateQuota {
179143 break
180144 }
181-
182- if ! canBeUpdated ( pod ) {
145+ if canBeUpdated , retry := r . isPodCanBeUpdated ( tree , its , pod ); ! canBeUpdated {
146+ needRetry = retry
183147 break
184148 }
185149
@@ -248,9 +212,8 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilder
248212 updatingPods ++
249213 }
250214 }
251-
252- updatedPods ++
253215 }
216+
254217 if ! isBlocked {
255218 meta .RemoveStatusCondition (& its .Status .Conditions , string (workloads .InstanceUpdateRestricted ))
256219 }
@@ -260,6 +223,57 @@ func (r *updateReconciler) Reconcile(tree *kubebuilderx.ObjectTree) (kubebuilder
260223 return kubebuilderx .Continue , nil
261224}
262225
226+ func (r * updateReconciler ) rollingUpdateQuota (its * workloads.InstanceSet , podList []* corev1.Pod ) (int , int , error ) {
227+ // handle 'RollingUpdate'
228+ replicas , maxUnavailable , err := parseReplicasNMaxUnavailable (its .Spec .InstanceUpdateStrategy , len (podList ))
229+ if err != nil {
230+ return - 1 , - 1 , err
231+ }
232+ currentUnavailable := 0
233+ for _ , pod := range podList {
234+ if ! intctrlutil .IsPodAvailable (pod , its .Spec .MinReadySeconds ) {
235+ currentUnavailable ++
236+ }
237+ }
238+ unavailable := maxUnavailable - currentUnavailable
239+ return replicas , unavailable , nil
240+ }
241+
242+ func (r * updateReconciler ) memberUpdateQuota (its * workloads.InstanceSet , podList []* corev1.Pod ) (int , error ) {
243+ // if it's a roleful InstanceSet, we use updateCount to represent Pods can be updated according to the spec.memberUpdateStrategy.
244+ updateCount := len (podList )
245+ if len (its .Spec .Roles ) > 0 {
246+ plan := NewUpdatePlan (* its , podList , r .isPodOrConfigUpdated )
247+ podsToBeUpdated , err := plan .Execute ()
248+ if err != nil {
249+ return - 1 , err
250+ }
251+ updateCount = len (podsToBeUpdated )
252+ }
253+ return updateCount , nil
254+ }
255+
256+ func (r * updateReconciler ) isPodCanBeUpdated (tree * kubebuilderx.ObjectTree , its * workloads.InstanceSet , pod * corev1.Pod ) (bool , bool ) {
257+ if ! isImageMatched (pod ) {
258+ tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the pod %s does not have the same image(s) in the status and in the spec" , its .Namespace , its .Name , pod .Name ))
259+ return false , false
260+ }
261+ if ! intctrlutil .IsPodReady (pod ) {
262+ tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the pod %s is not ready" , its .Namespace , its .Name , pod .Name ))
263+ return false , false
264+ }
265+ if ! intctrlutil .IsPodAvailable (pod , its .Spec .MinReadySeconds ) {
266+ tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the pod %s is not available" , its .Namespace , its .Name , pod .Name ))
267+ // no pod event will trigger the next reconciliation, so retry it
268+ return false , true
269+ }
270+ if ! isRoleReady (pod , its .Spec .Roles ) {
271+ tree .Logger .Info (fmt .Sprintf ("InstanceSet %s/%s blocks on update as the role of pod %s is not ready" , its .Namespace , its .Name , pod .Name ))
272+ return false , false
273+ }
274+ return true , false
275+ }
276+
263277func (r * updateReconciler ) switchover (tree * kubebuilderx.ObjectTree , its * workloads.InstanceSet , pod * corev1.Pod ) error {
264278 if its .Spec .MembershipReconfiguration == nil || its .Spec .MembershipReconfiguration .Switchover == nil {
265279 return nil
0 commit comments