Skip to content

feat(deployment): handle paused rollouts and proportional scaling#46

Open
indyjonesnl wants to merge 1 commit into
calfonso:mainfrom
indyjonesnl:upstream/deployment-paused-proportional
Open

feat(deployment): handle paused rollouts and proportional scaling#46
indyjonesnl wants to merge 1 commit into
calfonso:mainfrom
indyjonesnl:upstream/deployment-paused-proportional

Conversation

@indyjonesnl
Copy link
Copy Markdown

Problem

Two Deployment features missing — both required by K8s conformance:

  1. Paused rollouts: setting `spec.paused = true` should freeze the rolling-update step. We were ignoring it and continuing to scale RSes.
  2. Proportional scaling during a rollout: when `spec.replicas` changes while a rolling update is in progress, K8s distributes the delta across all RSes proportional to their current replica count (so neither old nor new RS gets starved). We were applying the full delta to the new RS only, breaking rollback scenarios that depend on the old RS retaining capacity.

Fix

  • Honor `spec.paused` — bail out of `reconcile_deployment` before scaling RSes when paused.
  • Implement the proportional-scaling helper: `(rs.spec.replicas / sum(active_rs.replicas)) * delta`, round-half-up. Matches `pkg/controller/deployment/util.GetProportion` in K8s.

Verification

`cargo build --workspace --locked` clean. Depends on #32 for green CI.

Match upstream Kubernetes v1.35 deployment controller semantics for the
two conformance scenarios in Unit 8:

- Paused deployments: detect spec.paused and route through scale() only,
  so the rolling-update progression (which scales the old RS down) is
  skipped while paused. Scale events are still honored.
- Proportional scaling: refactor the scale path into a single
  scale_replica_sets() helper mirroring k8s sync.go scale():
    1. FindActiveOrLatest -> direct scale of the single active RS.
    2. IsSaturated -> scale every old RS to 0.
    3. Multiple active RSes -> proportional distribution using each
       RS's max-replicas annotation as the denominator (GetProportion),
       newest-first, with rounding leftover assigned to the new RS.
- Detect scaling events across all active RSes (not gated on
  old_rs_total > 0), matching upstream isScalingEvent().

Adds 5 unit tests covering proportional distribution (active rollout +
paused), paused rollout non-progression, single-new-RS rollover, and
old-RS scale-down on rollover saturation.

K8s refs: pkg/controller/deployment/{deployment_controller,sync}.go,
pkg/controller/deployment/util/deployment_util.go.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant