Fleet management
A Fleet is a set of kind clusters described in one YAML
manifest. klimax fleet create -f reconciles the fleet into
existence — creating clusters in dependency order, several at a time — and
klimax fleet delete tears the whole thing down again.
Looking for the field-by-field schema? See the Fleet resource reference. This page is the how-to.
Why fleets
Running klimax cluster create a few times is fine for one or
two clusters. But a hub-and-spoke demo, a multi-region test, or a
service-mesh lab is a fixed topology you'll rebuild again and
again. A fleet manifest captures that topology once: check it into git,
hand it to a teammate, or feed it to CI, and everyone gets the same
clusters — same nums, same labels, same order.
A minimal fleet
Only cluster names are required; everything else defaults. This is a complete, valid manifest:
apiVersion: klimax.dev/v1alpha1
kind: Fleet
spec:
clusters:
- dev
- staging
Create it:
$ klimax fleet create -f fleet.yaml
klimax creates dev and staging, auto-assigning
each a free cluster num (and with it
a subnet, API port, and MetalLB pool slice), then merges both kubeconfig
contexts. A bare string is shorthand — expand any entry into an object to
override its options.
Creating a fleet is additive and idempotent
fleet create only ever creates. It detects which
clusters already exist and skips them; run it twice and the second run is
a no-op. Preview the plan without touching anything with
--dry-run:
$ klimax fleet create -f fleet.yaml --dry-run
$ klimax fleet create -f fleet.yaml # create what's missing
$ klimax fleet create -f fleet.yaml # again → "Nothing to do"
fleet create is not a full reconcile — it
does not prune or mutate clusters. Removing a cluster from the manifest
does not delete it, and editing an existing cluster's options has no effect
on the running cluster. To change a cluster, delete and re-create it.
Adopting existing clusters
A manifest can list a cluster that already exists but was created outside
the fleet — by hand, or as part of another fleet. fleet create
never relabels those silently: it prints them in the plan as
skip and warns that they were left unchanged.
Pass --adopt to pull them in. Adoption sets the
klimax.dev/fleet=<metadata.name> node label (plus any
per-cluster labels: from the manifest) on the running cluster —
nothing is re-created and no workload is disturbed:
$ klimax fleet create -f fleet.yaml --dry-run # foreign clusters show as "skip"
$ klimax fleet create -f fleet.yaml --adopt # they show as "adopt" and get relabelled
To adopt clusters without a manifest at all, name them directly:
$ klimax fleet adopt dev-fleet edge-1 edge-2
Adoption is label-only and reversible — re-adopt a cluster into another
fleet, or clear the label with
klimax cluster label <name> -l klimax.dev/fleet-.
Ordering with dependsOn
List the clusters an entry must wait for in dependsOn. klimax
builds a dependency graph (a DAG — cycles are rejected at validation) and
won't start a cluster until all of its dependencies are ready. Here a
hub comes up first, then two spokes in parallel:
apiVersion: klimax.dev/v1alpha1
kind: Fleet
metadata:
name: mesh-lab
spec:
maxParallel: 2
clusters:
- hub
- name: spoke-a
dependsOn: [hub]
- name: spoke-b
dependsOn: [hub]
Parallelism & failure strategy
spec.maxParallel caps how many clusters create at once
(0 or 1 = sequential). Independent clusters run
up to that cap; dependsOn ordering is always honoured. Two
error strategies control what happens on a failure:
spec.strategy | Behaviour on a failed cluster |
|---|---|
FailFast (default) | Stop scheduling new clusters; let in-flight ones finish, then report. |
ContinueOnError | Keep creating every cluster whose dependencies succeeded; report all failures at the end. |
Override the manifest's parallelism from the command line with
--max-parallel:
$ klimax fleet create -f fleet.yaml --max-parallel 3
Per-cluster options
Any entry can be an object that overrides options for just that cluster —
the cluster num, the topology region/zone,
which registry mirrors it uses, addons like metrics-server, and extra node
labels. spec.defaults sets values inherited by every entry
that doesn't override them. Most mirror
klimax cluster create
flags, expressed declaratively — and the manifest additionally lets you
pin a cluster's num, which the CLI always
auto-assigns. See the
Fleet resource reference for the
full schema.
Node labels
Every cluster klimax creates — fleet or single — gets its nodes labelled. Fleets add the fleet name; you can attach your own labels too.
| Label | Where it comes from |
|---|---|
managed-by=klimax | Always, on every klimax cluster. |
klimax.dev/fleet=<name> | Fleets with a metadata.name. |
topology.kubernetes.io/region, …/zone | Per-cluster region/zone (or the europe-west<num> defaults). |
| Custom key/value | The labels: map (fleet) or -l key=value (CLI). |
In a manifest, defaults.labels apply to all clusters and
per-cluster labels win on conflict:
spec:
defaults:
labels:
owner: platform-team
clusters:
- name: spoke-a
labels:
team: search
env: dev
The single-cluster equivalent uses repeatable -l flags:
$ klimax cluster create spoke-a -l team=search -l env=dev
The klimax fleet command
You've already seen klimax fleet create -f, which reads a
manifest. The rest of the klimax fleet family works on
live clusters, grouped by the
klimax.dev/fleet=<name> node label (set from a manifest's
metadata.name). Membership is whatever currently carries the
label — no manifest required — so it also catches clusters you labelled by
hand.
| Command | What it does |
|---|---|
klimax fleet list | Group live clusters by their klimax.dev/fleet label (-o text/json/yaml). |
klimax fleet describe <name> | Show one fleet's members with their num, ports, nodes, and labels. |
klimax fleet create -f <file> | Create the manifest's clusters — same engine as cluster apply -f (--dry-run, --max-parallel, --adopt). |
klimax fleet adopt <name> <cluster>… | Relabel existing clusters into the fleet — see Adopting existing clusters. |
klimax fleet delete <name> | Delete every member of that fleet, resolved by label (-y skips the prompt). |
klimax fleet delete -f <file> | Delete the manifest's clusters — same as cluster delete -f. |
klimax fleet label <name> -l k=v | Propagate node labels to every member (-l key- removes one). |
$ klimax fleet list
$ klimax fleet describe dev-fleet # members, nums, ports, nodes, labels
$ klimax fleet create -f fleet.yaml
$ klimax fleet adopt dev-fleet edge-1 # pull an existing cluster in
$ klimax fleet label dev-fleet -l tier=frontend # label the whole fleet at once
$ klimax fleet delete dev-fleet -y
fleet list/delete <name>/label <name>
work off the live label, not the manifest — handy after you've
added or relabelled clusters since applying. fleet create/
delete -f are thin aliases over the
cluster apply/delete -f paths.
Filter & delete by label selector
Beyond whole fleets, cluster list and cluster delete
take a kubectl-style label selector via
-l/--selector, matched against node labels:
$ klimax cluster list -l klimax.dev/fleet=dev-fleet # one fleet's members
$ klimax cluster list -l env=dev
$ klimax cluster delete -l env=test --yes # delete all that match
Mind the two meanings of -l: on cluster create
and … label it's --label key=value (a label to
set); on cluster list and cluster delete it's
--selector (a query to match).
Exporting a fleet
The inverse of fleet create -f. Labs often start ad-hoc —
a cluster here, another one there — and only later turn out to be worth
keeping. klimax fleet export reads the live clusters and
writes a Fleet manifest, so you can capture one into a reproducible file
instead of reconstructing it by hand.
# by name
$ klimax fleet export dev staging > fleet.yaml
# by label selector
$ klimax fleet export -l klimax.dev/fleet=mesh > fleet.yaml
# or pick them interactively
$ klimax fleet export > fleet.yaml
With no names and no selector it opens the same multi-select picker
cluster delete uses: ↑/↓ to move, Space to toggle, a
for all, Enter to confirm.
Each cluster contributes its name, num,
nodeVersion, region/zone and any
custom node labels. --nums (on by default) records the num so
re-applying the manifest pins the same API ports; pass
--nums=false for a manifest that can land anywhere.
--name sets metadata.name, which otherwise comes
from the clusters' shared klimax.dev/fleet label and falls
back to exported.
Some things cannot be recovered from a running cluster.
dependsOn ordering, registry mirror selection and
addons leave no trace in the live state, so they are not
exported. If your fleet relies on them, add them back by hand — otherwise
the manifest will create the same clusters, but not in the same way.
Tearing down a fleet
Fastest is by fleet name — klimax fleet delete <name>
removes every live member. Or delete from the manifest with
klimax fleet delete -f, which works in
reverse-dependency order and only touches clusters that
are both in the manifest and running. Both prompt once unless you pass
-y:
$ klimax fleet delete dev-fleet # by fleet label
$ klimax fleet delete -f fleet.yaml -y # by manifest, no prompt (CI)
This removes the clusters, not the VM. To reclaim everything — VM,
clusters, and the host route — use klimax destroy (see
Reset & reinstall).
See also
- Fleet resource — every manifest field, its type, default, and validation rules.
- CLI reference — Clusters —
apply,delete,create, and their flags. - Getting started — the single-cluster basics fleets build on.