Documentation menu

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.strategyBehaviour on a failed cluster
FailFast (default)Stop scheduling new clusters; let in-flight ones finish, then report.
ContinueOnErrorKeep 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.

LabelWhere it comes from
managed-by=klimaxAlways, on every klimax cluster.
klimax.dev/fleet=<name>Fleets with a metadata.name.
topology.kubernetes.io/region, …/zonePer-cluster region/zone (or the europe-west<num> defaults).
Custom key/valueThe 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.

CommandWhat it does
klimax fleet listGroup 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=vPropagate 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