@@ -319,20 +319,20 @@ func (r *ReconcileWorkloadSpread) syncWorkloadSpread(ws *appsv1alpha1.WorkloadSp
319
319
klog .Warningf ("WorkloadSpread (%s/%s) has no matched pods, target workload's replicas[%d]" , ws .Namespace , ws .Name , workloadReplicas )
320
320
}
321
321
322
- // group Pods by subset
323
- podMap , err := r .groupPod (ws , pods , workloadReplicas )
322
+ // group Pods by pod-revision and subset
323
+ versionedPodMap , subsetPodMap , err := r .groupVersionedPods (ws , pods , workloadReplicas )
324
324
if err != nil {
325
325
return err
326
326
}
327
327
328
328
// update deletion-cost for each subset
329
- err = r .updateDeletionCost (ws , podMap , workloadReplicas )
329
+ err = r .updateDeletionCost (ws , versionedPodMap , workloadReplicas )
330
330
if err != nil {
331
331
return err
332
332
}
333
333
334
334
// calculate status and reschedule
335
- status , scheduleFailedPodMap := r .calculateWorkloadSpreadStatus (ws , podMap , workloadReplicas )
335
+ status , scheduleFailedPodMap := r .calculateWorkloadSpreadStatus (ws , versionedPodMap , subsetPodMap , workloadReplicas )
336
336
if status == nil {
337
337
return nil
338
338
}
@@ -362,8 +362,33 @@ func getInjectWorkloadSpreadFromPod(pod *corev1.Pod) *wsutil.InjectWorkloadSprea
362
362
return injectWS
363
363
}
364
364
365
- // groupPod returns a map, the key is the name of subset and the value represents the Pods of the corresponding subset.
366
- func (r * ReconcileWorkloadSpread ) groupPod (ws * appsv1alpha1.WorkloadSpread , pods []* corev1.Pod , replicas int32 ) (map [string ][]* corev1.Pod , error ) {
365
+ // groupVersionedPods will group pods by pod version and subset
366
+ func (r * ReconcileWorkloadSpread ) groupVersionedPods (ws * appsv1alpha1.WorkloadSpread , allPods []* corev1.Pod , replicas int32 ) (map [string ]map [string ][]* corev1.Pod , map [string ][]* corev1.Pod , error ) {
367
+ versionedPods := map [string ][]* corev1.Pod {}
368
+ for _ , pod := range allPods {
369
+ version := wsutil .GetPodVersion (pod )
370
+ versionedPods [version ] = append (versionedPods [version ], pod )
371
+ }
372
+
373
+ subsetPodMap := map [string ][]* corev1.Pod {}
374
+ versionedPodMap := map [string ]map [string ][]* corev1.Pod {}
375
+ // group pods by version
376
+ for version , pods := range versionedPods {
377
+ // group pods by subset
378
+ podMap , err := r .groupPodBySubset (ws , pods , replicas )
379
+ if err != nil {
380
+ return nil , nil , err
381
+ }
382
+ for subset , ps := range podMap {
383
+ subsetPodMap [subset ] = append (subsetPodMap [subset ], ps ... )
384
+ }
385
+ versionedPodMap [version ] = podMap
386
+ }
387
+ return versionedPodMap , subsetPodMap , nil
388
+ }
389
+
390
+ // groupPodBySubset returns a map, the key is the name of subset and the value represents the Pods of the corresponding subset.
391
+ func (r * ReconcileWorkloadSpread ) groupPodBySubset (ws * appsv1alpha1.WorkloadSpread , pods []* corev1.Pod , replicas int32 ) (map [string ][]* corev1.Pod , error ) {
367
392
podMap := make (map [string ][]* corev1.Pod , len (ws .Spec .Subsets )+ 1 )
368
393
podMap [FakeSubsetName ] = []* corev1.Pod {}
369
394
subsetMissingReplicas := make (map [string ]int )
@@ -507,18 +532,58 @@ func (r *ReconcileWorkloadSpread) patchFavoriteSubsetMetadataToPod(pod *corev1.P
507
532
// 1. current WorkloadSpreadStatus
508
533
// 2. a map, the key is the subsetName, the value is the schedule failed Pods belongs to the subset.
509
534
func (r * ReconcileWorkloadSpread ) calculateWorkloadSpreadStatus (ws * appsv1alpha1.WorkloadSpread ,
510
- podMap map [string ][] * corev1.Pod , workloadReplicas int32 ) ( * appsv1alpha1. WorkloadSpreadStatus , map [string ][]* corev1.Pod ) {
511
- // set the generation in the returned status
535
+ versionedPodMap map [string ]map [ string ][] * corev1.Pod , subsetPodMap map [string ][]* corev1.Pod ,
536
+ workloadReplicas int32 ) ( * appsv1alpha1. WorkloadSpreadStatus , map [ string ][] * corev1. Pod ) {
512
537
status := appsv1alpha1.WorkloadSpreadStatus {}
538
+ // set the generation in the returned status
513
539
status .ObservedGeneration = ws .Generation
514
540
// status.ObservedWorkloadReplicas = workloadReplicas
515
- status .SubsetStatuses = make ([]appsv1alpha1.WorkloadSpreadSubsetStatus , len (ws .Spec .Subsets ))
541
+ status .VersionedSubsetStatuses = make (map [string ][]appsv1alpha1.WorkloadSpreadSubsetStatus , len (versionedPodMap ))
542
+
543
+ // overall subset statuses
544
+ var scheduleFailedPodMap map [string ][]* corev1.Pod
545
+ status .SubsetStatuses , scheduleFailedPodMap = r .calculateWorkloadSpreadSubsetStatuses (ws , ws .Status .SubsetStatuses , subsetPodMap , workloadReplicas )
546
+
547
+ // versioned subset statuses calculated by observed pods
548
+ for version , podMap := range versionedPodMap {
549
+ status .VersionedSubsetStatuses [version ], _ = r .calculateWorkloadSpreadSubsetStatuses (ws , ws .Status .VersionedSubsetStatuses [version ], podMap , workloadReplicas )
550
+ }
551
+
552
+ // Consider this case:
553
+ // A Pod has been created and processed by webhook, but the Pod is not cached by controller.
554
+ // We have to keep the subsetStatus for this version even though there is no Pod belonging to it.
555
+ for version := range ws .Status .VersionedSubsetStatuses {
556
+ if _ , exist := versionedPodMap [version ]; exist {
557
+ continue
558
+ }
559
+ versionSubsetStatues , _ := r .calculateWorkloadSpreadSubsetStatuses (ws , ws .Status .VersionedSubsetStatuses [version ], nil , workloadReplicas )
560
+ if ! isEmptySubsetStatuses (versionSubsetStatues ) {
561
+ status .VersionedSubsetStatuses [version ] = versionSubsetStatues
562
+ }
563
+ }
564
+
565
+ return & status , scheduleFailedPodMap
566
+ }
567
+
568
+ func isEmptySubsetStatuses (statues []appsv1alpha1.WorkloadSpreadSubsetStatus ) bool {
569
+ replicas , creating , deleting := 0 , 0 , 0
570
+ for _ , subset := range statues {
571
+ replicas += int (subset .Replicas )
572
+ creating += len (subset .CreatingPods )
573
+ deleting += len (subset .DeletingPods )
574
+ }
575
+ return replicas + creating + deleting == 0
576
+ }
577
+
578
+ func (r * ReconcileWorkloadSpread ) calculateWorkloadSpreadSubsetStatuses (ws * appsv1alpha1.WorkloadSpread ,
579
+ oldSubsetStatuses []appsv1alpha1.WorkloadSpreadSubsetStatus , podMap map [string ][]* corev1.Pod , workloadReplicas int32 ,
580
+ ) ([]appsv1alpha1.WorkloadSpreadSubsetStatus , map [string ][]* corev1.Pod ) {
581
+ subsetStatuses := make ([]appsv1alpha1.WorkloadSpreadSubsetStatus , len (ws .Spec .Subsets ))
516
582
scheduleFailedPodMap := make (map [string ][]* corev1.Pod )
517
583
518
584
// Using a map to restore name and old status of subset, because user could adjust the spec's subset sequence
519
585
// to change priority of subset. We guarantee that operation and use subset name to distinguish which subset
520
586
// from old status.
521
- oldSubsetStatuses := ws .Status .SubsetStatuses
522
587
oldSubsetStatusMap := make (map [string ]* appsv1alpha1.WorkloadSpreadSubsetStatus , len (oldSubsetStatuses ))
523
588
for i := range oldSubsetStatuses {
524
589
oldSubsetStatusMap [oldSubsetStatuses [i ].Name ] = & oldSubsetStatuses [i ]
@@ -557,10 +622,10 @@ func (r *ReconcileWorkloadSpread) calculateWorkloadSpreadStatus(ws *appsv1alpha1
557
622
removeWorkloadSpreadSubsetCondition (subsetStatus , appsv1alpha1 .SubsetSchedulable )
558
623
}
559
624
560
- status . SubsetStatuses [i ] = * subsetStatus
625
+ subsetStatuses [i ] = * subsetStatus
561
626
}
562
627
563
- return & status , scheduleFailedPodMap
628
+ return subsetStatuses , scheduleFailedPodMap
564
629
}
565
630
566
631
// calculateWorkloadSpreadSubsetStatus returns the current subsetStatus for subset.
@@ -678,9 +743,7 @@ func (r *ReconcileWorkloadSpread) calculateWorkloadSpreadSubsetStatus(ws *appsv1
678
743
679
744
func (r * ReconcileWorkloadSpread ) UpdateWorkloadSpreadStatus (ws * appsv1alpha1.WorkloadSpread ,
680
745
status * appsv1alpha1.WorkloadSpreadStatus ) error {
681
- if status .ObservedGeneration == ws .Status .ObservedGeneration &&
682
- // status.ObservedWorkloadReplicas == ws.Status.ObservedWorkloadReplicas &&
683
- apiequality .Semantic .DeepEqual (status .SubsetStatuses , ws .Status .SubsetStatuses ) {
746
+ if apiequality .Semantic .DeepEqual (status , ws .Status ) {
684
747
return nil
685
748
}
686
749
0 commit comments