Skip to content

Commit

Permalink
Fixed deployment readiness (operational status) detection after updat…
Browse files Browse the repository at this point in the history
…e. The algorithm is taken from the `kubectl rollout status` command.
  • Loading branch information
Amper committed Nov 11, 2024
1 parent cbe3688 commit 046948a
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions internal/controller/operator/factory/reconcile/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,24 +77,40 @@ func waitDeploymentReady(ctx context.Context, rclient client.Client, dep *appsv1
if err := rclient.Get(ctx, types.NamespacedName{Namespace: dep.Namespace, Name: dep.Name}, &actualDeploy); err != nil {
return false, fmt.Errorf("cannot fetch actual deployment state: %w", err)
}
for _, cond := range actualDeploy.Status.Conditions {
if cond.Type == appsv1.DeploymentProgressing {
// https://kubernetes.io/docs/concepts/workloads/internal/controller/deployment/#complete-deployment
// Completed status for deployment
if cond.Reason == "NewReplicaSetAvailable" && cond.Status == "True" {
return true, nil
}
return false, nil
}
cond := getDeploymentCondition(actualDeploy.Status, appsv1.DeploymentProgressing)
if cond != nil && cond.Reason == "ProgressDeadlineExceeded" {
return false, fmt.Errorf("deployment %s/%s has exceeded its progress deadline", dep.Namespace, dep.Name)
}
if actualDeploy.Spec.Replicas != nil && actualDeploy.Status.UpdatedReplicas < *actualDeploy.Spec.Replicas {
// Waiting for deployment rollout to finish: part of new replicas have been updated...
return false, nil
}
if actualDeploy.Status.Replicas > actualDeploy.Status.UpdatedReplicas {
// Waiting for deployment rollout to finish: part of old replicas are pending termination...
return false, nil
}
if actualDeploy.Status.AvailableReplicas < actualDeploy.Status.UpdatedReplicas {
// Waiting for deployment rollout to finish: part of updated replicas are available
return false, nil
}
return false, nil
return true, nil
})
if err != nil {
return reportFirstNotReadyPodOnError(ctx, rclient, fmt.Errorf("cannot wait for deployment to become ready: %w", err), dep.Namespace, labels.SelectorFromSet(dep.Spec.Selector.MatchLabels), dep.Spec.MinReadySeconds)
}
return nil
}

func getDeploymentCondition(status appsv1.DeploymentStatus, condType appsv1.DeploymentConditionType) *appsv1.DeploymentCondition {
for i := range status.Conditions {
c := status.Conditions[i]
if c.Type == condType {
return &c
}
}
return nil
}

func reportFirstNotReadyPodOnError(ctx context.Context, rclient client.Client, origin error, ns string, selector labels.Selector, minReadySeconds int32) error {
// list pods and join statuses
var podList corev1.PodList
Expand Down

0 comments on commit 046948a

Please sign in to comment.