--- - name: Check if k3s service is installed ansible.builtin.stat: path: /etc/systemd/system/k3s.service register: k3s_service - name: Check if k3s binary exists ansible.builtin.stat: path: /usr/local/bin/k3s register: k3s_bin - name: Determine if k3s needs installation ansible.builtin.set_fact: k3s_needs_install: "{{ not k3s_bin.stat.exists or not k3s_service.stat.exists }}" - name: Find the first available wired interface IP ansible.builtin.set_fact: k3s_node_ip: "{{ ansible_facts[item]['ipv4']['address'] }}" loop: "{{ k3s_wired_interfaces }}" when: - ansible_facts[item] is defined - ansible_facts[item]['ipv4'] is defined - ansible_facts[item]['ipv4']['address'] is defined - k3s_node_ip is not defined - name: Fallback to default IPv4 address if no wired interface IP found ansible.builtin.set_fact: k3s_node_ip: "{{ ansible_facts['default_ipv4']['address'] }}" when: - k3s_node_ip is not defined - ansible_facts['default_ipv4'] is defined - ansible_facts['default_ipv4']['address'] is defined - name: Verify k3s_node_ip was found ansible.builtin.assert: that: - k3s_node_ip is defined fail_msg: "Could not find a valid IP address on any of the specified wired interfaces: {{ k3s_wired_interfaces }}. Available facts: {{ ansible_facts.keys() | list }}" - name: Install k3s dependencies ansible.builtin.package: name: - curl - iptables state: present - name: Download k3s install script ansible.builtin.get_url: url: https://get.k3s.io dest: /tmp/k3s_install.sh mode: "0755" - name: Initialize first k3s server node ansible.builtin.command: cmd: /tmp/k3s_install.sh environment: INSTALL_K3S_VERSION: "{{ k3s_version }}" K3S_TOKEN: "prole-k3s-ha-token" # In a real prod environment, use a secret INSTALL_K3S_EXEC: "server --cluster-init --bind-address {{ k3s_node_ip }} --node-ip {{ k3s_node_ip }} --advertise-address {{ k3s_node_ip }}" INSTALL_K3S_SKIP_SELINUX_RPM: "true" when: - inventory_hostname == groups['k3s_hosts'][0] - k3s_needs_install - name: Wait for k3s token to be generated ansible.builtin.wait_for: path: /var/lib/rancher/k3s/server/node-token when: inventory_hostname == groups['k3s_hosts'][0] - name: Read k3s node token ansible.builtin.slurp: src: /var/lib/rancher/k3s/server/node-token register: node_token_b64 when: inventory_hostname == groups['k3s_hosts'][0] - name: Set node token fact ansible.builtin.set_fact: k3s_cluster_token: "{{ node_token_b64.content | b64decode | trim }}" when: - inventory_hostname == groups['k3s_hosts'][0] - node_token_b64 is defined - node_token_b64.content is defined - name: Share node token with other nodes ansible.builtin.set_fact: k3s_cluster_token: "{{ hostvars[groups['k3s_hosts'][0]]['k3s_cluster_token'] }}" when: - inventory_hostname != groups['k3s_hosts'][0] - hostvars[groups['k3s_hosts'][0]]['k3s_cluster_token'] is defined - name: Join additional k3s server nodes ansible.builtin.command: cmd: /tmp/k3s_install.sh environment: INSTALL_K3S_VERSION: "{{ k3s_version }}" K3S_URL: "https://{{ hostvars[groups['k3s_hosts'][0]]['k3s_node_ip'] }}:6443" K3S_TOKEN: "{{ k3s_cluster_token }}" INSTALL_K3S_EXEC: "server --bind-address {{ k3s_node_ip }} --node-ip {{ k3s_node_ip }} --advertise-address {{ k3s_node_ip }}" INSTALL_K3S_SKIP_SELINUX_RPM: "true" when: - inventory_hostname != groups['k3s_hosts'][0] - k3s_needs_install - k3s_cluster_token is defined register: k3s_join failed_when: - k3s_join.rc != 0 - "'already exists' not in k3s_join.stderr" - name: Ensure k3s service is started and enabled ansible.builtin.service: name: k3s state: started enabled: true