Skip to content

CKS: node drain on scale-down and upgrade fails too easily, and a failed upgrade can't be resumed #14610

Open

Description

@bhouse-nexthop

problem

Both scale-down and upgrade of a CloudStack-managed Kubernetes cluster drain a node before they remove or upgrade it, and both handle a drain that fails, or doesn't finish quickly, badly.

Scale-down (KubernetesClusterScaleWorker.removeKubernetesClusterNode):

  • When kubectl drain exits non-zero, for example because a PodDisruptionBudget doesn't allow an eviction yet, it gives up at once with no retry.
  • When it does retry, after an exception, each attempt is counted twice.
  • The node is left cordoned.
  • The cluster goes to Alert, although no node was removed and the cluster still works.

Upgrade (KubernetesClusterUpgradeWorker):

  • A failed drain is retried at once, with no wait for the eviction to become possible, and on the last failure the node is left cordoned.
  • Only the first control node is waited on to be Ready. The next node can be drained while the previous one is still coming back.
  • The script for node i is run over SSH on port sshPort + i. The port-forwarding rules aren't created in the order of the upgrade's VM list: manually upgraded nodes are left out of that list, and nodes added later get the next free port. So the script can run on the wrong node.

Both: kubectl drain runs without --timeout, so a fixed 60s SSH timeout cuts it off rather than a deadline of its own.

After a failed upgrade the cluster is left in Alert. upgradeKubernetesCluster only accepts a Running cluster, so the upgrade can't be retried or finished, although the nodes already upgraded are known (kubernetesnodeversion in the cluster's VM list).

versions

4.22 (the code is the same on main).

The steps to reproduce the bug

  1. Create a CKS cluster with 2 or more worker nodes.
  2. Deploy a workload with a PodDisruptionBudget that allows no disruption (for example minAvailable equal to the replica count) on the worker that a scale-down would remove.
  3. Scale the cluster down by one worker.
  4. The drain fails at once, the cluster goes to Alert, and the node stays cordoned. No node is removed.

For the upgrade: let the drain or the upgrade script fail on any node after the first one. The cluster goes to Alert with some nodes at the new version, and upgradeKubernetesCluster refuses to run again because the cluster isn't Running.

What to do about it?

  • Use one drain helper for both paths:
    • each attempt counts once, and a non-zero exit or an exception is retried after a wait;
    • kubectl drain --timeout comes from a setting, and the SSH wait is derived from it;
    • on the last failure the node is uncordoned and the drain output is reported.
  • On scale-down, cordon and drain every node to remove before removing any. If one can't be drained, uncordon them all and leave the cluster as it was rather than in Alert.
  • On upgrade, wait for every node to be Ready, and reach each node through its own SSH port-forwarding rule.
  • Let upgradeKubernetesCluster be retried on a cluster in Alert after an upgrade to the same version failed part way, skipping the nodes already upgraded.

Activity

  1. github-actions commented on Nov 9, 2026

    @github-actions

    Warning

    threat detection engine error
    The threat detection engine encountered an error and could not complete analysis. This is a tooling failure, not a security finding.

    What happened

    The threat detection engine failed to produce results.

    Review the workflow run logs for details.

    🎯 Triage report

    CKS drains nodes before scale-down and upgrade, and both paths handle a failed or slow drain poorly. On scale-down, one failed drain (for example a PodDisruptionBudget) gives up without retry and leaves the node cordoned, and the cluster moves to Alert although no node was removed. On upgrade, a failed drain is retried at once, the node is left cordoned, only the first control node is waited on, and the upgrade script can reach the wrong node through the SSH port-forward rules. A failed upgrade also leaves the cluster in Alert, where upgradeKubernetesCluster refuses to run again.

    📊 Assessment

    Dimension Value Reasoning
    Type type:bug Drain and upgrade failures, with reproduction steps
    Component component:cks Scale and upgrade workers in the CKS plugin
    Severity Severity:Major Failed drains leave clusters in Alert and failed upgrades cannot be resumed
    Labels type:bug, component:cks, Severity:Major
    Coding agent Needs more info Several separate changes (drain helper, scale-down ordering, upgrade SSH mapping, resume); maintainers should confirm scope

    🔗 Similar issues

    💡 Notes and suggestions
    • Reproduction for scale-down: a PodDisruptionBudget that allows no disruption on the worker a scale-down would remove.
    • The report lists four separate fixes; splitting them into smaller items may help review.

    Generated by Daily Issue Triage · copilot · haiku55 · ~4 AIC · ⊞ 3.8K · ◷

    Add this agentic workflow to your repo

    To install this agentic workflow, run

    gh aw add githubnext/agentics/workflows/daily-issue-triage.md@139fa09ef17cde4135e696ff8e7af09bc5ddfa6e
    
  2. added this to the 4.22.3 milestone on Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions