The most-copied Terraform module for Kubernetes on Hetzner just changed what your nodes boot. With the v3 line of kube-hetzner/terraform-hcloud-kube-hetzner, every brand-new nodepool boots openSUSE Leap Micro — while your existing MicroOS nodes keep running untouched. If you deploy Kubernetes on Hetzner Cloud with Terraform, this is the single most consequential default flip in the module's history, and it settles a question every self-hosting team eventually faces: rolling or fixed releases on the machines under your cluster?
The short version, worked out in full below. New cluster: take the Leap Micro default — it is the stable path, and fighting the default buys you nothing. Existing MicroOS cluster: stay put; the module deliberately preserves your OS on upgrade because switching means recreating nodes, and there is no forced migration. Talos-curious: Talos remains the purer Kubernetes OS, but it means leaving the module's supported path entirely, so only pay that price if you specifically want API-only, no-SSH node management.
| Situation | Verdict | Why |
|---|---|---|
| New kube-hetzner cluster | Boot Leap Micro (the default) | Stable default; k3s on Leap Micro is the tested path |
| Existing MicroOS cluster | Stay on MicroOS | Preserved on upgrade; migration means node recreation |
| RKE2 on Hetzner | Leap Micro, but pin snapshots carefully | RKE2 is supported; SELinux snapshot selection is on you |
| Want Talos-style minimalism | Leave the module, adopt Talos deliberately | No SSH/API-driven is a different operating model, not an upgrade |
What v3 actually changed
The v3.0.0 release notes read like a stability manifesto, and the OS switch is the headline. Here is the complete inventory of what moved:
| Change | Detail |
|---|---|
os selector per nodepool | Control plane, agent, and autoscaler pools each choose leapmicro or microos |
New nodepools default to leapmicro | Fresh apply boots Leap Micro with no extra variables |
| Existing nodepools stay on MicroOS | Upgrading the module does not recreate nodes or flip their OS |
leapmicro_x86_snapshot_id / leapmicro_arm_snapshot_id | Pin exact Leap Micro images per architecture |
hcloud-leapmicro-snapshots Packer template | Build your own Leap Micro snapshots reproducibly |
kube-hetzner/os server label | Automatic OS detection per server, so mixed fleets stay coherent |
| RKE2 first-class | kubernetes_distribution = "rke2" is fully supported next to k3s |
| v3.1.0 mirror hardening | Custom Leap Micro mirrors must meet publisher-signed-checksum requirements |
| v3.2.1 Kubernetes channels | Accepts the v1.36 channel for both K3s and RKE2 |
Two follow-ups sharpen the picture. The v3.1.0 canary evidence shows both node types reaching Ready on k3s v1.36.3+k3s1 from a signed snapshot, with zero unhealthy workloads — the project now proves the default path against real Hetzner infrastructure before shipping. And v3.2.1 explicitly approves the v1.36 channel rather than silently floating to it, which is the same conservatism as the OS switch: move deliberately, on pinned artifacts, with receipts.
That conservatism extends to the part most teams never look at: snapshot selection. When you pin images — which you should on any cluster you care about — the choice is a matrix of Kubernetes distribution by CPU architecture, because the SELinux policy baked into the snapshot differs:
| x86_64 | ARM64 (Ampere) | |
|---|---|---|
| k3s | Leap Micro snapshot via leapmicro_x86_snapshot_id | Leap Micro snapshot via leapmicro_arm_snapshot_id |
| RKE2 | Leap Micro snapshot via leapmicro_x86_snapshot_id, SELinux selection validated | Leap Micro snapshot via leapmicro_arm_snapshot_id, SELinux selection validated |
The module's own support matrix flags RKE2 snapshot pinning with "validate SELinux snapshot selection carefully," and v3.1.0 tightened the supply chain further by requiring publisher-signed checksums for custom mirrors. The direction is unmistakable: the project treats the node image as a pinned, signed artifact — not a floating latest — and the OS default now matches that philosophy.
Why: rolling releases break clusters
The rationale is stated plainly in the migration PR that drove the switch: openSUSE MicroOS is a rolling release. Every new openSUSE Tumbleweed snapshot automatically produces a new MicroOS release, which means continuous updates flowing onto your nodes — and continuous opportunities for an update to break your k3s cluster. Teams running kube-hetzner hit exactly that: surprise breakage traced to the OS layer, on machines whose whole job is to stay boring underneath Kubernetes.
Leap Micro inverts the cadence. It is a fixed-point release that pairs Leap's stability with MicroOS's immutable design: transactional updates with automatic rollback on failure, but against a stable base that changes on a support lifecycle, not on every upstream snapshot. The lifecycle numbers tell the story:
| MicroOS | Leap Micro | |
|---|---|---|
| Release model | Rolling (tracks Tumbleweed) | Fixed-point (Leap family) |
| Update cadence | Continuous snapshots | Maintenance updates on a stable base |
| Community support | Current snapshot only | ~24 months per release (Leap 16 family alignment) |
| Extended support | None meaningful | Up to 4 years via migration to SUSE Linux Enterprise Micro |
| Package tool | transactional-update | transactional-update (no zypper on either) |
That last row matters more than it looks. Both OSes are immutable with transactional updates and rollback — the operational muscle memory transfers completely. What changes is not how you update but how often the floor moves: from "every Tumbleweed snapshot" to "a stable base with a two-year support window." For a node OS, whose ideal behavior is to be invisible for months at a time, that is the whole ballgame.
There is a broader signal here worth naming. With one default flip, the maintainers voted that fixed-point beats rolling for production nodes. Rolling-release node OSes optimize for always-current packages; fixed-point immutable OSes optimize for a node fleet that changes only when the operator says so. A decade into the immutable-OS experiment, the community's revealed preference is converging on the second answer.
The honest three-way: MicroOS vs Leap Micro vs Talos
Leap Micro is not the only immutable answer, and the switch does not make it the best OS for every team. The serious alternative is Talos Linux: minimal, immutable, and API-driven, with no SSH, no console, and no package manager — every node operation goes through a mutual-TLS API, and the OS runs from memory so the whole disk belongs to Kubernetes. Here is the head-to-head:
| MicroOS | Leap Micro | Talos Linux | |
|---|---|---|---|
| Release model | Rolling | Fixed-point, ~24-month support | Fixed releases, Kubernetes-aligned |
| Update mechanism | transactional-update + reboot (Kured) | transactional-update + reboot (Kured) | Atomic image update via API |
| Shell / SSH | Full openSUSE userspace, SSH works | Full openSUSE userspace, SSH works | No SSH, no shell, API only |
| Debugging story | SSH in, familiar tools | SSH in, familiar tools | talosctl API: logs, network, containers |
| Attack surface | General-purpose distro, immutable | General-purpose distro, immutable | Kernel + a handful of binaries |
| Kubernetes fit | Runs k3s/RKE2 well | Runs k3s/RKE2 well (stable default) | Purpose-built for Kubernetes only |
| kube-hetzner support | Legacy/upgrade support | Stable default | Not supported — separate stack |
| Best for | Existing clusters standing pat | New clusters, teams that SSH sometimes | Teams committed to API-only ops |
Read the table by team, not by column. If you ever SSH into a node to debug a CNI hiccup, inspect a disk, or run a vendor's diagnostic script, the openSUSE userspace on Leap Micro is a feature, not a compromise — Talos will fight you every one of those times by design. If your compliance story benefits from "there is literally no shell to reach," or you run enough nodes that per-node SSH is an anti-pattern anyway, Talos's minimalism earns its learning curve. And MicroOS is now a legacy answer: fine to keep running, not something to choose fresh — the module's own support matrix says exactly that.
One more honest note: neither openSUSE option is "lighter" than Talos. A general-purpose userspace with transactional updates carries more moving parts than an OS that is essentially a kernel plus Kubernetes plumbing. Leap Micro wins on familiarity and ecosystem, Talos wins on minimalism and attack surface. Pick the axis you actually optimize for.
What to do Monday morning
New cluster: accept the default and pin your snapshots. A fresh apply already boots Leap Micro. The one deliberate step is pinning leapmicro_x86_snapshot_id (and the ARM variable if you run Ampere nodes) to the tested snapshot instead of floating — the module gives you the variables and the Packer template, so a reproducible fleet is one decision away. If you run RKE2 rather than k3s, double-check the SELinux snapshot selection against the matrix above before you roll past your first nodepool.
Existing MicroOS cluster: do nothing, on purpose. The v3 upgrade preserves your OS precisely so you are not forced into node recreation. Schedule the module upgrade, verify the plan shows no server replacement, and keep your existing update flow (Kured for HA-aware reboots, the system-upgrade-controller for k3s). Migrate a pool to Leap Micro only when you have a reason — new pool for new workloads is the natural seam, since the os selector is per nodepool and the kube-hetzner/os label keeps mixed fleets detectable.
Talos-curious: treat it as a stack change, not an OS swap. Talos does not slot into kube-hetzner; adopting it means replacing the Terraform-module workflow with Talos machine configuration and talosctl-driven operations. That is a legitimate choice — it is also a migration project with its own learning curve, backup story, and upgrade runbook. Pilot it on a non-production cluster first, and go in for the API-driven model, not because a default changed elsewhere.
Everyone: respect the new supply-chain posture. v3 refuses to bootstrap from get.k3s.io/get.rke2.io install scripts and will not trust a checksum just because it was downloaded next to its payload; v3.1.0 extends signed-checksum requirements to custom Leap Micro mirrors. If you mirror images internally, publish the signatures too — the module now checks, and an unsigned mirror is a failed apply, not a warning.
The default is the documentation
Defaults are the loudest form of maintainer advice, and kube-hetzner's maintainers just advised every new Hetzner cluster to boot a fixed-point immutable OS with a two-year support window. The reasoning generalizes beyond one module: node OSes should change on operator schedule, from pinned and signed images, with rollback when an update goes wrong. Rolling releases had their argument — always-current packages — and production experience kept billing it as surprise breakage at 3 a.m.
Expect the rest of the self-hosted ecosystem to keep drifting the same way: pinned artifacts over floating tags, fixed bases over rolling snapshots, signed supply chains over downloaded checksums. The teams that internalize that posture now — pin the snapshot, check the signature, let the default carry the maintenance burden — will spend their next incident debugging their app, not their nodes.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



