Skip to content

Usage & workflow

This section walks the full lifecycle of a recommendation: how it appears, how to read it, how to approve it, and what the operator does after approval.

Recommendations are namespaced custom resources. List them with the scalingrecommendations plural or the scalerec short name:

Terminal window
# All namespaces:
kubectl get scalingrecommendations -A
# One namespace:
kubectl get scalerec -n <namespace>

The printed columns come from the CRD:

NAME TARGET RISK APPROVED PHASE
web web low false pending
api api medium true verified
ColumnSourceMeaning
TARGET.spec.targetRef.nameThe HPA (or ScaledObject) the recommendation tunes.
RISK.spec.riskLevellow / medium / high, from the analysis.
APPROVED.spec.approvedWhether a human has approved it.
PHASE.status.phaseLifecycle state (see §6.5).

A recommendation is created with the same name as its target HPA, in that HPA’s namespace. The operator leaves existing recommendations alone, so your approval and any manual edits are never overwritten.

Terminal window
kubectl get scalerec <name> -n <namespace> -o yaml

Key fields under spec:

FieldMeaning
targetRef{ kind: HorizontalPodAutoscaler | ScaledObject, name } - what gets patched.
riskLevellow / medium / high.
summaryMdHuman-readable Markdown summary of the reasoning.
projectedSavingsUsdMonthlyEstimated monthly saving, when the analysis produced one.
configDiffA map of field → { from, to }: the exact change. Fields: min_replicas, max_replicas, target_cpu_pct, scale_down_cooldown_s.
scheduleOptional list of predictive windows: { startCron, durationMinutes, minReplicas }. Present only for forecasted recurring peaks.

Read the summaryMd for the why, and configDiff for the what. For example, a diff of min_replicas: { from: 10, to: 3 } with target_cpu_pct: { from: 50, to: 70 } proposes lowering the floor and raising the CPU target - trading idle headroom for cost.

Approval is a single edit to spec.approved. The operator applies it on the next tick.

Terminal window
kubectl patch scalerec <name> -n <namespace> \
--type merge -p '{"spec":{"approved":true}}'

You can review the diff first and approve in one motion, or edit interactively with kubectl edit scalerec <name> -n <namespace>. Until approved is true, nothing is changed on the live workload.

On the next tick after approval, the leader operator:

  1. Patches the target. For an HPA it sets minReplicas, maxReplicas, the CPU averageUtilization target, and/or the scale-down stabilization window, per the configDiff. For a KEDA ScaledObject it sets minReplicaCount, maxReplicaCount, and/or cooldownPeriod.
  2. Records the apply. status.phase becomes applied, status.appliedAt is stamped, and status.probationUntil is set to now + the probation window.

Apply requires a valid (or in-grace) license. If the operator is unlicensed, an approved recommendation is marked blocked instead of applied (see Licensing).

6.5 Probation, verification, and auto-rollback

Section titled “6.5 Probation, verification, and auto-rollback”

After the probation window (default 45 minutes), the verify pass re-reads the workload’s health and decides:

VerdictActionResulting phase
HealthyKeep the change.verified
Inconclusive (too little post-apply data)Extend probation.stays applied
Degraded, rollback enabledRevert to the previous config (from values).rolledBack
Degraded, rollback disabledHold for re-judgement (revert later if you re-enable rollback).degraded

The rollback restores exactly the values the operator changed, and runs regardless of license state - it only ever undoes the operator’s own change, so an expired license can never strand a degraded workload.

PhaseMeaning
pendingCreated, awaiting approval (or approved, not yet applied this tick).
appliedPatched onto the workload; on probation.
verifiedHealthy after probation. The terminal happy state.
rolledBackAuto-reverted after the change degraded health.
degradedDegraded but held (rollback was disabled); re-judged each cycle.
blockedApproved but not applied - the operator is unlicensed.
failedThe apply call itself failed (see status.detail and the logs).

When forecasting is enabled and a workload shows a strong recurring peak, the recommendation carries a schedule: one or more windows, each a KEDA-style startCron, a durationMinutes, and the minReplicas floor to hold during it. After approval:

  • KEDA ScaledObject targets: the operator installs the windows as KEDA cron triggers (named stepscale-cron-N, timezone UTC). KEDA then performs the time-based scaling; your own (non-cron) triggers are preserved untouched.
  • HPA targets: the operator itself raises minReplicas to the window floor inside each window and restores the baseline outside it.

status.scheduleActive reflects whether a schedule is currently being enforced. If a forecasted peak repeatedly fails to materialize (the pre-scaled floor sits idle), the operator retracts the schedule and restores the baseline, recording the reason in status.detail.

To inspect the active schedule on a KEDA target:

Terminal window
kubectl get scaledobject <name> -n <namespace> \
-o jsonpath='{.spec.triggers[?(@.type=="cron")]}{"\n"}'