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.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:
$ 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.
| Label | Where it comes from |
|---|---|
managed-by=marina | Always, on every marina cluster. |
marina.run/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:
$ 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.
| Command | What it does |
|---|---|
marina fleet list | Group 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=v | Propagate 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
- 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.