Skip to main content
📬 Get weekly Production AI insights Practical notes on Kubernetes, AI infrastructure and platform engineering. No spam. Subscribe free
Flatcar Container Linux: Immutable Kubernetes Nodes Guide
Platform Engineering

Flatcar Container Linux: Immutable Kubernetes Nodes Guide

Why the host OS still matters in Kubernetes, and how Flatcar Container Linux delivers immutable, auto-updating nodes with Ignition, A/B updates and sysexts.

LB
Luca Berton
· 4 min read

“Kubernetes abstracts the operating system away” is one of the most expensive myths in platform engineering. At Open Source Summit Europe 2026 in Prague, I had a Udienza slot with Thilo Fromm, a long-time maintainer of Flatcar Container Linux, built around that exact question: why should platform teams still care about the host OS? I summarised the OS conversations of the week in The OS Layer in the AI Era.

This guide is the practical follow-up: what Flatcar is, how it works, and how to run Kubernetes nodes on it.

What Flatcar is

Flatcar was created by Kinvolk, a Berlin company that is now part of Microsoft, as a derivative of CoreOS Container Linux after CoreOS reached end of life. In 2024 it was accepted into the CNCF at the incubating level. It was the first operating system distribution the CNCF adopted. The CNCF announcement quoted CNCF CTO Chris Aniszczyk:

“A secure community-owned cloud native operating system was one of the missing layers of the CNCF technology stack.”

The same announcement named adopters including Adobe, with more than 20,000 nodes, the STACKIT managed Kubernetes service, and Wipro.

The four ideas behind it

1. An immutable, read-only /usr

The operating system lives on a read-only partition. You do not install packages on a node. Anything that is not the base OS runs as a container, or as a system extension (below). That removes the classic “someone SSHed in and installed something” drift that makes nodes impossible to rebuild.

2. Declarative provisioning with Ignition

A node is configured once, at first boot, by Ignition. You write the configuration in human-friendly Butane YAML and convert it to Ignition JSON. A minimal example:

variant: flatcar
version: 1.0.0
passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-ed25519 AAAA... you@example.com
storage:
  files:
    - path: /etc/hostname
      mode: 0644
      contents:
        inline: worker-01
butane --pretty --strict worker-01.bu > worker-01.ign

Because the configuration is a file, nodes become reproducible: the same file gives you the same node, every time.

3. Atomic A/B updates with rollback

Flatcar keeps two OS partitions. An update is written to the inactive one, and the node switches at the next reboot. If the new version fails to boot, it rolls back to the previous partition automatically. Updates come through release channels (Alpha, Beta, Stable, and an LTS channel), and fleets can be controlled with Nebraska, Flatcar’s update server, for staged rollouts and policy.

You can check the update state on a node with:

update_engine_client -status

4. System extensions for what the base does not ship

When you need something on the host that is not in the base image, such as a specific container runtime or Kubernetes version, Flatcar uses systemd-sysext. An extension is an image that is overlaid onto /usr at boot, so the base stays immutable and the extension stays versioned and replaceable. The community sysext-bakery publishes ready-made extensions, including Kubernetes components.

systemd-sysext list

Running Kubernetes on Flatcar

There are three common patterns:

  1. Cluster API. Flatcar is supported by Cluster API providers on several platforms, so nodes are created from Flatcar images with Ignition configuration generated by the bootstrap provider. This is the cleanest option for fleets.
  2. Managed Kubernetes services that offer Flatcar as a node image, such as the STACKIT example above.
  3. kubeadm with sysexts. For self-managed clusters, Butane provisions the node, a Kubernetes sysext provides kubelet and kubeadm, and kubeadm joins the node.

Whichever you choose, coordinate reboots. Automatic OS updates are only safe if nodes are drained before they reboot. Use a reboot coordinator such as Kured or the Flatcar Linux Update Operator, so that only a limited number of nodes update at a time and workloads are moved first.

Why this matters for security

An immutable host is a security control:

  • Smaller attack surface. No package manager on the node and a minimal base.
  • Fast patching. Kernel and OS fixes arrive as a whole new image through the update channel. With thousands of Linux kernel CVEs a year, that is the only patching model that scales.
  • Tamper evidence. A read-only, verified /usr makes unauthorised changes much harder to hide.
  • Clean rollback. If an update breaks something, you roll back the whole OS rather than debug a half-applied package set.

Flatcar, Talos, Bottlerocket or bootc?

Flatcar is not the only immutable option. Talos Linux goes further with an API-only OS and no shell at all (see my TalosCon 2025 recap). Bottlerocket is AWS’s container OS. bootc brings image-based updates to RHEL and Fedora (see bootc for immutable Linux). Choose Flatcar when you want:

  • a general-purpose Linux with a shell for debugging, but an immutable core,
  • vendor-neutral governance in the CNCF, as discussed in my neutral governance piece from Prague,
  • support for multiple clouds and bare metal with the same image and the same tooling.

A migration checklist

  1. Inventory everything you install on nodes today. Each item must become a container, a sysext, or Ignition configuration.
  2. Write Butane configurations and keep them in Git.
  3. Pick an update channel and a reboot coordinator before the first production node.
  4. Start with one stateless node pool, then move the rest.
  5. Remove SSH access for routine work. If you need a shell on a node for anything other than debugging, the design is not finished.

More from Prague

Free 30-min Production AI consultation

Book Now