User guide: kaironctl bulk scale by label selector
kaironctl scale machineset NAME --replicas N (see
machine-sets.md) always addressed exactly one named
MachineSet. That's fine for a single fleet, but scaling every MachineSet
that makes up an environment -- say, everything labeled env=staging --
down to zero before a maintenance window, or back up together afterward,
meant a shell loop around kaironctl get -o output or kubectl scale -l.
This adds the same --selector convention
kaironctl delete and
kaironctl get already have, to scale.
Usage
kaironctl scale machineset --selector k=v [--selector k2=v2 ...] --replicas N [--dry-run] [--namespace NS]
--selector is repeatable; every key=value pair given must match (logical
AND, never OR), using the exact same label-matching rule
(model.LabelsMatch) delete/get's own --selector already use.
--replicas sets the same target replica count on every matched
MachineSet -- this is deliberately narrower than edit's per-object flags
(see below for why).
$ kaironctl scale machineset --selector env=staging --replicas 0 --dry-run
machineset/api (dry-run, not scaled)
machineset/web (dry-run, not scaled)
machineset/worker (dry-run, not scaled)
$ kaironctl scale machineset --selector env=staging --replicas 0
machineset/api scaled to 0 replicas
machineset/web scaled to 0 replicas
machineset/worker scaled to 0 replicas
$ kaironctl scale machineset --selector team=payments,tier=nightly --replicas 3
no machinesets matched selector; nothing to scale
Only machineset is supported, since it's the only kind scale supports at
all -- there is no kind switch to generalize here the way delete's
matchingNames/deleteByKindName needs one.
Why --selector was added to scale but not to edit
kaironctl edit (migrationpolicy, snapshotschedule, quota, budget, machine)
each expose several independent fields per kind -- applying the same
--max-concurrent or --priority value to every object a selector matches
is a much less obviously safe or wanted operation than "scale everything
matching this selector to the same N," since those objects are far more
likely to genuinely need different values from each other. scale mutates
exactly one field (spec.replicas), so a bulk caller applying one target
value to every match is the natural, common case rather than an edge case
-- the same reasoning kaironctl-bulk-delete.md gives for why bulk deletion
made sense for delete (a single, uniform action -- "gone") but not
originally for a hypothetical bulk edit. --selector was intentionally
not added to edit for this reason.
Why an empty selector refuses to run, on purpose
$ kaironctl scale machineset --selector --replicas 0
error: invalid key=value "": want key=value
Same rule as bulk delete: --selector must resolve to a genuinely
non-empty key=value map, since model.LabelsMatch already treats an
empty selector as matching nothing, not everything. Without this
refusal, a mistyped or empty --selector would silently match zero
MachineSets and look like a successful no-op instead of surfacing the
mistake. --dry-run is a second, independent safety net on top of that: it
runs the exact same selector-matching logic and lists precisely what a real
run would scale, without patching anything.
Real limits today (first cut)
- No transaction, no rollback. Each match is patched one object at a
time by calling the exact same single-object
kc.PatchMachineSetkaironctl scale machineset NAME --replicas Nalready uses, in sorted-by-name order. If patching the third of five matches fails (a network blip, an RBAC denial, a validating-webhook rejection), the first two are already scaled, kaironctl exits non-zero immediately, and the remaining two are left untouched -- nothing retries or continues past the first error. Re-running the exact same command is the recovery path. - No
--allshortcut. There is deliberately no way to match "everyMachineSet" without at least one real--selectorpair -- see above. - One target value for every match, not a per-object delta (e.g. no
"scale each match by +1"). Matches with different current replica counts
all end up at the same
N. - Selector matching, not a general query language.
--selectoris stillmodel.LabelsMatch's plain equality-per-key semantics (no set-basedin/notin, no!=), the same limit every other selector in Kairon already has today. - No new RBAC. This reuses exactly the
list/patchverbs onmachinesetskaironctl scalealready needed -- nothing about the RBAC surface changes, andscripts/check_rbac_coverage.pywas re-run to confirm.