recreate.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package deployment
  14. import (
  15. apps "k8s.io/api/apps/v1"
  16. "k8s.io/api/core/v1"
  17. "k8s.io/apimachinery/pkg/types"
  18. "k8s.io/kubernetes/pkg/controller"
  19. "k8s.io/kubernetes/pkg/controller/deployment/util"
  20. )
  21. // rolloutRecreate implements the logic for recreating a replica set.
  22. func (dc *DeploymentController) rolloutRecreate(d *apps.Deployment, rsList []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) error {
  23. // Don't create a new RS if not already existed, so that we avoid scaling up before scaling down.
  24. newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(d, rsList, false)
  25. if err != nil {
  26. return err
  27. }
  28. allRSs := append(oldRSs, newRS)
  29. activeOldRSs := controller.FilterActiveReplicaSets(oldRSs)
  30. // scale down old replica sets.
  31. scaledDown, err := dc.scaleDownOldReplicaSetsForRecreate(activeOldRSs, d)
  32. if err != nil {
  33. return err
  34. }
  35. if scaledDown {
  36. // Update DeploymentStatus.
  37. return dc.syncRolloutStatus(allRSs, newRS, d)
  38. }
  39. // Do not process a deployment when it has old pods running.
  40. if oldPodsRunning(newRS, oldRSs, podMap) {
  41. return dc.syncRolloutStatus(allRSs, newRS, d)
  42. }
  43. // If we need to create a new RS, create it now.
  44. if newRS == nil {
  45. newRS, oldRSs, err = dc.getAllReplicaSetsAndSyncRevision(d, rsList, true)
  46. if err != nil {
  47. return err
  48. }
  49. allRSs = append(oldRSs, newRS)
  50. }
  51. // scale up new replica set.
  52. if _, err := dc.scaleUpNewReplicaSetForRecreate(newRS, d); err != nil {
  53. return err
  54. }
  55. if util.DeploymentComplete(d, &d.Status) {
  56. if err := dc.cleanupDeployment(oldRSs, d); err != nil {
  57. return err
  58. }
  59. }
  60. // Sync deployment status.
  61. return dc.syncRolloutStatus(allRSs, newRS, d)
  62. }
  63. // scaleDownOldReplicaSetsForRecreate scales down old replica sets when deployment strategy is "Recreate".
  64. func (dc *DeploymentController) scaleDownOldReplicaSetsForRecreate(oldRSs []*apps.ReplicaSet, deployment *apps.Deployment) (bool, error) {
  65. scaled := false
  66. for i := range oldRSs {
  67. rs := oldRSs[i]
  68. // Scaling not required.
  69. if *(rs.Spec.Replicas) == 0 {
  70. continue
  71. }
  72. scaledRS, updatedRS, err := dc.scaleReplicaSetAndRecordEvent(rs, 0, deployment)
  73. if err != nil {
  74. return false, err
  75. }
  76. if scaledRS {
  77. oldRSs[i] = updatedRS
  78. scaled = true
  79. }
  80. }
  81. return scaled, nil
  82. }
  83. // oldPodsRunning returns whether there are old pods running or any of the old ReplicaSets thinks that it runs pods.
  84. func oldPodsRunning(newRS *apps.ReplicaSet, oldRSs []*apps.ReplicaSet, podMap map[types.UID]*v1.PodList) bool {
  85. if oldPods := util.GetActualReplicaCountForReplicaSets(oldRSs); oldPods > 0 {
  86. return true
  87. }
  88. for rsUID, podList := range podMap {
  89. // If the pods belong to the new ReplicaSet, ignore.
  90. if newRS != nil && newRS.UID == rsUID {
  91. continue
  92. }
  93. for _, pod := range podList.Items {
  94. switch pod.Status.Phase {
  95. case v1.PodFailed, v1.PodSucceeded:
  96. // Don't count pods in terminal state.
  97. continue
  98. case v1.PodUnknown:
  99. // This happens in situation like when the node is temporarily disconnected from the cluster.
  100. // If we can't be sure that the pod is not running, we have to count it.
  101. return true
  102. default:
  103. // Pod is not in terminal phase.
  104. return true
  105. }
  106. }
  107. }
  108. return false
  109. }
  110. // scaleUpNewReplicaSetForRecreate scales up new replica set when deployment strategy is "Recreate".
  111. func (dc *DeploymentController) scaleUpNewReplicaSetForRecreate(newRS *apps.ReplicaSet, deployment *apps.Deployment) (bool, error) {
  112. scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, *(deployment.Spec.Replicas), deployment)
  113. return scaled, err
  114. }