Skip to content

[Bug] New version can get stuck INACTIVE and never promote when a scale-to-zero autoscaler holds its Deployment at 0 replicas #438

Description

@noamyehudai

Summary

With AllAtOnce rollout and a backlog-based scale-to-zero autoscaler on the versioned worker Deployments (e.g. KEDA's Temporal scaler keyed per workerDeploymentBuildId, minReplicaCount: 0), a newly rolled-out version can deadlock and never become Current: the autoscaler holds its Deployment at 0 replicas, so it has no pollers; the controller then refuses to promote it; the next deploy supersedes it; and it is left permanently as an INACTIVE / never-Current version. It never self-recovers.

Environment

  • temporal-worker-controller v1.8.0 (Helm chart 0.27.0), controller-runtime v0.24.0
  • Temporal Server v1.30.x, CLI v1.6.x
  • Rollout strategy: AllAtOnce
  • Per-version pod autoscaling via a KEDA ScaledObject (temporal scaler), minReplicaCount: 0, trigger keyed to the version's own workerDeploymentBuildId backlog

The deadlock

  1. A new build lands → the controller creates the versioned Deployment.
  2. The autoscaler scales that Deployment on the backlog for that build ID. A version that is not yet Current has no workflows pinned to its build ID → its build-id backlog is 0 → the autoscaler scales it to 0 replicas → 0 pollers.
  3. The controller (AllAtOnce) attempts to set it Current and fails:
    unable to set current deployment version: proposed current version
    'default/example-worker:1.4.0-a1b2' is missing active task queues from the
    current version; these would become unversioned if it is set as the current version
    
    A version with 0 pollers polls no task queues, so it is "missing the active task queues from the current version." (This guard is correct — promoting a poller-less version would orphan those task queues as unversioned.)
  4. Deadlock: no pollers → can't be promoted; not Current → no backlog → the autoscaler grants no pollers.
  5. The next deploy retargets the controller to a newer build. The stranded version stays never-Current → INACTIVE forever — nothing ever routes to it, so it never gets pollers and never recovers.

Trigger condition

Deploying while the task queue is idle (no backlog to activate the per-build-id scaler). With steady traffic at deploy time — or a minReplicas ≥ 1 autoscaler — the new version comes up with pollers and promotes normally, so this does not reproduce. It's intermittent and correlates strongly with idle-time deploys (in one environment we see a long tail of consecutive never-Current INACTIVE versions from quiet periods, and none from busy periods).

Impact

Reproduction

  1. Configure a worker with AllAtOnce rollout and a per-version KEDA ScaledObject (temporal scaler, minReplicaCount: 0, trigger keyed to the version's workerDeploymentBuildId).
  2. With no traffic on the task queue, roll out a new build.
  3. Observe: the new version's Deployment is scaled to 0; the controller logs the "missing active task queues" error on the set-current attempt; the version never becomes Current.
  4. Roll out another build → the previous one is left INACTIVE permanently.

Expected behavior

During a rollout the controller should ensure the target version has at least one active poller before/while calling SetWorkerDeploymentCurrentVersion — e.g. warm a poller for the target version (ensure ≥1 ready replica, or wait for readiness) prior to set-current, then hand scaling back to the autoscaler. That keeps scale-to-zero autoscaling compatible with rollout, instead of forcing users onto a permanent minReplicas ≥ 1 (which loses scale-to-zero and keeps drained versions from scaling down during sunset — see also #350).

Workarounds

  • Use a minReplicas ≥ 1 autoscaler (e.g. a plain HPA). Removes the deadlock, but gives up scale-to-zero and holds non-current/drained versions at ≥1 replica until the sunset delete.
  • Ensure task-queue traffic at deploy time.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions