Talos Linux is a minimal, immutable operating system built only to run Kubernetes. It has no SSH, no shell and no package manager: every change goes through an authenticated API with the talosctl client, driven by a declarative machine configuration. In this tutorial you will boot three machines from the Talos ISO, generate and apply machine configurations, bootstrap a cluster with one control plane node and two workers, manage the nodes through the API, and upgrade Talos and Kubernetes.

Prerequisites

To follow this guide you need:

  • Three virtual machines or bare metal servers that you can boot from an ISO image, on the same network: one control plane node (at least 2 vCPUs, 2 GB of RAM, 4 GB recommended) and two workers (at least 1 vCPU and 1 GB of RAM each), each with a disk of 10 GB or more.
  • A workstation running Linux or macOS with kubectl installed.
  • Network access from the workstation to the nodes on TCP 50000 (Talos API) and TCP 6443 (Kubernetes API).
  • Static IP addresses or DHCP reservations for the nodes. This guide uses 192.168.1.11 for the control plane and 192.168.1.21 and 192.168.1.22 for the workers; replace them with yours.

Step 1 - Installing talosctl

talosctl must match the Talos version you deploy. Find the current release on the Talos GitHub releases page and set it in a variable (the value below is an example):

TALOS_VERSION=v1.11.0

On a Linux workstation, download the binary from the release and install it:

curl -fsSLo talosctl "https://github.com/siderolabs/talos/releases/download/${TALOS_VERSION}/talosctl-linux-amd64"
sudo install -m 0755 talosctl /usr/local/bin/talosctl

On macOS, use Homebrew instead:

brew install siderolabs/tap/talosctl

Check the client version:

talosctl version --client
Client:
        Tag:         v1.11.0
        ...

Step 2 - Booting the nodes from the Talos ISO

Download the ISO for the same version from the Talos Image Factory at factory.talos.dev. Choose Bare-metal Machine, your Talos version and architecture, and no extra system extensions for this tutorial. The factory gives you the ISO link and an installer image name; note the installer image, you will use it for upgrades.

Boot all three machines from the ISO. Talos starts in maintenance mode: it runs from memory, shows its IP address on the console and waits for a configuration through the API.

From your workstation, confirm you can reach a node and find the disk to install to. The --insecure flag is required in maintenance mode because the node has no certificates yet:

talosctl get disks --insecure --nodes 192.168.1.11
NODE   NAMESPACE   TYPE   ID      VERSION   SIZE     READ ONLY   TRANSPORT   ROTATIONAL   WWID   MODEL
       runtime     Disk   sda     1         43 GB    false       virtio                           QEMU HARDDISK
       runtime     Disk   sr0     1         110 MB   true                                         QEMU DVD-ROM

Here the install disk is /dev/sda. On some virtual machines it is /dev/vda, and on NVMe servers /dev/nvme0n1.

Step 3 - Generating the machine configuration

Keep the cluster's secrets (certificate authorities, tokens and encryption keys) in their own file, so you can regenerate configurations later without creating a new cluster:

mkdir -p ~/talos && cd ~/talos
talosctl gen secrets -o secrets.yaml

Generate the configurations. The first argument is the cluster name and the second is the Kubernetes API endpoint. With a single control plane node it is that node's address; for a highly available cluster, use a load balancer or a shared virtual IP in front of three control plane nodes instead:

talosctl gen config my-cluster https://192.168.1.11:6443 \
  --with-secrets secrets.yaml \
  --install-disk /dev/sda \
  --output-dir _out
generating PKI and tokens
Created _out/controlplane.yaml
Created _out/worker.yaml
Created _out/talosconfig
  • controlplane.yaml configures control plane nodes (etcd, API server, scheduler, controller manager).
  • worker.yaml configures worker nodes.
  • talosconfig is the client configuration and certificate that talosctl uses to authenticate.

These files and secrets.yaml grant full control of the cluster. Keep them out of public repositories and back them up securely.

Validate the files before applying them:

talosctl validate --config _out/controlplane.yaml --mode metal
talosctl validate --config _out/worker.yaml --mode metal

Step 4 - Applying the configuration to the nodes

Send the control plane configuration to the first node:

talosctl apply-config --insecure --nodes 192.168.1.11 --file _out/controlplane.yaml

Then the worker configuration to both workers:

talosctl apply-config --insecure --nodes 192.168.1.21 --file _out/worker.yaml
talosctl apply-config --insecure --nodes 192.168.1.22 --file _out/worker.yaml

Each node installs Talos to disk and reboots. Remove the ISO from the virtual machines, or change the boot order, so they boot from disk.

Point talosctl at the new cluster so you do not have to repeat the endpoint on every command. The endpoint is the node talosctl connects to; the node is the default target of commands:

export TALOSCONFIG=~/talos/_out/talosconfig
talosctl config endpoint 192.168.1.11
talosctl config node 192.168.1.11

From now on, commands run without --insecure and use the client certificate from talosconfig.

Step 5 - Bootstrapping the cluster

etcd must be initialized exactly once, on one control plane node. Run bootstrap after the control plane node has rebooted from disk:

talosctl bootstrap

Wait for the cluster to become healthy. The health check verifies etcd, the Kubernetes components and that all nodes have joined, and takes a few minutes on the first boot:

talosctl health
waiting for etcd to be healthy: OK
waiting for all k8s nodes to report ready: OK
...
waiting for all control plane components to be ready: OK

Download the kubeconfig. Without arguments, talosctl merges it into ~/.kube/config:

talosctl kubeconfig
kubectl get nodes -o wide
NAME            STATUS   ROLES           AGE   VERSION   INTERNAL-IP    OS-IMAGE
talos-cp-1      Ready    control-plane   4m    v1.34.x   192.168.1.11   Talos (v1.11.0)
talos-w-1       Ready    <none>          3m    v1.34.x   192.168.1.21   Talos (v1.11.0)
talos-w-2       Ready    <none>          3m    v1.34.x   192.168.1.22   Talos (v1.11.0)

The default configuration installs Flannel as the network plugin, so pods can already talk to each other. Run a quick test deployment:

kubectl create deployment hello --image=nginx
kubectl rollout status deployment/hello

Step 6 - Managing nodes through the API

Because there is no SSH, you inspect and operate nodes with talosctl. Add --nodes to target a node other than the default. The most useful commands are:

talosctl services --nodes 192.168.1.21
talosctl logs kubelet --nodes 192.168.1.21
talosctl dmesg --nodes 192.168.1.21
talosctl get addresses --nodes 192.168.1.21
talosctl read /etc/os-release --nodes 192.168.1.21

For a live overview of CPU, memory, logs and network per node, open the terminal dashboard:

talosctl dashboard --nodes 192.168.1.11,192.168.1.21,192.168.1.22

To change a setting, edit the machine configuration with a patch instead of by hand. For example, to set a hostname on the first worker, create a patch file:

nano hostname-w1.yaml
machine:
  network:
    hostname: talos-w-1

Apply it to that node:

talosctl patch machineconfig --nodes 192.168.1.21 --patch @hostname-w1.yaml

Talos applies changes without a reboot when it can, and tells you when a reboot is needed.

Step 7 - Upgrading Talos and Kubernetes

Talos upgrades replace the whole operating system image atomically, and roll back automatically if the node fails to boot. Upgrade one node at a time, starting with the control plane, and check health between nodes. Use the installer image from the Image Factory for the new version (or ghcr.io/siderolabs/installer:<version> if you use no extensions):

talosctl upgrade --nodes 192.168.1.11 --image ghcr.io/siderolabs/installer:v1.11.1
talosctl health

Repeat for each worker. Upgrade your local talosctl to the same version afterwards.

Kubernetes is upgraded separately. The command upgrades the control plane components and the kubelet on every node in order. Run it with --dry-run first to see what it will change:

talosctl upgrade-k8s --to 1.34.1 --dry-run
talosctl upgrade-k8s --to 1.34.1

Check the Talos support matrix before upgrading: each Talos release supports a specific range of Kubernetes versions.

Troubleshooting

talosctl times out connecting to a node in maintenance mode. TCP 50000 is blocked between the workstation and the node, or you are using the wrong IP. Read the address from the node's console screen.

tls: certificate required or x509 errors after applying the configuration. You are still using --insecure, or TALOSCONFIG does not point at the talosconfig generated with this configuration. Drop --insecure once the node has been configured.

talosctl health waits forever for etcd. You have not run talosctl bootstrap, or you ran it before the control plane node rebooted from disk. Check with talosctl service etcd and talosctl logs etcd.

Workers never become Ready. They cannot reach the control plane endpoint on port 6443. Confirm the endpoint in worker.yaml and check talosctl logs kubelet --nodes <worker_ip>.

A node rebooted back into maintenance mode. It booted from the ISO again. Remove the ISO or fix the boot order.

Conclusion

You built a Kubernetes cluster on Talos Linux, managed its nodes through the Talos API and learned the upgrade path for both Talos and Kubernetes. Next, add two more control plane nodes behind a virtual IP or load balancer for high availability, replace Flannel with Cilium if you need network policies, and add storage with a CSI driver, using Image Factory system extensions when the driver needs host tools such as iSCSI.