Skip to content

Ansible Configuration

Ansible never configures a node here: it generates files on the deployment host, and Ignition applies them once, on the first boot after a node is installed.

It renders two Ignition configs per host from two templates — one the PXE environment runs to install, one flatcar-install embeds into the system it writes. Changing anything under ansible/ therefore takes a rebuild of the affected node, not a reboot. The directory layout is in Repository layout.

Inventory

ansible/inventory.yaml is the single source of truth for the machines; every generated artifact comes from it, and the values are baked into the output rather than read at boot. The variables are described in Quickstart step 2. Every playbook targets the k8s_nodes group, the parent of control_plane and workers, which carries ansible_user and the SSH options.

Every edit needs a regeneration, and some need two

make config re-renders the Ignition configs, PXE menus and router config from the inventory; make download fetches what flatcar_channel, flatcar_version, syslinux_version and kubernetes_version name. The Flatcar, Kubernetes and kube-vip versions are rendered into the configs too, so a version bump needs make artifacts, which runs both. Which target reads which variable is in the Quickstart table. An edit followed by neither changes nothing at all, silently.

bootstrap_cluster in the control_plane group decides whether the first control-plane host renders kubeadm init (true, the first install) or, like every other control plane, kubeadm join --control-plane (false, every rebuild). A rebuilt node that ran init would start a second cluster on the same VIP — see Rebuilding a node.

kube_vip_version only sets the bootstrap static pod that gives kubeadm init a VIP; once ArgoCD syncs, payload/platform/kube-vip/ takes over and its image is what runs — see Control Plane VIP.

Playbooks

Playbook Does
config.yaml Generates the bootstrap token, certificate key and etcd encryption key into output/credentials/ (mode 0700); renders the Ignition configs via Butane into output/http (mode 0600), the sysupdate config for running nodes beside them, the per-MAC PXE menus into output/tftp/pxelinux.cfg/, the router's FRR config into output/router/frr-bgp.conf, and a readable copy of the kubeadm config into output/tmp/ (the copy that runs is inlined into Ignition)
download.yaml Fetches the Flatcar kernel, initrd, OS image and its detached signature, checked against the .DIGESTS.asc that gpgv verifies; the Kubernetes sysext image; and the syslinux bootloader files, checked the same way against sha256sums.asc. The signing keys are fetched and trusted through the primary fingerprints pinned in the playbook
reinstall.yaml Rewrites DEFAULT in the generated PXE menus — install to arm, localboot to disarm. make reinstall and make reinstall-cancel are the two directions, both taking LIMIT=<host>. Arming refuses while bootstrap_cluster is true and the API VIP answers, or when an endpoint name is not the one the cluster publishes. It touches only output/tftp/pxelinux.cfg/, so the next make config regenerates the safe default. See Switching back to local boot
kubeconfig.yaml Copies the admin kubeconfig over SSH to output/kubeconfig, mode 0600, with the VIP as its server

config.yaml is safe to re-run: the password lookup reads an existing credential file back instead of generating a new value, so the encryption key every control-plane node shares stays the one etcd's Secrets were encrypted with.

config.yaml renews the join credentials on the first control-plane host that answers with a running cluster, so the node being replaced may be any of them; it fails when none answers while output/kubeconfig exists, since a node booted then could not join, and skips the renewal silently only before the first bootstrap.

kubeconfig.yaml targets control_plane[0] — the first control-plane host in the inventory, with no fallback. If that node is down, copy /etc/kubernetes/admin.conf off any other control-plane node by hand. Keep a copy of the result off the cluster: it is the credential you want when the web UIs are unreachable, and output/ is exactly as durable as the laptop it is on.