On this page
Cloud hosts
A cloud host is a fleet host Stado rents from a cloud to build on. It is an
ordinary registry target, reached over SSH with its own fleet key, so
stado host kompilator <host> … builds there like on any other host. It carries
one more declaration, targets[].cloud, and it is returned once it stands
idle. Azure is the provider this release implements.
stado cloud host create NAME --provider azure --location LOCATION --size SIZE --disk-gb GIB --idle-minutes MINUTES [--json]
stado cloud host list --provider azure [--json]
stado cloud host delete NAME --provider azure [--json]
stado cloud host reap --provider azure [--apply] [--json]
What it needs
- Azure enabled in the profile (
providers, notproviders_disabled; the environment'sWC_PROVIDERSandWC_DISABLED_PROVIDERSselect it for one invocation) and the compute bindingsazure.subscription_id,azure.resource_group,azure.vnet,azure.subnet,azure.image_urnandazure.vm_username. A missing one is refused naming every missing key:a cloud host on Azure is addressed with bindings this deployment does not declare: <keys>;stado config setdeclares each. - The location's subnet,
<azure.vnet>-<location>/<azure.subnet>; Stado creates no virtual network. cloud_hosts.admit_fromin the registry: the fleet hosts that reach cloud hosts, for examplestado registry set --path cloud_hosts --value '{"admit_from":["build-host","always-on-mac"]}'. Without it:the registry names no host whose address a cloud host admits (cloud_hosts.admit_from is absent); ….- The operator's Azure credit floor ruling, read by the Azure credit gate.
- No Azure Policy denying the resources a host is made of (application
security groups, public addresses, interfaces, VMs, disks). A deny answers
at the first of them,
the application security group stado-cloud-hosts-<location> was not made: … HTTP 403: RequestDisallowedByPolicy …naming the assignment, and nothing is created.
Create
create does these in order and stops at the first that fails:
- Refuses a name already registered (
target '<name>' is already registered) and a name that is not a target identifier. - Prices the size at the highest on-demand hour any configured location
quotes and prints the projected hourly burn, that hour plus the recorded
hour of every cloud host already declared:
projected hourly burn: <total> USD (<name> <size> at <hour> USD, <where priced>; <n> cloud host(s) already running at <hours> USD). The credit gate then takes one hour of all of them from the balance and refuses unless what remains is above the floor:creating cloud host <name> (<size>) in <location> is refused: the Azure credit balance <balance> USD less one hour of <size> (…) and one hour of the machines already running (<hours> USD) is not above the floor <amount> <currency> (the operator's ruling <id>: "<his words>"); …. Otherwise it printscredit: balance <balance> USD, <after> USD after one hour of all of them, above the floor …. - Asks each
admit_fromhost for its public address over its host channel (curlof<api.url>/api/egress, which the product site answers with the address the request came from) and records the answers incloud_hosts.egresswith the time they were read. - Admits exactly those addresses on SSH (port 22): the location gets the
application security group
stado-cloud-hosts-<location>, and when the subnet carries a security group of its own, that group gets the rulestado-cloud-hostsadmitting the addresses to the application group only, at the first priority from 100 no other rule holds. Every other interface in the subnet is left as it was. Every cloud host already declared is readmitted with the same addresses. - Mints the host's fleet key as
stado fleet key generatedoes. - Creates the host's public address (static, Standard), its security group
admitting the addresses on SSH, its interface in the subnet and the
application group, and the VM holding the key's public half. cloud-init
installs the build toolchain (build-essential, pkg-config, OpenSSL headers,
clang, cmake, protoc, git, rsync, Node.js and npm from the image, rustup in
the account's home) and an sshd drop-in refusing passwords. Each revision's
rust-toolchain.tomlchooses its Rust toolchain. A failure removes what was created and names what could not be removed. - Enrolls the host through the verified
fleet enrollpath. A host that cannot be enrolled is deleted again, since nothing would return it. - Records
targets[].cloud: provider, location, size, disk, the priced hour and where it was priced, the idle minutes, the address, the VM id and when it was created. - Waits for cloud-init to finish (
cloud-init status --wait) and asks for$HOME/.cargo/bin/rustc --version(rustup's prefix; kompilator is compiled with that rustc),node --versionandnpm --version. A first boot that did not finish cleanly is refused naming/var/log/cloud-init-output.logon the host.
Reap
A cloud host is busy while a managed run stands in ~/.stado/work/runs (every
stado host kompilator run lives there until it ends) or a cargo or rustc
process runs. Otherwise it has stood idle since its run area last changed, or
since it was created if no run ever came. reap first measures and readmits
the fleet's addresses as create does, then lists each host as busy,
idle, reapable (idle past its minutes) or unread with the cause; a host
that cannot be read is never judged idle. With --apply, each reapable host
is deleted as delete deletes it (reaped, or reap_failed with the cause,
which exits non-zero).
The coordinator runs the applied pass on every tick when Azure is enabled in
its profile and a cloud host is declared, and logs cloud-host reaper: … for
each host it reaped, failed to reap or could not read.
Delete
delete refuses a name the registry declares no cloud host for (the registry declares no Azure cloud host <name> (it declares …)), then deletes
the VM with its OS disk, the interface, the security group and the public
address, each followed to the end of Azure's operation and confirmed gone.
Only then does it remove the registry entry and the fleet key. A resource
Azure still holds keeps the entry: <name> is still registered because Azure did not release everything: …; deleting it again retries.
List
list prints each declared host with Azure's power state of its VM
(running, deallocated, absent, or unread: <cause>), location, size,
address, priced hour, idle minutes and creation time, and the hourly burn of
the running ones. --json carries the same rows and cloud_hosts.egress.
Source: this website