// Returns a replica set that matches the intent of the given deployment. Returns nil if the new replica set doesn't exist yet. // 1. Get existing new RS (the RS that the given deployment targets, whose pod template is the same as deployment's). // 2. If there's existing new RS, update its revision number if it's smaller than (maxOldRevision + 1), where maxOldRevision is the max revision number among all old RSes. // 3. If there's no existing new RS and createIfNotExisted is true, create one with appropriate revision number (maxOldRevision + 1) and replicas. // Note that the pod-template-hash will be added to adopted RSes and pods. func (dc *DeploymentController) getNewReplicaSet(deployment *extensions.Deployment, rsList []extensions.ReplicaSet, maxOldRevision int64, oldRSs []*extensions.ReplicaSet, createIfNotExisted bool) (*extensions.ReplicaSet, error) { // Calculate revision number for this new replica set newRevision := strconv.FormatInt(maxOldRevision+1, 10) existingNewRS, err := deploymentutil.FindNewReplicaSet(deployment, rsList) if err != nil { return nil, err } else if existingNewRS != nil { // Set existing new replica set's annotation if setNewReplicaSetAnnotations(deployment, existingNewRS, newRevision, true) { return dc.client.Extensions().ReplicaSets(deployment.ObjectMeta.Namespace).Update(existingNewRS) } return existingNewRS, nil } if !createIfNotExisted { return nil, nil } // new ReplicaSet does not exist, create one. namespace := deployment.ObjectMeta.Namespace podTemplateSpecHash := podutil.GetPodTemplateSpecHash(deployment.Spec.Template) newRSTemplate := deploymentutil.GetNewReplicaSetTemplate(deployment) // Add podTemplateHash label to selector. newRSSelector := labelsutil.CloneSelectorAndAddLabel(deployment.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) // Create new ReplicaSet newRS := extensions.ReplicaSet{ ObjectMeta: api.ObjectMeta{ // Make the name deterministic, to ensure idempotence Name: deployment.Name + "-" + fmt.Sprintf("%d", podTemplateSpecHash), Namespace: namespace, }, Spec: extensions.ReplicaSetSpec{ Replicas: 0, Selector: newRSSelector, Template: newRSTemplate, }, } allRSs := append(oldRSs, &newRS) newReplicasCount, err := deploymentutil.NewRSNewReplicas(deployment, allRSs, &newRS) if err != nil { return nil, err } newRS.Spec.Replicas = newReplicasCount // Set new replica set's annotation setNewReplicaSetAnnotations(deployment, &newRS, newRevision, false) createdRS, err := dc.client.Extensions().ReplicaSets(namespace).Create(&newRS) if err != nil { dc.enqueueDeployment(deployment) return nil, fmt.Errorf("error creating replica set %v: %v", deployment.Name, err) } if newReplicasCount > 0 { dc.eventRecorder.Eventf(deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", "up", createdRS.Name, newReplicasCount) } return createdRS, dc.updateDeploymentRevision(deployment, newRevision) }
func (dc *DeploymentController) reconcileNewReplicaSet(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment extensions.Deployment) (bool, error) { if newRS.Spec.Replicas == deployment.Spec.Replicas { // Scaling not required. return false, nil } if newRS.Spec.Replicas > deployment.Spec.Replicas { // Scale down. scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, deployment.Spec.Replicas, deployment) return scaled, err } newReplicasCount, err := deploymentutil.NewRSNewReplicas(&deployment, allRSs, newRS) if err != nil { return false, err } scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, newReplicasCount, deployment) return scaled, err }
// Returns a replica set that matches the intent of the given deployment. // It creates a new replica set if required. // The revision of the new replica set will be updated to maxOldRevision + 1 func (dc *DeploymentController) getNewReplicaSet(deployment extensions.Deployment, maxOldRevision int64, oldRSs []*extensions.ReplicaSet, createIfNotExisted bool) (*extensions.ReplicaSet, error) { // Calculate revision number for this new replica set newRevision := strconv.FormatInt(maxOldRevision+1, 10) existingNewRS, err := deploymentutil.GetNewReplicaSetFromList(deployment, dc.client, func(namespace string, options api.ListOptions) (*api.PodList, error) { podList, err := dc.podStore.Pods(namespace).List(options.LabelSelector) return &podList, err }, func(namespace string, options api.ListOptions) ([]extensions.ReplicaSet, error) { return dc.rsStore.ReplicaSets(namespace).List(options.LabelSelector) }) if err != nil { return nil, err } else if existingNewRS != nil { // Set existing new replica set's annotation if setNewReplicaSetAnnotations(&deployment, existingNewRS, newRevision) { return dc.client.Extensions().ReplicaSets(deployment.ObjectMeta.Namespace).Update(existingNewRS) } return existingNewRS, nil } if !createIfNotExisted { return nil, nil } // Check the replica set expectations of the deployment before creating a new one. dKey, err := controller.KeyFunc(&deployment) if err != nil { return nil, fmt.Errorf("couldn't get key for deployment %#v: %v", deployment, err) } if !dc.rsExpectations.SatisfiedExpectations(dKey) { dc.enqueueDeployment(&deployment) return nil, fmt.Errorf("replica set expectations not met yet before getting new replica set\n") } // new ReplicaSet does not exist, create one. namespace := deployment.ObjectMeta.Namespace podTemplateSpecHash := podutil.GetPodTemplateSpecHash(deployment.Spec.Template) newRSTemplate := deploymentutil.GetNewReplicaSetTemplate(deployment) // Add podTemplateHash label to selector. newRSSelector := labelsutil.CloneSelectorAndAddLabel(deployment.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) // Set ReplicaSet expectations (1 ReplicaSet should be created) dKey, err = controller.KeyFunc(&deployment) if err != nil { return nil, fmt.Errorf("couldn't get key for deployment controller %#v: %v", deployment, err) } dc.rsExpectations.ExpectCreations(dKey, 1) // Create new ReplicaSet newRS := extensions.ReplicaSet{ ObjectMeta: api.ObjectMeta{ GenerateName: deployment.Name + "-", Namespace: namespace, }, Spec: extensions.ReplicaSetSpec{ Replicas: 0, Selector: newRSSelector, Template: &newRSTemplate, }, } // Set new replica set's annotation setNewReplicaSetAnnotations(&deployment, &newRS, newRevision) allRSs := append(oldRSs, &newRS) newReplicasCount, err := deploymentutil.NewRSNewReplicas(&deployment, allRSs, &newRS) if err != nil { return nil, err } newRS.Spec.Replicas = newReplicasCount createdRS, err := dc.client.Extensions().ReplicaSets(namespace).Create(&newRS) if err != nil { dc.rsExpectations.DeleteExpectations(dKey) return nil, fmt.Errorf("error creating replica set: %v", err) } if newReplicasCount > 0 { dc.eventRecorder.Eventf(&deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", "up", createdRS.Name, newReplicasCount) } return createdRS, dc.updateDeploymentRevision(deployment, newRevision) }
// Returns a replica set that matches the intent of the given deployment. // It creates a new replica set if required. // The revision of the new replica set will be updated to maxOldRevision + 1 func (dc *DeploymentController) getNewReplicaSet(deployment extensions.Deployment, maxOldRevision int64, oldRSs []*extensions.ReplicaSet, createIfNotExisted bool) (*extensions.ReplicaSet, error) { // Calculate revision number for this new replica set newRevision := strconv.FormatInt(maxOldRevision+1, 10) existingNewRS, err := deploymentutil.GetNewReplicaSetFromList(deployment, dc.client, func(namespace string, options api.ListOptions) (*api.PodList, error) { podList, err := dc.podStore.Pods(namespace).List(options.LabelSelector) return &podList, err }, func(namespace string, options api.ListOptions) ([]extensions.ReplicaSet, error) { return dc.rsStore.ReplicaSets(namespace).List(options.LabelSelector) }) if err != nil { return nil, err } else if existingNewRS != nil { // Set existing new replica set's annotation if setNewReplicaSetAnnotations(&deployment, existingNewRS, newRevision) { return dc.client.Extensions().ReplicaSets(deployment.ObjectMeta.Namespace).Update(existingNewRS) } return existingNewRS, nil } if !createIfNotExisted { return nil, nil } // new ReplicaSet does not exist, create one. namespace := deployment.ObjectMeta.Namespace podTemplateSpecHash := podutil.GetPodTemplateSpecHash(deployment.Spec.Template) newRSTemplate := deploymentutil.GetNewReplicaSetTemplate(deployment) // Add podTemplateHash label to selector. newRSSelector := labelsutil.CloneSelectorAndAddLabel(deployment.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) // Set ReplicaSet expectations (1 ReplicaSet should be created). // This clobbers previous expectations, but we checked that in syncDeployment. // We don't set expectations for deletions of 0-replica ReplicaSets because re-setting // expectations would clobber these, and redundant deletions shouldn't cause harm. dKey, err := controller.KeyFunc(&deployment) if err != nil { return nil, fmt.Errorf("couldn't get key for deployment %#v: %v", deployment, err) } // Create new ReplicaSet newRS := extensions.ReplicaSet{ ObjectMeta: api.ObjectMeta{ GenerateName: deployment.Name + "-", Namespace: namespace, }, Spec: extensions.ReplicaSetSpec{ Replicas: 0, Selector: newRSSelector, Template: &newRSTemplate, }, } // Set new replica set's annotation setNewReplicaSetAnnotations(&deployment, &newRS, newRevision) allRSs := append(oldRSs, &newRS) newReplicasCount, err := deploymentutil.NewRSNewReplicas(&deployment, allRSs, &newRS) if err != nil { return nil, err } // Increment expected creations dc.rsExpectations.RaiseExpectations(dKey, 1, 0) if newReplicasCount != 0 { dc.podExpectations.RaiseExpectations(dKey, newReplicasCount, 0) } newRS.Spec.Replicas = newReplicasCount createdRS, err := dc.client.Extensions().ReplicaSets(namespace).Create(&newRS) if err != nil { // Decrement expected creations dc.rsExpectations.LowerExpectations(dKey, 1, 0) if newReplicasCount != 0 { dc.podExpectations.LowerExpectations(dKey, newReplicasCount, 0) } dc.enqueueDeployment(deployment) return nil, fmt.Errorf("error creating replica set %v: %v", dKey, err) } if newReplicasCount > 0 { dc.eventRecorder.Eventf(&deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", "up", createdRS.Name, newReplicasCount) } return createdRS, dc.updateDeploymentRevision(deployment, newRevision) }