--- - name: Install k3s on 3-node cluster hosts: vm1,vm2,vm3 become: true become_user: root serial: 1 # Ensure tasks are executed one host at a time tasks: - name: Check if k3s is already installed ansible.builtin.stat: path: /usr/local/bin/k3s register: k3s_binary - name: Check if k3s token file exists ansible.builtin.stat: path: /opt/k3s-token register: k3s_token_file when: inventory_hostname == 'vm1' - name: Generate and save k3s token if not present (first node) ansible.builtin.copy: dest: /opt/k3s-token content: "{{ lookup('pipe', 'head -c 16 /dev/urandom | sha256sum | cut -d\" \" -f1') }}" owner: root group: root mode: '0600' force: false register: generated_k3s_token when: inventory_hostname == 'vm1' and not k3s_token_file.stat.exists - name: Download k3s install script ansible.builtin.get_url: url: https://get.k3s.io dest: /tmp/k3s_install.sh mode: '0755' when: not k3s_binary.stat.exists - name: Ensure .kube directory exists ansible.builtin.file: path: /home/user/.kube state: directory mode: '0755' when: inventory_hostname == 'vm1' and not k3s_binary.stat.exists - name: Install k3s on first node ansible.builtin.shell: | set -o pipefail # --write-kubeconfig-mode 644 K3S_TOKEN=$(cat /opt/k3s-token) /bin/bash /tmp/k3s_install.sh server --cluster-init --disable traefik --disable servicelb --tls-san 192.168.56.80 --node-name vm1 --node-ip 192.168.56.80 if [ $? -eq 0 ]; then mkdir -p /home/vagrant/.kube && cp /etc/rancher/k3s/k3s.yaml /home/vagrant/.kube/config && chown vagrant:vagrant /home/vagrant/.kube/config fi args: executable: /bin/bash creates: /usr/local/bin/k3s when: inventory_hostname == 'vm1' and not k3s_binary.stat.exists - name: Read k3s token from master node (for subsequent nodes) ansible.builtin.command: cat /opt/k3s-token register: k3s_token_content delegate_to: vm1 when: inventory_hostname != 'vm1' and not k3s_binary.stat.exists changed_when: false - name: Wait for k3s API server to be ready on master node ansible.builtin.wait_for: host: 192.168.56.80 port: 6443 timeout: 60 delegate_to: "{{ inventory_hostname }}" when: inventory_hostname != 'vm1' and not k3s_binary.stat.exists - name: Install k3s on subsequent nodes ansible.builtin.shell: | set -o pipefail {% if inventory_hostname == 'vm2' %} NODE_IP="192.168.56.81" {% elif inventory_hostname == 'vm3' %} NODE_IP="192.168.56.82" {% else %} NODE_IP="192.168.56.80" {% endif %} K3S_URL=https://192.168.56.80:6443 \ K3S_TOKEN={{ k3s_token_content.stdout }} \ INSTALL_K3S_EXEC="server --disable traefik --disable servicelb --node-name={{ inventory_hostname }} --node-ip ${NODE_IP}" \ /bin/bash /tmp/k3s_install.sh 2>&1 exit_code=$? if [ $exit_code -ne 0 ]; then echo "K3S INSTALL FAILED - Service Status:" systemctl status k3s.service --no-pager -l | head -20 echo "Recent logs:" journalctl -u k3s.service --no-pager -l | tail -10 exit $exit_code fi args: executable: /bin/bash creates: /usr/local/bin/k3s register: k3s_install_result failed_when: false when: inventory_hostname != 'vm1' and not k3s_binary.stat.exists - name: Show k3s failure details ansible.builtin.debug: msg: "{{ k3s_install_result.stdout_lines[-30:] }}" when: inventory_hostname != 'vm1' and not k3s_binary.stat.exists and k3s_install_result.rc != 0 - name: Fail if k3s installation failed ansible.builtin.fail: msg: "K3S installation failed on {{ inventory_hostname }}" when: inventory_hostname != 'vm1' and not k3s_binary.stat.exists and k3s_install_result.rc != 0 - name: Ensure /home/vagrant/.kube directory exists ansible.builtin.file: path: /home/vagrant/.kube state: directory owner: vagrant group: vagrant mode: '0700' - name: Copy kubeconfig to vagrant user ansible.builtin.copy: src: /etc/rancher/k3s/k3s.yaml dest: /home/vagrant/.kube/config owner: vagrant group: vagrant mode: '0600' remote_src: true - name: Ensure KUBECONFIG is set in vagrant .bashrc ansible.builtin.lineinfile: path: /home/vagrant/.bashrc line: 'export KUBECONFIG=~/.kube/config' state: present insertafter: EOF owner: vagrant group: vagrant mode: '0644' - name: Ensure kubectl completion is sourced in vagrant .bashrc ansible.builtin.lineinfile: path: /home/vagrant/.bashrc line: 'source <(kubectl completion bash)' state: present insertafter: EOF owner: vagrant group: vagrant mode: '0644'