Files
Compose-Files/AnisiblePlaybooks/k3sup-k3s-cluster/files/main.yml
T
2026-07-20 09:23:17 -04:00

201 lines
7.8 KiB
YAML

---
- name: Bootstrap K3s cluster with k3sup
hosts: all
gather_facts: false
<%- if secrets_file %>
vars_files:
- << secrets_file >>
<%- endif %>
vars:
k3s_server_target: "{{ hostvars['<< k3s_server_host >>'].ansible_host | default('<< k3s_server_host >>') }}"
<%- if kubeconfig_destination_mode == 'remote' %>
k3s_generated_kubeconfig_path: "/tmp/<< k3s_context_name | default('homelab-k3s') >>-kubeconfig"
<%- else %>
k3s_generated_kubeconfig_path: "<< local_kubeconfig_path >>"
<%- endif %>
tasks:
- name: Gather control machine facts
ansible.builtin.setup:
delegate_to: localhost
run_once: true
register: localhost_facts
- name: Validate that the first server host exists in inventory
ansible.builtin.assert:
that:
- "'<< k3s_server_host >>' in hostvars"
fail_msg: "Inventory host '<< k3s_server_host >>' was not found."
run_once: true
- name: Resolve k3sup release asset
ansible.builtin.set_fact:
k3sup_release_asset: >-
{%- if localhost_facts.ansible_facts.ansible_system == 'Linux' and localhost_facts.ansible_facts.ansible_architecture in ['x86_64', 'amd64'] -%}
k3sup
{%- elif localhost_facts.ansible_facts.ansible_system == 'Linux' and localhost_facts.ansible_facts.ansible_architecture in ['aarch64', 'arm64'] -%}
k3sup-arm64
{%- elif localhost_facts.ansible_facts.ansible_system == 'Linux' and localhost_facts.ansible_facts.ansible_architecture in ['armv7l', 'armv6l'] -%}
k3sup-arm
{%- elif localhost_facts.ansible_facts.ansible_system == 'Darwin' and localhost_facts.ansible_facts.ansible_architecture in ['x86_64', 'amd64'] -%}
k3sup-darwin
{%- elif localhost_facts.ansible_facts.ansible_system == 'Darwin' and localhost_facts.ansible_facts.ansible_architecture in ['arm64', 'aarch64'] -%}
k3sup-darwin-arm64
{%- else -%}
unsupported
{%- endif -%}
when: install_k3sup_binary | default(false)
run_once: true
- name: Fail when k3sup binary installation is not supported for this control machine
ansible.builtin.fail:
msg: "Automatic k3sup installation is not supported for {{ localhost_facts.ansible_facts.ansible_system }}/{{ localhost_facts.ansible_facts.ansible_architecture }}. Set install_k3sup_binary=false and install k3sup manually."
when:
- install_k3sup_binary | default(false)
- k3sup_release_asset == "unsupported"
run_once: true
- name: Ensure local directory for k3sup exists
ansible.builtin.file:
path: "{{ '<< k3sup_install_path >>' | dirname }}"
state: directory
mode: "0755"
delegate_to: localhost
become: true
when: install_k3sup_binary | default(false)
run_once: true
- name: Install k3sup binary on the control machine
ansible.builtin.get_url:
url: "https://github.com/alexellis/k3sup/releases/download/<< k3sup_version >>/{{ k3sup_release_asset }}"
dest: "<< k3sup_install_path >>"
mode: "0755"
delegate_to: localhost
become: true
when: install_k3sup_binary | default(false)
run_once: true
- name: Verify k3sup is available
ansible.builtin.command:
cmd: "<< k3sup_install_path >> version"
changed_when: false
delegate_to: localhost
run_once: true
- name: Ensure local kubeconfig directory exists when using local destination mode
ansible.builtin.file:
path: "{{ k3s_generated_kubeconfig_path | dirname }}"
state: directory
mode: "0700"
delegate_to: localhost
when: "<< kubeconfig_destination_mode >>" == "local"
run_once: true
- name: Check whether K3s is already present on the first server
ansible.builtin.stat:
path: /etc/rancher/k3s/k3s.yaml
delegate_to: "<< k3s_server_host >>"
register: k3s_server_install_state
run_once: true
- name: Bootstrap the first K3s server with k3sup
ansible.builtin.command:
cmd: >-
<< k3sup_install_path >> install
--ip {{ k3s_server_target }}
--user << k3s_server_user | default('ubuntu') >>
--ssh-port << k3s_server_ssh_port | default(22) >>
--local-path {{ k3s_generated_kubeconfig_path }}
--merge=false
--context << k3s_context_name | default('homelab-k3s') >>
<%- if k3sup_use_sudo %>
--sudo
<%- endif %>
<%- if k3s_server_ssh_key_path %>
--ssh-key << k3s_server_ssh_key_path | quote >>
<%- endif %>
<%- if extra_server_args %>
--k3s-extra-args << extra_server_args | quote >>
<%- endif %>
delegate_to: localhost
when:
- bootstrap_control_plane | default(true)
- not (k3s_server_install_state.stat.exists | default(false))
run_once: true
- name: Resolve inventory hosts for K3s agents
ansible.builtin.set_fact:
k3s_agent_inventory_hosts: "{{ query('inventory_hostnames', '<< k3s_agent_hosts_pattern >>') }}"
when: join_agent_nodes | default(true)
run_once: true
- name: Fail when agent join is enabled but no hosts match the inventory pattern
ansible.builtin.assert:
that:
- k3s_agent_inventory_hosts | length > 0
fail_msg: "No inventory hosts matched '<< k3s_agent_hosts_pattern >>'."
when: join_agent_nodes | default(true)
run_once: true
- name: Check whether K3s agent is already present on each node
ansible.builtin.stat:
path: /etc/systemd/system/k3s-agent.service
delegate_to: "{{ item }}"
loop: "{{ k3s_agent_inventory_hosts | default([]) }}"
loop_control:
label: "{{ item }}"
register: k3s_agent_install_state
when: join_agent_nodes | default(true)
run_once: true
- name: Join agent nodes to the K3s cluster with k3sup
ansible.builtin.command:
cmd: >-
<< k3sup_install_path >> join
--ip {{ hostvars[item.item].ansible_host | default(item.item) }}
--server-ip {{ k3s_server_target }}
--user << k3s_agent_user | default('ubuntu') >>
--server-user << k3s_server_user | default('ubuntu') >>
--ssh-port << k3s_agent_ssh_port | default(22) >>
--server-ssh-port << k3s_server_ssh_port | default(22) >>
<%- if k3sup_use_sudo %>
--sudo
<%- endif %>
<%- if k3s_server_ssh_key_path %>
--ssh-key << k3s_server_ssh_key_path | quote >>
<%- endif %>
<%- if extra_agent_args %>
--k3s-extra-args << extra_agent_args | quote >>
<%- endif %>
delegate_to: localhost
loop: "{{ k3s_agent_install_state.results | default([]) }}"
loop_control:
label: "{{ item.item }}"
when:
- join_agent_nodes | default(true)
- not (item.stat.exists | default(false))
run_once: true
- name: Ensure remote kubeconfig directory exists
ansible.builtin.file:
path: "{{ '<< kubeconfig_remote_path >>' | dirname }}"
state: directory
mode: "0700"
delegate_to: "<< kubeconfig_remote_host | default('localhost') >>"
become: << kubeconfig_remote_become | default(false) >>
when: "<< kubeconfig_destination_mode >>" == "remote"
run_once: true
- name: Copy kubeconfig to the remote destination host
ansible.builtin.copy:
src: "{{ k3s_generated_kubeconfig_path }}"
dest: "<< kubeconfig_remote_path >>"
owner: "<< kubeconfig_remote_owner | default('ubuntu') >>"
group: "<< kubeconfig_remote_group | default('ubuntu') >>"
mode: "<< kubeconfig_remote_mode | default('0600') >>"
delegate_to: "<< kubeconfig_remote_host | default('localhost') >>"
become: << kubeconfig_remote_become | default(false) >>
when: "<< kubeconfig_destination_mode >>" == "remote"
run_once: true