// cleanupUnhealthyReplicas will scale down old rcs with unhealthy replicas, so that all unhealthy replicas will be deleted. func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRCs []*api.ReplicationController, deployment extensions.Deployment, maxCleanupCount int) (int, error) { sort.Sort(controller.ControllersByCreationTimestamp(oldRCs)) // Safely scale down all old rcs with unhealthy replicas. ReplicationController/ReplicaSet will sort the pods in the order // such that not-ready < ready, unscheduled < scheduled, and pending < running. This ensures that unhealthy replicas will // been deleted first and won't increase unavailability. totalScaledDown := 0 for _, targetRC := range oldRCs { if totalScaledDown >= maxCleanupCount { break } if targetRC.Spec.Replicas == 0 { // cannot scale down this RC. continue } readyPodCount, err := deploymentutil.GetAvailablePodsForRCs(dc.client, []*api.ReplicationController{targetRC}, 0) if err != nil { return totalScaledDown, fmt.Errorf("could not find available pods: %v", err) } if targetRC.Spec.Replicas == readyPodCount { // no unhealthy replicas found, no scaling required. continue } scaledDownCount := int(math.Min(float64(maxCleanupCount-totalScaledDown), float64(targetRC.Spec.Replicas-readyPodCount))) newReplicasCount := targetRC.Spec.Replicas - scaledDownCount _, err = dc.scaleRCAndRecordEvent(targetRC, newReplicasCount, deployment) if err != nil { return totalScaledDown, err } totalScaledDown += scaledDownCount } return totalScaledDown, nil }
// scaleDownOldRCsForRollingUpdate scales down old rcs when deployment strategy is "RollingUpdate". // Need check maxUnavailable to ensure availability func (dc *DeploymentController) scaleDownOldRCsForRollingUpdate(allRCs []*api.ReplicationController, oldRCs []*api.ReplicationController, deployment extensions.Deployment) (int, error) { maxUnavailable, isPercent, err := util.GetIntOrPercentValue(&deployment.Spec.Strategy.RollingUpdate.MaxUnavailable) if err != nil { return 0, fmt.Errorf("invalid value for MaxUnavailable: %v", err) } if isPercent { maxUnavailable = util.GetValueFromPercent(maxUnavailable, deployment.Spec.Replicas) } // Check if we can scale down. minAvailable := deployment.Spec.Replicas - maxUnavailable minReadySeconds := deployment.Spec.MinReadySeconds // Find the number of ready pods. readyPodCount, err := deploymentutil.GetAvailablePodsForRCs(dc.client, allRCs, minReadySeconds) if err != nil { return 0, fmt.Errorf("could not find available pods: %v", err) } if readyPodCount <= minAvailable { // Cannot scale down. return 0, nil } sort.Sort(controller.ControllersByCreationTimestamp(oldRCs)) totalScaledDown := 0 totalScaleDownCount := readyPodCount - minAvailable for _, targetRC := range oldRCs { if totalScaledDown >= totalScaleDownCount { // No further scaling required. break } if targetRC.Spec.Replicas == 0 { // cannot scale down this RC. continue } // Scale down. scaleDownCount := int(math.Min(float64(targetRC.Spec.Replicas), float64(totalScaleDownCount-totalScaledDown))) newReplicasCount := targetRC.Spec.Replicas - scaleDownCount _, err = dc.scaleRCAndRecordEvent(targetRC, newReplicasCount, deployment) if err != nil { return totalScaledDown, err } totalScaledDown += scaleDownCount } return totalScaledDown, nil }
func (dc *DeploymentController) cleanupOldRcs(oldRCs []*api.ReplicationController, deployment extensions.Deployment) error { diff := len(oldRCs) - *deployment.Spec.RevisionHistoryLimit if diff <= 0 { return nil } sort.Sort(controller.ControllersByCreationTimestamp(oldRCs)) var errList []error // TODO: This should be parallelized. for i := 0; i < diff; i++ { controller := oldRCs[i] // Avoid delete rc with non-zero replica counts if controller.Spec.Replicas != 0 || controller.Generation > controller.Status.ObservedGeneration { continue } if err := dc.client.ReplicationControllers(controller.Namespace).Delete(controller.Name); err != nil && !errors.IsNotFound(err) { glog.V(2).Infof("Failed deleting old rc %v for deployment %v: %v", controller.Name, deployment.Name, err) errList = append(errList, err) } } return utilerrors.NewAggregate(errList) }