klimax is now marina. Same tool, new name since v0.3. Existing install? Migrate with marina migrate →
Documentation menu

Fleet management

A Fleet is a set of kind clusters described in one YAML manifest. marina fleet create -f reconciles the fleet into existence — creating clusters in dependency order, several at a time — and marina 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 marina 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: marina.run/v1alpha1
kind: Fleet
spec:
  clusters:
    - dev
    - staging

Create it:

$ marina fleet create -f fleet.yaml

marina 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:

$ marina fleet create -f fleet.yaml --dry-run
$ marina fleet create -f fleet.yaml            # create what's missing
$ marina 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 marina.run/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:

$ marina fleet create -f fleet.yaml --dry-run   # foreign clusters show as "skip"
$ marina fleet create -f fleet.yaml --adopt     # they show as "adopt" and get relabelled

To adopt clusters without a manifest at all, name them directly:

$ marina 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 marina cluster label <name> -l marina.run/fleet-.

Ordering with dependsOn

List the clusters an entry must wait for in dependsOn. marina 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: marina.run/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:

$ marina 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 marina 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 marina 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=marinaAlways, on every marina cluster.
marina.run/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:

$ marina cluster create spoke-a -l team=search -l env=dev

The marina fleet command

You've already seen marina fleet create -f, which reads a manifest. The rest of the marina fleet family works on live clusters, grouped by the marina.run/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
marina fleet listGroup live clusters by their marina.run/fleet label (-o text/json/yaml).
marina fleet describe <name>Show one fleet's members with their num, ports, nodes, and labels.
marina fleet create -f <file>Create the manifest's clusters — same engine as cluster apply -f (--dry-run, --max-parallel, --adopt).
marina fleet adopt <name> <cluster>…Relabel existing clusters into the fleet — see Adopting existing clusters.
marina fleet delete <name>Delete every member of that fleet, resolved by label (-y skips the prompt).
marina fleet delete -f <file>Delete the manifest's clusters — same as cluster delete -f.
marina fleet label <name> -l k=vPropagate node labels to every member (-l key- removes one).
$ marina fleet list
$ marina fleet describe dev-fleet                  # members, nums, ports, nodes, labels
$ marina fleet create -f fleet.yaml
$ marina fleet adopt dev-fleet edge-1              # pull an existing cluster in
$ marina fleet label dev-fleet -l tier=frontend    # label the whole fleet at once
$ marina 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:

$ marina cluster list -l marina.run/fleet=dev-fleet   # one fleet's members
$ marina cluster list -l env=dev
$ marina 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. marina 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
$ marina fleet export dev staging > fleet.yaml

# by label selector
$ marina fleet export -l marina.run/fleet=mesh > fleet.yaml

# or pick them interactively
$ marina 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 marina.run/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 — marina fleet delete <name> removes every live member. Or delete from the manifest with marina 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:

$ marina fleet delete dev-fleet          # by fleet label
$ marina 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 marina destroy (see Reset & reinstall).

Fleet-wide names and certificates

Every fleet has its own DNS zone, <fleet>.demo.internal. Any member can publish a name there by annotating a Service — external-dns.kubernetes.io/hostname: gateway.lab.demo.internal — and every member gets a *.<fleet>.demo.internal wildcard certificate in the Secret default/marina-fleet-wildcard-tls. Adopted clusters get both; the last member's deletion removes the zone and its certificates. Which name to use when: the Hostname playbook.

See also