Cluster & node upgrades
kcore nodes run NixOS. Host upgrades move the system forward using an immutable flake revision (flakeRef + flakeRev) while the controller orchestrates prepare/activate work on each node. Workloads (VMs/containers) use the normal lifecycle APIs; they are not upgraded by this flow.
These pages match one kcore release. The GitHub Release for that version includes cluster-update-X.Y.Z.yaml. Community Edition nodes fetch that git commit and compile it. A later private channel will serve prebuilt closures of newer versions, the provisioner, and the backup service.
Cluster rollout vs single node
Both use the same kind: ClusterUpdate manifest. The selector decides scope:
- Whole cluster — e.g.
selector.allNodes: true(subject to labels/datacenter filters when you use them). - Controllers only —
selector.controllersOnly: true. - One or few nodes —
selector.nodeIds: ["<uuid>", …]for a targeted or rolling-by-hand rollout.
There is no separate command for “upgrade this machine only”; narrow the selector instead.
CLI (kctl update cluster)
Alias: kctl update os. Requires a working controller context (same TLS setup as other kctl commands).
# Dry-run: resolve targets, viability, reboot hints
kctl update cluster plan -f rollout.yaml
# Submit or update the ClusterUpdate resource
kctl update cluster apply -f rollout.yaml
# Observe cluster + per-node phases
kctl update cluster get release-0-4-2
kctl update cluster list
# If approvalPolicy is manual
kctl update cluster approve release-0-4-2
kctl update cluster cancel release-0-4-2
kctl update cluster rollback release-0-4-2
# Boot a generation staged because the kernel or guest units changed
kctl update cluster reboot release-0-4-2 --node <node-id>
Switch to CLI in the strip above for command blocks.
YAML manifest outline
The release asset is camelCase. kctl also accepts the snake_case names. See YAML manifest reference (ClusterUpdate). Copy cluster-update-X.Y.Z.yaml from the GitHub Release for that version. It already contains the commit and the tested pins.
kind: ClusterUpdate
metadata:
name: release-0-4-2
spec:
target:
version: "0.4.2"
flakeRef: github:kcorehypervisor/kcore
flakeRev: "<full-git-sha>"
selector:
allNodes: true
strategy:
strategyType: one-at-a-time
maxUnavailable: 1
batchSize: 1
drainVms: false
activation:
mode: auto
approvalPolicy: manual
updateKind: kcore
Showing Terraform examples. Provider source is kcorehypervisor/kcore, version 0.5.0.
Reboot stays kctl update cluster reboot. Destroy cancels the rollout.
resource "kcore_cluster_update" "os" {
name = "release-0-5-0"
version = "0.5.0"
flake_ref = "github:kcorehypervisor/kcore"
flake_rev = "<full-git-sha>"
nixpkgs_rev = "<nixpkgs-rev>"
all_nodes = true
strategy = "one-at-a-time"
max_unavailable = 1
batch_size = 1
drain_vms = false
activation = "auto"
update_kind = "kcore"
schema_version = 59
previous_schema_version = 56
min_compatible_reader = 56
approval = "manual"
approve = false
tested_os_pins {
nixpkgs_rev = "<nixpkgs-rev>"
ceph_rev = "<ceph-rev>"
ceph_sha256 = "<ceph-sha256>"
kubernetes_version = "1.37.0"
}
}
With approvalPolicy: manual, the controller waits for kctl update cluster approve <name> before rolling. Automatic policies advance without that step. strategyType for this release is one-at-a-time. A nixpkgs move is a second manifest with updateKind: nixpkgs whose nixpkgsRev is one of testedOsPins.
Phases
The cluster resource exposes a phase (pending, rolling_out, succeeded, failed, …). Each node row tracks prepare/activate progress and errors. Use kctl update cluster get for detail.
canary, batch, and per-dc are refused. The rollout advances one node at a time.
Host rollback
Controller rollback expresses rollout intent. For a broken activation you can still recover with normal NixOS generation commands on the machine (e.g. previous bootloader generation); keep that in your physical/datacenter runbook.
Further reading
- Technical documentation index (
docs/README.md) - Browse
docs/on GitHub — operator guidecluster-and-node-upgrades.mdand design notescluster-updates.mdlive here once merged tomain.