What's New in v0.1.27
v0.1.27 adds a namespace freeze kill-switch and per-minute resize increase caps. CREATE initial sizing, dest leftover limits, OneShot, and safety restore now follow the same live apply rules as in-place resize.
Highlights
- Annotate a namespace with
attune.io/freeze=trueto stop new resizes while recommendations and pending safety revert keep running. - Increase budgets are now per minute (
maxCpuIncreasePerMinute/maxMemoryIncreasePerMinute) instead of per reconcile cycle. - New pods, dest leftover limits, OneShot, and template persist use the same clamp, floor, and dest-cap path as live
/resize.
Namespace freeze
- There was no cluster-local way to pause apply during an incident.
attune.io/freeze=trueon the policy namespace skips in-place resize, eviction, startup boost, template persist, and CREATE initial sizing. Recommendations, status, and export still update. Pending safety observation still reverts unsafe pods and restores AfterSuccessfulResize templates.ResizeBlocked=Truewithreason=NamespaceFrozen. Lifting the annotation clears that reason. A failed namespace Get is treated as frozen. Chart RBAC already includesnamespacesget/list/watch. Hand-managed ClusterRoles must add those verbs (#685, #686, #741).
Resize rate caps
- Per-cycle increase caps changed meaning when you changed
reconcileInterval. PrefermaxCpuIncreasePerMinuteandmaxMemoryIncreasePerMinute. Admission warns onmaxTotalCpuIncrease/maxTotalMemoryIncrease; those fields still apply until you migrate. The per-minute bucket carries leftover milliseconds into the next refill (#707, #710, #741).
CREATE, dest leftover, and OneShot
-
CREATE ignored cluster or namespace AttuneDefaults. New pods merge defaults before applying ControlledValues, so a cluster
RequestsAndLimitsdefault writes limits on create (#725). -
Wizard inherit omitted
metricsSourceand the API server rejected the policy.metricsSourceis optional. Inherit stays valid without snapshotting the provider into the generated policy (#728, #741). -
CronJob CREATE did not apply initial sizing. The webhook matches through the owning Job. Recommend-mode CronJobs get CREATE sizing (#731, #732).
-
Startup boost on CREATE was a no-op, or invented a dest limit. Boost now applies on CREATE, dest-caps to the recommendation dest when limits are controlled, copies memory dest so Guaranteed QoS is preserved, and skips shrink. Expiry keeps the annotation when QoS would skip the restore (#730, #734, #741, #742).
-
LimitRange leftover dest limits were ignored. CREATE, persist, and
/resizedest-cap to the live leftover dest. The plan dest-clamps before AtTarget so Auto and OneShot converge. Dest-clamped applyTois persisted. CPU dest clamp at target emitsResizeDeferred. HPA retune uses the applied leftover CPU, not the uncapped rec (#721, #722, #723, #727, #729). -
OneShot stuck on the first replica. Selection walks past a replica that is already at the applied (post-clamp, post-floor) target, or that MemoryPressure, Infeasible plus InPlaceOnly, quota, or QoS would skip. Later replicas move in the same cycle. Safety revert restores the AfterSuccessfulResize template (#682, #683, #684).
Safety, persist, and live apply
-
Safety revert could strip GPU or hugepage template fields. Restore keeps extended and ephemeral resources (#700).
-
Restore after a safety revert could stop after one failure. Restore retries when Ready recovers and live already matches the applied revert target (including the memory-limit clamp and Guaranteed raise). Freeze does not skip pending safety. Cleanup stays blocked until restore lands (#686, #687, #688).
-
Persist skipped after eviction, or after a hold that made rec fields look equal. AfterSuccessfulResize includes Evicted so InPlaceOrRecreate patches the template before recreate. Persist applies the usage floor against live usage, not a stale
rec.Current. RequestsOnly leftover template limits are not a template change (#679, #680). -
Floor, MemoryPressure, Infeasible eviction, and last-replica checks used a stale informer pod. Those paths now live-Get the pod, or live-List Running pods for last replica. A failed live Get skips. Last-replica eviction counts only Running pods with no deletion timestamp (#673, #677).
-
SafetyObservationis now a named status condition (Observing,Evaluating,RestorePending,Incomplete). It is derived fromattune.iotracking annotations each reconcile and is removed when no tracked pods remain (#711, #720). -
kubectl attune statusandsavingsaccepted unknown--sort-byvalues and printed unsorted output. Unknown values now exit 1. Allowed values arename,namespace,savings, andage(#677). -
attune_eviction_totalnow increments for skipped attempts as well as successes. Theresultlabel issuccess,denied,last_replica,list_failed, orno_selector. Alerts that treated every increment as an eviction should filterresult="success"(#677).
Upgrade notes
- Upgrade the chart to 0.1.27, or set
image.tagto0.1.27orv0.1.27. - Pull
ghcr.io/attune-io/attune:v0.1.27orghcr.io/attune-io/attune:0.1.27. Both tags point at the same digest. - Apply CRDs before
helm upgradeif you need new schema fields (kubectl apply --server-side --force-conflictsfrom the releasecrds.yaml). - If you maintain your own ClusterRole, add
namespacesget,list, andwatch. A missing grant looks like a cluster-wide freeze. - Prefer
maxCpuIncreasePerMinute/maxMemoryIncreasePerMinute. The old per-cycle fields still apply and emit an admission warning. - Alerts on
attune_eviction_totalshould filterresult="success". - Scripts that passed a typo to
kubectl attune --sort-bynow exit 1.
See Upgrading for dest leftover, OneShot, last-replica eviction, and freeze details.