· · 8 min leestijd Advanced

Talos Linux: het immutable Kubernetes OS dat mijn kijk op nodes veranderde

Waarom Talos Linux het perfecte OS is voor Kubernetes: immutable, API-driven, en secure by default. Echte ervaringen uit productie.

Een gladde zwarte plaatmachine met één poort waar zij via een kabel mee praat, de koevoet van een wezen vindt niks

TL;DR Talos Linux is een Linux die Kubernetes draait en verder niks. Geen SSH, geen shell, geen packagemanager. Elke wijziging gaat via een API en een YAML-bestand in Git. Ik draai m’n nodes er nu drie jaar op, en deze post is hoe ik ophield de shell te missen.

De eerste keer dat ik naar een Talos -node probeerde te SSH’en, kreeg ik niks. Geen shell, geen verbinding, niet eens een loginprompt. Ik heb er een minuut naar zitten staren en me afgevraagd hoe ik een machine moest debuggen waar ik niet in kon.

Dat was drie jaar geleden. Sindsdien heb ik Kubernetes op niks anders meer gedraaid.

Vóór Talos zagen m’n nodes eruit zoals de meeste Kubernetes-nodes eruitzien. Een algemene distro, gehardend met een CIS-benchmark-script, een SSH-key erop, een configmanagement-tool om drift in toom te houden, en daarna twee jaar naar binnen SSH’en om te fixen wat die tool niet zag. Elke node had z’n eigen geschiedenis, en maar een deel daarvan stond ergens opgeschreven.

Wat Talos weglaat

Talos Linux is een Linux-distributie die gebouwd is om Kubernetes te draaien en verder niks. “Distributie” is nog ruim genomen, want Talos gooit het meeste weg van wat een Linux-bak tot een Linux-bak maakt. Er is geen SSH, dus je komt niet op een node. Er is geen packagemanager, dus geen apt-get, geen yum, niks te installeren. Er is helemaal geen shell, geen bash, geen sh. Het root-filesystem is read-only. Alles wat je met de machine wilt doen gaat via een gRPC-API.

Mijn eerste reactie was “dat is gestoord, hoe krijg je dan ooit iets gedaan”. Die van jou waarschijnlijk ook. Het antwoord duurde bij mij even, en het is de rest van deze post.

De fix die op één disk leefde

Jaren vóór Talos lag productie midden in de nacht plat. Ik SSH’te naar de kapotte node, debugde in paniek wat rond, vond het probleem, en fixte het door met de hand een configfile aan te passen en een service te herstarten. Terug naar bed.

Die fix bestond op precies één plek, de disk van die node. Niet in Git, nergens gedocumenteerd. Maanden later vervingen we de node en het probleem kwam recht terug, omdat niemand meer wist van de handmatige aanpassing die het in leven had gehouden.

Dat kost een mutable node je, en het stapelt zich op. Elke SSH-sessie is een kans op drift. Elke quick fix is schuld die je later terugbetaalt, meestal tijdens het volgende incident, en zonder de context die je de eerste keer had.

Stel je nu een node voor die je niet met de hand kúnt laten driften, omdat er geen weg naar binnen is. Dat is Talos. Je kunt niet SSH’en en zitten klooien. Elke wijziging gaat via de API, dus elke wijziging is te tracken, te versioneren en te reproduceren. Mijn handmatige aanpassing was een diff van één regel in Git geweest, gereviewd, en de vervangende node had hem vanaf dag één gehad.

Als ik dit uitleg komt de tegenwerping snel. En debuggen dan? En noodgevallen?

Debuggen zonder shell

Terecht. Talos levert talosctl, een CLI die met de Talos-API praat, en die dekt de dingen waar je normaal een shell voor open zou doen:

# Systeem logs ophalen
talosctl logs kubelet

# Kernel berichten streamen
talosctl dmesg -f

# Draaiende processen tonen
talosctl processes

# Node health checken
talosctl health

# Elk bestand van de node lezen
talosctl read /etc/hosts

# Volledige machine configuratie ophalen
talosctl get machineconfig

Alles wat je normaal via SSH doet zit hier, met één verschil dat ertoe doet. De API heeft access control en audit logging, en is te beperken tot specifieke operaties. SSH is een alles-of-niets root-shell, en dat is precies wat een aanvaller ook wil.

Voor de momenten dat je even naar een machine wilt zitten kijken is er een dashboard:

talosctl dashboard

Dat is een read-only TUI met systeemstats, logs en de status van de node. Voor echte noodgevallen is er een debugcontainer, een privileged container met volledige toegang tot de host. Onhandig in gebruik, en dat is expres, zodat je er niet uit gewoonte naar grijpt.

Eén YAML-bestand per node

Een Talos-node wordt geconfigureerd met één YAML-machineconfig. Een uitgekleed voorbeeld:

machine:
  type: controlplane
  token: <bootstrap-token>
  ca:
    crt: <ca-certificate>
    key: <ca-key>
  network:
    hostname: node-01
    interfaces:
      - interface: eth0
        dhcp: true
  install:
    disk: /dev/sda
    image: ghcr.io/siderolabs/installer:v1.6.0

cluster:
  clusterName: homelab
  controlPlane:
    endpoint: https://192.168.1.100:6443

Dat bestand beschrijft alles van de node. Netwerkinstellingen, disklayout, Kubernetes-versie, kernelargumenten, system extensions, CNI -configuratie.

Toepassen is één commando:

talosctl apply-config --nodes 192.168.1.10 --file controlplane.yaml

Talos configureert de node niet zozeer, het laat de node naar het bestand toe convergeren. Wijzig het bestand, pas opnieuw toe, en de node schuift naar de nieuwe staat. Hetzelfde declaratieve model dat Kubernetes voor pods gebruikt, een laag dieper.

GitOps een laag dieper

Vergelijk dat eens met waar OS-configuratie normaal leeft. Ansible-playbooks die afgedreven zijn van wat er op de bak staat. Een configmanagement-tool die niemand helemaal vertrouwt. Een laag tribal knowledge, opgebouwd in SSH-sessies die geen spoor achterlieten. De source of truth is “vraag het degene die het heeft opgezet”, en die vertrekt een keer.

Omdat een Talos-node één YAML-bestand is, valt hij zo in dezelfde GitOps-workflow als de rest. Mijn repo ziet er zo uit:

infrastructure/
├── talos/
│   ├── controlplane-1.yaml
│   ├── controlplane-2.yaml
│   ├── controlplane-3.yaml
│   ├── worker-1.yaml
│   └── worker-2.yaml
├── kubernetes/
│   └── ... (manifests beheerd door ArgoCD)
└── ...

Moet ik iets op een node wijzigen, zeg een kernelargument of een netwerkinstelling, dan pas ik de YAML aan, commit, en apply. De commit is de documentatie. Reviewbaar in een PR, reproduceerbaar op de volgende node die ik bouw. Dat is de hele reden dat ik het zo doe.

Wat een aanvaller op de bak aantreft

Haal de shell en de packagemanager weg en een hele klasse aanvallen werkt niet meer. Geen packagemanager, dus geen curl | bash die malware installeert. Geen SSH, dus niks om te brute-forcen. Een read-only filesystem, dus geen systeembinaries omwisselen. Een minimale userspace, dus er valt sowieso minder aan te vallen.

De node draait alleen wat Kubernetes nodig heeft: containerd , kubelet en een paar ondersteunende services. Geen cron, geen systemd-resolved, geen van de achtergronddaemons die een algemene distro meelevert omdat je ze ooit misschien wilt.

Stel dat een aanvaller een container popt en naar de host ontsnapt. Waar landt hij dan? Op een read-only filesystem zonder shell, zonder packagemanager, en zonder plek om te blijven zitten. Dat sluit aan bij zero-trust-principes, in die zin dat de node zichzelf niet eens vertrouwt om goed geconfigureerd te blijven en de gedeclareerde staat blijft afdwingen.

Upgrades met ingebouwde rollback

Upgrades zijn het stuk dat ik het leukst vind:

talosctl upgrade --nodes 192.168.1.10 \
  --image ghcr.io/siderolabs/installer:v1.7.0

Talos haalt het nieuwe OS-image op, schrijft het naar een tweede partitie, en reboot ernaartoe. Komt de nieuwe versie niet op, dan rolt de node uit zichzelf terug naar de vorige.

Dat is een transactionele upgrade. Geen half toegepaste staat, geen zaterdag kwijt aan een kernel die halverwege de upgrade panickte. Hij voltooit, of hij rolt in z’n geheel terug.

Voor een Kubernetes-versiesprong zet je de nieuwe versie in de machineconfig en pas je die toe. Talos regelt het drainen en cordonen als je het Talos-aware upgradepad gebruikt.

Wanneer je Talos niet moet gebruiken

Dit past niet iedereen. Blijf bij een traditionele distro als:

  • je specifieke packages nodig hebt die niet als Talos-extension bestaan
  • je Linux nog aan het leren bent en de abstractie er te veel van verbergt
  • je team nog niet toe is aan API-driven beheer
  • je non-Kubernetes-workloads op dezelfde nodes draait

Talos doet Kubernetes en verder niks. Is dat niet je hoofdzaak, dan ben je je tijd kwijt aan vechten tegen het ontwerp in plaats van het te gebruiken.

Debuggen heeft ook een steilere curve aan het begin. Als iets breekt kun je je er niet met vim /etc/whatever uit wurmen. Je moet eerst de Talos-tools en -concepten leren. Op de lange termijn is dat winst, omdat het betere gewoontes afdwingt, maar tijdens de adoptie kost het echt wat, en dat zeg ik liever gewoon.

Uitproberen in Docker

De snelste manier om Talos te proberen is met Docker:

# Maak een lokaal cluster
talosctl cluster create --name demo

# Haal kubeconfig op
talosctl kubeconfig --nodes 127.0.0.1

# Je draait nu Talos lokaal
kubectl get nodes

Wil je iets dat dichter bij echt komt, begin dan met een klein homelabcluster. Mijn homelab draait op refurbished mini-PCs, een goedkope manier om met Talos te experimenteren voordat je er productie op zet. De Talos-documentatie is goed, met guides voor bare metal, AWS, GCP, Azure, VMware en meer.

Wat de toolchain aanneemt

Dus waarom draait niet iedereen z’n nodes zo? Omdat de hele industrie van het tegendeel uitgaat. Traditioneel infrastructuurbeheer is gebouwd op het idee dat je op een gegeven moment de machine op moet om iets met de hand te fixen. SSH-keys, bastionhosts, jumpboxes, consoletoegang. De hele toolchain bestaat om je een weg naar binnen te geven.

Talos haalt die weg naar binnen weg. De gok is dat je hem nooit nodig hebt, omdat de node zichzelf beschrijft en uit zichzelf convergeert. Is er iets mis, dan pas je het bestand aan en apply je opnieuw. Dat is rigide, en die rigiditeit is precies wat de drift tegenhoudt.

In de praktijk valt het reuze mee. Elk incident dat ik op Talos heb gehad ging hetzelfde. Logs lezen via de API, de misconfiguratie zien, het bestand fixen, apply. De fix is een commit, dus hij documenteert zichzelf. Niemand hoeft achteraf te vragen of er iemand ingelogd heeft en iets heeft veranderd, want dat kan niemand.

Drie jaar verder mis ik SSH niet. De API geeft me alles wat een shell me gaf, plus access control, een audittrail en een node die ik uit een bestand kan herbouwen. Talos heeft een uitgesproken mening over hoe je een node hoort te draaien. De mijne bleek erbij te passen.