01

An OS that is an API

Talos Linux is a Linux distribution with one job: run Kubernetes. It is immutable (the root filesystem is a read-only image), minimal (roughly a dozen binaries of its own), and has no SSH, no shell and no package manager. Every interaction, from reading a log to reconfiguring the network, is an authenticated gRPC call handled by machined, which runs as PID 1. You manage nodes the way you manage Kubernetes objects: declare, apply, let controllers converge.

talosctl → where does the call go?

gRPC · mTLS · :50000
-e endpoint
-n nodes
$talosctl -e 10.0.0.10 -n 10.0.0.12 logs kubelet
talosctlyour laptop~/.talos/configcp-110.0.0.10 · endpointapid:50000 mTLSmachinedPID 1kubelet logcontrol planecp-210.0.0.11 apid:50000 mTLSmachinedPID 1kubelet logcontrol planeworker-110.0.0.12 apid:50000 mTLSmachinedPID 1kubelet logworkerworker-210.0.0.13 apid:50000 mTLSmachinedPID 1kubelet logworker
step 0/9
Press run. The request is gRPC over mTLS: talosctl presents the client certificate from your talosconfig.
(output appears here)
-e vs -n

The endpoint is not the node

Your talosconfig lists endpoints (usually the control-plane IPs, or a load balancer). Commands go to an endpoint's apid, which proxies to the nodes you name with -n. That means workers don't need to be reachable from your laptop, and one command can fan out to many nodes, each reply tagged with its node. Authorization is in the client certificate: os:admin, os:operator, os:reader.
~/.talos/config (talosconfig)
context: homelab
contexts:
  homelab:
    endpoints: [10.0.0.10, 10.0.0.11, 10.0.0.12]  # control planes
    nodes: [10.0.0.10]                            # default -n
    ca: LS0tLS1CRUdJTi...      # Talos API CA
    crt: LS0tLS1CRUdJTi...     # your client cert (role: os:admin)
    key: LS0tLS1CRUdJTi...
everyday talosctl
talosctl config endpoint 10.0.0.10 10.0.0.11 10.0.0.12
talosctl -n 10.0.0.21 dashboard          # live TUI
talosctl -n 10.0.0.21 services           # what machined runs
talosctl -n 10.0.0.21 logs kubelet -f
talosctl -n 10.0.0.21 dmesg
talosctl -n 10.0.0.21,10.0.0.22 get addresses
talosctl -n 10.0.0.21 read /proc/meminfo  # read-only file access
talosctl -n 10.0.0.21 pcap -i eth0        # packet capture, no tcpdump install
the whole process list

What actually runs on a node

On a traditional distro the OS is a pile of packages that Kubernetes happens to run on. On Talos the OS is a small, fixed set of services that exist only to run the kubelet and, on control planes, etcd.
wherewhat it does
machinedPID 1, every nodeReplaces systemd and the whole userland. Runs services, holds the config, runs the COSI controllers that drive network, disks, time, etc.
apid:50000, every nodeThe gRPC front door. Terminates mTLS, checks the role in your client cert, and proxies to other nodes' apid.
trustd:50001, control planesIssues certificates to other nodes (e.g. a worker's apid) after they prove they hold the cluster's machine token.
containerdevery nodeTwo instances: one for Talos system services, one (CRI) for the kubelet's pods.
kubeletevery nodeRuns as a container managed by machined, configured from machine.kubelet.
etcdcontrol planesManaged by machined, not by Kubernetes. Data lives on EPHEMERAL at /var/lib/etcd.
udevd, auditd, …every nodeA handful of small helpers. That's the whole list — there is no sshd, bash, or apt.
imperative vs declarative

Fixing a node without logging into it

The absence of SSH isn't a restriction you work around; it removes the most common source of drift. Every fix becomes a change to declared config (which you keep in git) or a new image, so the next node you build is identical.

Same incident, two operating models

Incident: A node goes NotReady. The kubelet keeps restarting after someone set a bad flag.

Traditional nodeSSH + package manager + mutable files
  1. ssh admin@node-7needs an SSH daemon, keys and a user on every node
  2. sudo systemctl status kubeletinspect the unit
  3. sudo journalctl -u kubelet -n 200read the logs
  4. sudo vim /var/lib/kubelet/config.yamlhand-edit a file on one node
  5. sudo systemctl restart kubeletnode-7 now differs from its siblings
Talos nodetalosctl + declarative config
  1. talosctl -n 10.0.0.17 service kubeletservice state + recent events, over the API
  2. talosctl -n 10.0.0.17 logs kubeletsame log stream, no shell
  3. vim patches/kubelet.yaml # in gitfix the declared config, not the node
  4. talosctl -n 10.0.0.17 patch mc --patch @patches/kubelet.yamlmachined restarts kubelet with the new config — no reboot
steps (trad)
5
steps (talos)
4
drift introduced
2
drift on talos
0
immutable by construction

Disk layout: one mutable partition

Talos boots a SquashFS root image from its initramfs into memory, read-only. On disk there are only a few partitions with narrowly defined purposes, so you always know which bytes matter: the config in STATE, workload data in EPHEMERAL.

Install disk & memory

click a partition · pick an operation
in memoryloaded from the initramfs on every boot
/ (rootfs)SquashFS · read-only

machined, apid, trustd, containerd, runc… roughly a dozen binaries. The kubelet itself runs from a container image.

/systemtmpfs

runtime state: sockets, generated configs

/etc, /usr …read-only (a few files bind-mounted)

no package manager could write here even if it existed

install disk (GPT)
STATE/system/state

The machine configuration (config.yaml) and node identity. Can be encrypted (TPM / KMS / static key).

The only thing that defines the node. Survives upgrades; wiping it returns the node to maintenance mode.

tip
Click a partition to see what it holds.
GRUB vs systemd-boot
Older and BIOS installs use GRUB with A/B kernels on the BOOT partition. Since Talos 1.10, new installs on UEFI machines use systemd-boot, where each slot is a Unified Kernel Image (kernel + initramfs + cmdline, optionally signed for Secure Boot) on the EFI partition. The A/B idea is the same.
COSI: the Kubernetes model, inside the OS

Everything is a resource

machined is built on COSI (Common Operating System Interface): typed resources in namespaces, and controllers that watch some resources and write others. Specs describe what should be, statuses record what is. It's the same reconcile loop as a Kubernetes controller, which is why Talos self-heals instead of running scripts once at boot.

A controller loop, one event at a time

inputs
you / the world
talosctl, cables, pods
MachineConfig
v4
controllers (in machined)
AddressConfigController
watch → diff → act
AddressSpecController
watch → diff → act
AddressStatusController
watch → diff → act
LinkStatusController
watch → diff → act
resources · talosctl get …
AddressSpecv0
eth0/10.0.0.50/24 · absent
AddressStatusv0
eth0/10.0.0.50/24 · absent
LinkStatusv7
eth0 · operState: up
NodeAddressv3
current · [10.0.0.17/24]
kernel
Linux kernel
netlink: eth0
eth0 up
10.0.0.17/24
Pick an event and trigger it. Each controller only watches resources and writes resources; the chain emerges from those watches.
reading resources
talosctl get rd                       # list every resource type
talosctl -n 10.0.0.21 get links
talosctl -n 10.0.0.21 get addresses
talosctl -n 10.0.0.21 get routes
talosctl -n 10.0.0.21 get members      # cluster membership (discovery)
talosctl -n 10.0.0.21 get machineconfig -o yaml
talosctl -n 10.0.0.21 get addresses --watch   # stream changes
$ talosctl -n 10.0.0.21 get addresses
NODE        NAMESPACE   TYPE            ID                     VERSION   ADDRESS          LINK
10.0.0.21   network     AddressStatus   eth0/10.0.0.21/24      1         10.0.0.21/24     eth0
10.0.0.21   network     AddressStatus   eth0/fe80::be24:11/64  2         fe80::be24:11/64 eth0
10.0.0.21   network     AddressStatus   lo/127.0.0.1/8         1         127.0.0.1/8      lo
10.0.0.21   network     AddressStatus   cilium_host/10.244…    1         10.244.1.94/32   cilium_host
  • why it mattersThere is no back door: the gRPC API is the only way in, so everything is authenticated, role-scoped and auditable, and a compromised workload has no shell to land in.
  • why it mattersThe read-only root and the narrow disk layout mean a node is fully described by its image version plus its machine config. Reproducing or replacing a node is routine.
  • why it mattersCOSI controllers continuously reconcile desired and actual state, so configuration is applied (and re-applied after drift) by the OS itself, not by an external tool.