Zaroz
Workload guides

Scale a Workload to more units

This guide continues from Deploy a Workload from a public image. Read Fixed and autoscaled policies first if "units" is new to you.

It uses the api helper from the deploy guide, and these variables: PROJECT_ID (from the subscription) and SERVICE_ID (the service instance). The routes live under /projects/{project_id}/service-instances/{id}/units.

TerminalCode
export UNITS="$ZAROZ_API/projects/$PROJECT_ID/service-instances/$SERVICE_ID/units"

API status

The units routes are used by the console and are tagged console-only in the API reference. They accept your session token or a personal access token.

1. See what you have

TerminalCode
curl -s "$UNITS" -H "Authorization: Bearer $ZAROZ_TOKEN" | jq '{scalable, max_units, included_units, multi_unit_in_use, volume_locked}'
TypeScriptCode
const base = `/projects/${projectId}/service-instances/${serviceId}/units`; const units = await api("GET", base); console.log(units.scalable, units.max_units, units.included_units, units.volume_locked); for (const u of units.data) console.log(u.ordinal, u.state, u.billing_class);
Code
base = f"/projects/{project_id}/service-instances/{service_id}/units" units = api("GET", base) print(units["scalable"], units["max_units"], units["included_units"], units["volume_locked"]) for u in units["data"]: print(u["ordinal"], u["state"], u["billing_class"])

scalable must be true and volume_locked false. billing_class is included for units the plan covers and extra for the rest.

2. Quote a fixed policy of 3 units

Nothing is saved by a quote.

TerminalCode
curl -s -X POST "$UNITS/policy/quote" \ -H "Authorization: Bearer $ZAROZ_TOKEN" -H "Content-Type: application/json" \ -d '{"mode":"fixed","min_units":3}'
TypeScriptCode
const quote = await api("POST", `${base}/policy/quote`, { mode: "fixed", min_units: 3 }); console.log(quote.extra_units, quote.hourly_cents, quote.monthly_cents);
Code
quote = api("POST", f"{base}/policy/quote", {"mode": "fixed", "min_units": 3}) print(quote["extra_units"], quote["hourly_cents"], quote["monthly_cents"])

Giving only min_units sets max_units to the same number. monthly_cents is the most that policy can cost in a month; the arithmetic is in Billing.

3. Apply it

TerminalCode
curl -s -X PATCH "$UNITS/policy" \ -H "Authorization: Bearer $ZAROZ_TOKEN" -H "Content-Type: application/json" \ -d '{"mode":"fixed","min_units":3}'
TypeScriptCode
const policy = await api("PATCH", `${base}/policy`, { mode: "fixed", min_units: 3 }); console.log(policy.mode, policy.min_units, policy.max_units);
Code
policy = api("PATCH", f"{base}/policy", {"mode": "fixed", "min_units": 3}) print(policy["mode"], policy["min_units"], policy["max_units"])

A fixed policy applies at once: two units start. List the units again and watch their state move to running.

4. Autoscale between 1 and 4, targeting 60% CPU

TerminalCode
curl -s -X PATCH "$UNITS/policy" \ -H "Authorization: Bearer $ZAROZ_TOKEN" -H "Content-Type: application/json" \ -d '{"mode":"autoscaled","min_units":1,"max_units":4,"cpu_target_percent":60,"spend_cap_cents":1500}'
TypeScriptCode
await api("PATCH", `${base}/policy`, { mode: "autoscaled", min_units: 1, max_units: 4, cpu_target_percent: 60, spend_cap_cents: 1500, });
Code
api("PATCH", f"{base}/policy", { "mode": "autoscaled", "min_units": 1, "max_units": 4, "cpu_target_percent": 60, "spend_cap_cents": 1500, })

An autoscaled policy needs a CPU target, a memory target or a schedule rule. Omitted fields keep their value; send null to clear a nullable one, for example "spend_cap_cents": null.

5. Watch what it does

Decisions say what the autoscaler did and why; the count series shows how many units ran.

TerminalCode
curl -s "$UNITS/decisions?page_size=5" -H "Authorization: Bearer $ZAROZ_TOKEN" | jq '.data[] | {at, action, summary}' curl -s "$UNITS/count?window=24h" -H "Authorization: Bearer $ZAROZ_TOKEN" | jq '{included, markers}'
TypeScriptCode
const decisions = await api("GET", `${base}/decisions?page_size=5`); for (const d of decisions.data) console.log(d.at, d.action, d.summary); const count = await api("GET", `${base}/count?window=24h`); console.log(count.included, count.markers.length);
Code
decisions = api("GET", f"{base}/decisions", page_size=5) for d in decisions["data"]: print(d["at"], d["action"], d["summary"]) count = api("GET", f"{base}/count", window="24h") print(count["included"], len(count["markers"]))

6. Go back to one unit

TerminalCode
curl -s -X PATCH "$UNITS/policy" \ -H "Authorization: Bearer $ZAROZ_TOKEN" -H "Content-Type: application/json" \ -d '{"mode":"fixed","min_units":1}'
TypeScriptCode
await api("PATCH", `${base}/policy`, { mode: "fixed", min_units: 1 });
Code
api("PATCH", f"{base}/policy", {"mode": "fixed", "min_units": 1})

Units that are scaled away stop billing at once. If a change is refused, the details field starts with a reason code, for example volume_locks_to_one_unit or a limit (see Limits).

Last modified on