Request a transient scale Unreleased: coming in v1.3
Change how many Instances one OMENative component runs with the alpha kubectl ome scale command, until its autoscaler or OME sets the count again.
kubectl ome scale changes how many Instances one OMENative component runs, and leaves the InferenceService and its other components alone. It checks the component first, and refuses while other work is in progress on it or when the count is outside its bounds. The change is transient: the component's autoscaler, or OME, can set the count again at any time. For a lasting change, edit the component's minReplicas and maxReplicas instead. The command is alpha, so its flags and behavior can change between releases.
The example service¶
The steps add a third engine Instance to chat, a prefill-decode InferenceService in prod, for a burst of long prompts. The engine runs prefill and the decoder runs decode, each with its own InferenceReplica, so the request leaves the decoder and the router alone. The engine's autoscaler block, which is alpha, sets the class External, so OME runs no autoscaler for the engine and keeps the count you set:
apiVersion: ome.io/v1beta1
kind: InferenceService
metadata:
name: chat
namespace: prod
spec:
deploymentMode: OMENative
model:
name: llama-3-2-1b-instruct
runtime:
name: srt-llama-3-2-1b-instruct-pd
engine:
minReplicas: 2
maxReplicas: 4
autoscaler:
class: External
decoder:
minReplicas: 1
maxReplicas: 1
router:
minReplicas: 1
maxReplicas: 1scale accepts 2 to 4 engine Instances, from minReplicas to maxReplicas. --replicas counts Instances: here one pod each, and on a multi-node component a leader and its workers, which OME adds or removes as a unit. To deploy the service yourself, follow Serve a prefill-decode model, which lists what this model and runtime need. The third engine Instance needs a fourth GPU node.
How long a request lasts¶
Your count lasts until the owner of the count sets its own. The dry run in Step 1 shows the owner's class in its verified ownership row:
| Class | Who sets the count again | How long your request lasts |
|---|---|---|
HPA, the default |
The HorizontalPodAutoscaler that OME creates. | The HPA can replace it at once with the count its metrics call for. |
KEDA |
The ScaledObject that OME creates, through KEDA's HPA. | The same as HPA. |
External |
Your own autoscaler, if you run one. See Bring your own autoscaler. | Until your autoscaler, or you, change it. OME keeps any count of 1 or more. |
None |
OME, which sets it back to minReplicas. |
A few moments: your change prompts OME to set the count back. |
Step 1: Preview with a dry run¶
Every request needs --override-autoscaler and --yes, whatever the class. --override-autoscaler accepts that the owner can overwrite your count, and --yes confirms the request, since scale never prompts. So preview each request with a client dry run, which runs every check and sends nothing:
kubectl ome scale chat -n prod --component engine --replicas 3 --override-autoscaler --yes --dry-run clientThe preview on stderr shows /scale spec.replicas as 2 -> 3, bounds as 2..4 and verified ownership as External / external. The result on stdout shows accepted and applied as No. Preview describes every row. --dry-run server also has the API server check the request, including your permission to patch inferencereplicas/scale, and stores nothing.
Step 2: Submit the request¶
Run the same command without --dry-run:
kubectl ome scale chat -n prod --component engine --replicas 3 --override-autoscaler --yesThe command repeats its checks just before it sends the request, and refuses if anything changed. The result shows target as InferenceReplica/prod/chat-engine, replicas as 2 -> 3, and accepted and applied as Yes. That means the API server stored the count, not that the new Instance is up.
Step 3: Check the outcome¶
Run the follow-up command from the result, with --live-scale to read the engine's InferenceReplica too:
kubectl ome autoscale status chat -n prod --live-scaleThe engine's LIVE-SPEC shows 3, the count you asked for. Right after the request, LIVE-EVIDENCE can show Stale; if it does, run the command again. If LIVE-SPEC later shows another count, the owner has set its own.
Then list the Instances:
kubectl ome instance list chat -n prodA third engine Instance appears. Wait until its PHASE is Ready. The decoder and the router keep one Instance each.
In a script, kubectl ome wait --for=replicas=current with --component=engine --replicas=3 waits until the engine asks for and reports 3 Instances. It exits 0 on a match, even before the new Instance is ready, and 2 when it times out, after 60 seconds or the --timeout you set.
Troubleshooting¶
When scale refuses, it prints error: and the reason, changes nothing, and exits 1. These are the errors you're most likely to see. Refusals lists every refusal.
Work is active on the component¶
error: manual scale refused: selected lifecycle, migration or rollout work is active means the component is busy. One of its Instances is being created, updated, restarted, migrated or deleted, or a migration, rollout or rollback is in progress. Instances that an autoscaler or your earlier request added or removed count too. Check PHASE in kubectl ome instance list chat -n prod, and run kubectl ome migration status chat -n prod. scale needs the engine's PHASE in kubectl ome rollout status chat -n prod to be Stable or Unknown. If the engine is in a rollout group, its GROUP-PHASE must be Stable too.
The count is out of bounds¶
error: manual scale replicas must be positive and within verified bounds and partitions means --replicas is outside the component's minReplicas to maxReplicas, or below the partition of its rolling update. scale reads the maximum from maxReplicas in the InferenceService or its runtime. Without one, it accepts only the minimum, even when the controller's replica defaults give the autoscaler a wider range. To move the bounds, change minReplicas and maxReplicas.
The command line is rejected¶
error: invalid scale arguments; require one service, component engine|decoder|router, positive base-10 --replicas, supported output/dry-run and valid namespace/context/timeout means the command line is incomplete or malformed, as when you pass --override-autoscaler without --yes. error: manual scale is transient and requires --override-autoscaler --yes for every ownership class means --override-autoscaler is missing. Every class needs it.
A read fails¶
error: required Kubernetes API request failed; check access and connectivity means a read failed. Check the name, the namespace and your permissions. Without -n, scale uses your kubeconfig context's namespace.
The service doesn't run on OMENative¶
error: action refused: active runtime is unavailable, inconsistent or unbound means no component of the service runs on OMENative, or the CLI couldn't resolve the service's serving runtime. Deployment modes shows how to opt in.
The component can't be verified¶
These errors mean the CLI couldn't confirm who owns the count, or that something changed between its reads:
error: manual scale source evidence is unavailable or inconsistenterror: manual scale requires complete current selected replica and Scale evidenceerror: action refused: controller safety evidence is stale or inconsistenterror: manual scale source changed; inspect current status and prepare a new request
Usually the controller is still catching up with a recent change: wait, check LIVE-EVIDENCE in kubectl ome autoscale status chat -n prod --live-scale, and run the dry run again. Also check that the component exists and runs on OMENative.
A promote or rollback request is present¶
error: action refused: a rollout promote or rollback mailbox is present means the InferenceService has an ome.io/rollout-promote or ome.io/rollout-rollback annotation. A promote annotation left from an earlier rollout can stay. Remove it with kubectl annotate inferenceservice chat -n prod ome.io/rollout-promote-. A rollback annotation stays until a different target revision appears, as Roll back the canary explains. To remove it yourself, run:
kubectl annotate inferenceservice chat -n prod ome.io/rollout-rollback-inferenceservice.ome.io/chat annotatedRemoving it doesn't retry the rejected revision.
The patch is rejected as a conflict¶
error: guarded scale precondition rejected; inspect current status and prepare a new request means the InferenceReplica changed after the CLI read it, often because an autoscaler or OME updated it. Nothing changed, and the command exits 3. Run a new dry run before you try again.
The outcome is unknown¶
error: scale request outcome unknown; inspect kubectl ome autoscale status before preparing another request means the request failed without showing whether the API server stored it, as after a timeout or a network error. Check LIVE-SPEC in kubectl ome autoscale status chat -n prod --live-scale before you run scale again: the CLI never retries. You also see this error when you lack permission to patch inferencereplicas/scale, and then nothing changed. A server dry run checks that permission.
Clean up¶
When the burst ends, and no engine Instance is being created, scale the engine back to 2 the same way:
kubectl ome scale chat -n prod --component engine --replicas 2 --override-autoscaler --yesThe result shows replicas as 3 -> 2. OME drains and deletes one engine Instance, keeping Ready Instances first and lower indices next, as When the count changes describes.
Next steps¶
- kubectl ome scale: every flag, output row and refusal.
- Component autoscaling: set
minReplicas,maxReplicasand the autoscaler for a lasting change. - Bring your own autoscaler: hand a component's count to an autoscaler that you run.
- Migration and transient scale: which Instances OME keeps when the count changes.