--- - name: Update Cluster Nodes hosts: all serial: 1 # CRITICAL: Processes one node entirely before moving to the next become: yes tasks: - name: Determine an available k3s control plane node set_fact: # Picks the first server node that is NOT the one currently being updated active_master: "{{ groups['k3s_servers'] | difference([inventory_hostname]) | first }}" delegate_to: localhost - name: Check if updates are needed (Debian/Raspbian) apt: upgrade: dist update_cache: yes register: apt_status when: inventory_hostname in groups['k3s_servers'] or inventory_hostname in groups['k3s_agents_raspbian'] # For NixOS, we just run the upgrade and check if a reboot is flagged. - name: Run NixOS update command command: sudo nix flake update --flake $NIX_FLAKE_PATH && sudo nixos-rebuild switch --flake $NIX_FLAKE_PATH#{{ inventory_hostname_short }} register: nixos_status when: inventory_hostname in groups['k3s_agents_nixos'] - name: Check for Raspbian reboot required flag stat: path: /var/run/reboot-required register: reboot_required when: inventory_hostname not in groups['k3s_agents_nixos'] # --- THE KUBERNETES DRAIN PHASE --- - name: Drain the node safely command: > sudo k3s kubectl drain {{ inventory_hostname_short }} --ignore-daemonsets --delete-emptydir-data --force --grace-period=90 --timeout=5m delegate_to: "{{ active_master }}" when: (reboot_required.stat.exists | default(false)) or ('changed' in nixos_status | default({})) ignore_errors: yes # Prevents a stubborn pod from halting the entire cluster update # --- THE REBOOT PHASE --- - name: Reboot the node reboot: post_reboot_delay: 180 # Give k3s and Longhorn time to initialize when: (reboot_required.stat.exists | default(false)) or ('changed' in nixos_status | default({})) # --- THE UNCORDON PHASE --- - name: Uncordon the node command: sudo k3s kubectl uncordon {{ inventory_hostname_short }} delegate_to: "{{ active_master }}" when: (reboot_required.stat.exists | default(false)) or ('changed' in nixos_status | default({}))