Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12
○Not yet marked complete on this device.
One cluster has an answer to “where is VM 141”: the cluster. Four clusters do
not, and everything that used to be a single lookup becomes a search.
That is the shape of the whole problem. Nothing about operating a fleet is
conceptually new — inventory, change, alerting, on-call — but every one of them
acquires an extra dimension, and the tooling that was adequate at one cluster
quietly stops being adequate at three.
Inventory: one query per cluster, one table
The single most useful cluster-wide endpoint is /cluster/resources. It returns
every node, storage, guest and pool in one call, which is exactly the thing you
need per cluster to build a fleet view.
Read-only / Safeeverything this cluster knows about, in one call— Read-only. /cluster/resources returns nodes, storages, guests and pools with their status. --type narrows it. This is the endpoint the GUI resource tree is built from.
pvesh get /cluster/resources --output-format json | jq -r '.[] | [.type, .id, .node // "-", .status // "-"] | @tsv' | head -20
pvesh get /cluster/resources --type vm --output-format json | jq 'length'
Read-only / Safea fleet inventory, stamped with the cluster name— Read-only. Iterates clusters defined in a table you control, queries each one with an auditor token, and emits one TSV with a cluster column. Replace the token lookup with your secret store; the shape is the point.
declare -A FLEET=(
[site-a]="192.0.2.10"
[site-b]="192.0.2.60"
[site-c]="192.0.2.110"
)
for cluster in "${!FLEET[@]}"; do
host="${FLEET[$cluster]}"
token="$(cat "/etc/fleet/tokens/${cluster}")"
curl -sS --fail \
--header "Authorization: PVEAPIToken=fleet-audit@pve!ro=${token}" \
"https://${host}:8006/api2/json/cluster/resources?type=vm" \
| jq -r --arg c "$cluster" '.data[] | [$c, .vmid, .name // "-", .node, .status] | @tsv'
done | sort
The receiving identity for this should be an auditor: a user with PVEAuditor
on /, a privilege-separated token, and nothing else. It is read-only by
construction, so a leak of a fleet inventory token is an information disclosure
rather than an outage.
Alerting: two levels, and do not merge them
The instinct at cluster number two is to point everything at one alert pipeline.
That is right for delivery and wrong for authorship, because two genuinely
different classes of alert exist.
Per-cluster alerts are the ones you already have. A node down, a pool
approaching full, a failed backup job, a Ceph health warning, an HA fencing
event. Their scope is one cluster, they are meaningful without reference to any
other cluster, and PVE’s own notification system can raise many of them.
Fleet alerts are the ones that do not exist at one cluster and cannot be
computed inside one:
Fleet alert
Why one cluster cannot raise it
A cluster has stopped reporting entirely
The silent cluster is the one that would have told you
Version skew has exceeded policy
Requires comparing versions across clusters
A configuration difference has appeared since yesterday
Requires the drift report from the previous lesson
Aggregate capacity headroom is below the level needed to lose a site
Requires summing across clusters
A guest exists on two clusters with the same identity
Requires seeing both
The migration campaign has stalled
Requires state that spans the boundary
The most important of these is the first. Absence of signal is the failure
mode that a per-cluster alerting design cannot see, because every alert it
knows how to raise depends on the cluster being alive enough to raise it.
Whatever aggregates your fleet must have a heartbeat per cluster and must alert
on its absence, with a threshold shorter than the time it takes for that
cluster’s silence to matter.
Staged change across clusters
The single biggest operational gain from having several clusters is that a
change no longer has to land everywhere at once. That gain is only realised if
you actually stage it, and staging has four components.
An order, written down. Least critical to most critical, with the
validation cluster first. Not “we will start with whichever is convenient”.
A soak time between stages, defined in advance. Long enough for the failure
mode you are worried about to appear. For a kernel or microcode change that
means at least one full business cycle and one backup cycle; for a firewall rule
it may be an hour. The number should come from the failure you are guarding
against, not from the calendar.
Abort criteria, written before you start. “If any of these is true, stop and
do not proceed to the next cluster.” Concrete and observable: a fencing event, a
failed backup, a specific error in a specific log, a latency threshold. Criteria
authored after a stage has gone wrong are negotiated criteria.
A rollback that has been tested at least once, on the validation cluster.
On-call across a fleet
Three changes to the on-call model, in descending order of how often they are
skipped.
1. Every alert names its cluster, first. Not in a label at the bottom, not
implied by the node name — in the title. The responder’s first action is
opening the right GUI, and an alert that does not say which one costs a minute
of confusion at the worst time.
2. Every runbook starts by establishing which cluster. Runbooks written for
a single cluster start at step one with a diagnostic command. Fleet runbooks
need a step zero: identify the cluster, open its baseline document, note its
version and its known differences. Part XXII’s runbook material applies; the
addition is small and the omission is expensive.
3. Credentials and access must already exist for every cluster. The
responder who can log in to two of three clusters is a responder who will
escalate at 3 a.m. for an access problem. Access to every cluster is part of
the on-call rotation’s prerequisites, and it should be tested when someone joins
the rotation rather than when they are first paged.
What to centralise, and what not to
Centralise
Keep per cluster
Metrics, logs and dashboards, with a cluster label
The PVE notification targets, so a cluster can still shout when the aggregator is down
Inventory and CMDB
Backup jobs and windows, which legitimately differ by site
The configuration baseline and drift report
HA rules and groups, which are per-cluster by nature
The local console and IPMI path, which must not depend on the central system
Backup verification results
The restore capability itself: each cluster must be restorable without the others
The line running through the right-hand column is independent recoverability.
A fleet is only as resilient as its ability to lose the central layer and keep
operating. If losing the aggregator means losing alerting, or losing PDM means
losing the ability to manage a cluster, you have re-created the single fault
domain that splitting was supposed to remove — just one level up.
Key takeaways
/cluster/resources is the one call that returns every node, storage, guest
and pool for a cluster, and it is the right basis for a fleet inventory.
No PVE API response names its own cluster. Identity is added by the
collector, and inferring it from node names breaks the first time someone
names a node inconsistently.
Fleet inventory should run as a privilege-separated PVEAuditor token per
cluster, so a leak is disclosure rather than an outage.
Per-cluster alerts and fleet alerts are different classes. The essential fleet
alert is a heartbeat per cluster, because absence of signal is invisible to
every threshold rule you own.
Stage changes with a written order, a soak time derived from the failure mode,
abort criteria authored before you start, a tested rollback, and an end date
that stops temporary skew becoming permanent.
A validation cluster must match production’s shape — storage type, topology
class, HA and Ceph usage — even if it does not match its size. If it does not,
say what it validates and what it does not.
On-call needs the cluster named in the alert title, a step zero in every
runbook that identifies the cluster, and credentials for every cluster tested
before the first page.
Centralise metrics, inventory, baselines and runbooks. Keep per-cluster
notification targets, console access and restore capability, so losing the
central layer is a degradation and not an outage.
Knowledge check
Knowledge check · 5 questions
Q1. A fleet dashboard is built by querying /cluster/resources on each of four clusters and merging the results. Rows keep appearing under the wrong cluster. What is the design error?
Q2. Three clusters report to one Prometheus. A firewall change silently blocks scraping of cluster C on Friday. Nothing fires all weekend. What rule was missing?
Q3. Which of these belong in a staged cross-cluster rollout record before the first stage begins? Select all that apply.
Q4. Once a central aggregation layer such as PDM or a shared Prometheus is in place, per-cluster notification targets can be removed to avoid duplicate alerts.
Q5. A three-node cluster with local ZFS is proposed as the validation stage for an upgrade that will later land on two twenty-node hyper-converged Ceph clusters. What is the correct position?
Passing score: 75%. Answers are checked in this browser.