Skip to content

Resolve confusing use of TooManyRequests error for eviction #133097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion pkg/registry/core/pod/storage/eviction.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,25 @@ func (r *EvictionREST) checkAndDecrement(namespace string, podName string, pdb p
}
if pdb.Status.DisruptionsAllowed == 0 {
err := errors.NewTooManyRequests("Cannot evict pod as it would violate the pod's disruption budget.", 0)
err.ErrStatus.Details.Causes = append(err.ErrStatus.Details.Causes, metav1.StatusCause{Type: policyv1.DisruptionBudgetCause, Message: fmt.Sprintf("The disruption budget %s needs %d healthy pods and has %d currently", pdb.Name, pdb.Status.DesiredHealthy, pdb.Status.CurrentHealthy)})
condition := meta.FindStatusCondition(pdb.Status.Conditions, policyv1.DisruptionAllowedCondition)
if condition.Status == metav1.ConditionFalse {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

condition.Status will panic if condition is nil, which FindStatusCondition will return if the condition is not present

I'd suggest customizing how we construct the message based on CurrentHealthy / DesiredHealthy / presence of a SyncFailedReason or other False condition, with a sensible generic fallback to avoid being confusing. I'd also suggest keeping the existing message as-is if CurrentHealthy <= DesiredHealthy since that is not confusing.

condition := meta.FindStatusCondition(pdb.Status.Conditions, policyv1.DisruptionAllowedCondition)

var msg string
switch {
case pdb.Status.CurrentHealthy <= pdb.Status.DesiredHealthy:
  msg = fmt.Sprintf("The disruption budget %s needs %d healthy pods and has %d currently", pdb.Name, pdb.Status.DesiredHealthy, pdb.Status.CurrentHealthy)
case condition != nil && condition.Status == metav1.ConditionFalse && len(condition.Message) > 0 && condition.Reason == policy.SyncFailedReason:
  msg = fmt.Sprintf("The disruption budget %s does not allow evicting pods currently because it failed sync: %v", pdb.Name, condition.Message)
case condition != nil && condition.Status == metav1.ConditionFalse && len(condition.Message) > 0:
  msg = fmt.Sprintf("The disruption budget %s does not allow evicting pods currently: %v", pdb.Name, condition.Message)
default:
  msg = fmt.Sprintf("The disruption budget %s does not allow evicting pods currently", pdb.Name)
}

err.ErrStatus.Details.Causes = append(err.ErrStatus.Details.Causes, metav1.StatusCause{Type: policyv1.DisruptionBudgetCause, Message: msg})

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the above flow

Perhaps, this part could also output conditions without a condition.Message and print also the condition.Reason

switch {
...
case condition != nil && condition.Status == metav1.ConditionFalse && len(condition.Message) > 0:
  msg = fmt.Sprintf("The disruption budget %s does not allow evicting pods currently: %v", pdb.Name, condition.Message)
...

err.ErrStatus.Details.Causes = append(
err.ErrStatus.Details.Causes,
metav1.StatusCause{
Type: metav1.CauseType(condition.Type),
Message: condition.Message,
},
)
return err
}

err.ErrStatus.Details.Causes = append(
err.ErrStatus.Details.Causes,
metav1.StatusCause{
Type: policyv1.DisruptionBudgetCause,
Message: fmt.Sprintf("The disruption budget %s needs %d healthy pods and has %d currently", pdb.Name, pdb.Status.DesiredHealthy, pdb.Status.CurrentHealthy),
},
)
return err
}

Expand Down