--- # Joins this node as a k3s agent (worker). Only ever runs after server.yml has # succeeded somewhere — playbooks/k3s.yml targets k3s_control_plane before # k3s_workers — so K3S_URL below always points at an already-live API server. # # --node-name pins the k8s node object to the Ansible inventory_hostname — # see the matching comment in server.yml, same reason. - name: Bootstrap the k3s agent no_log: true # K3S_TOKEN passes through this block block: - name: Look up the k3s cluster secrets ansible.builtin.set_fact: k3s_secrets: >- {{ lookup('community.hashi_vault.vault_kv2_get', k3s_vault_path, engine_mount_point=vault_kv_mount, url=vault_addr, auth_method=vault_auth_method, role_id=vault_role_id | default(omit), secret_id=vault_secret_id | default(omit)).secret }} - name: Compute the desired k3s agent exec line ansible.builtin.set_fact: k3s_agent_exec: "agent --node-name {{ inventory_hostname }} {{ k3s_extra_args | join(' ') }}" # Compared against what k3s was last installed with (see the copy task # below) so a change to k3s_extra_args gets applied on the next run # instead of silently sitting unused: the version check below has no way # to notice an exec-line-only change. Missing file (first install) counts # as changed. - name: Read the exec line k3s was last installed with ansible.builtin.slurp: src: /etc/rancher/k3s/.ansible_install_exec register: k3s_installed_exec_raw failed_when: false check_mode: false - name: Determine whether the exec line has changed ansible.builtin.set_fact: k3s_exec_changed: >- {{ k3s_installed_exec_raw.content is not defined or (k3s_installed_exec_raw.content | b64decode) != k3s_agent_exec }} - name: Check the installed k3s version ansible.builtin.command: k3s --version register: k3s_installed_version changed_when: false failed_when: false check_mode: false # The installer is safe to re-run — it's a no-op if the requested version # and exec line are already active — but skipping it when neither changed # avoids restarting the agent (and briefly dropping the node's kubelet) # on every playbook run. Restarting the k3s-agent process itself (as # opposed to rebooting the node, which roles/k3s_maintenance handles # separately) doesn't touch already-running pods — containerd keeps them # up underneath it. playbooks/k3s.yml still runs this play with # serial: 1, so at most one node's kubelet is ever bouncing at a time. - name: Install/upgrade k3s agent ansible.builtin.shell: curl -sfL https://get.k3s.io | sh - environment: INSTALL_K3S_VERSION: "{{ k3s_version }}" INSTALL_K3S_EXEC: "{{ k3s_agent_exec }}" # The one control-plane node, addressed by its inventory IP rather # than delegating a lookup to it — simple and correct as long as this # cluster stays single-server. Revisit if it ever gets HA control # plane nodes. K3S_URL: "https://{{ hostvars[groups['k3s_control_plane'][0]].ansible_host }}:6443" K3S_TOKEN: "{{ k3s_secrets.K3S_TOKEN }}" when: >- k3s_installed_version.rc != 0 or k3s_version not in k3s_installed_version.stdout or k3s_exec_changed - name: Ensure the k3s-agent service is enabled and running ansible.builtin.systemd_service: name: k3s-agent enabled: true state: started # k3s creates /etc/rancher/k3s itself once it has something to put there # (a config.yaml, the generated kubeconfig on the server) — an agent with no # extra config doesn't necessarily end up with anything else prompting that, # so this marker can't assume the directory already exists. - name: Ensure /etc/rancher/k3s exists ansible.builtin.file: path: /etc/rancher/k3s state: directory owner: root group: root mode: "0755" - name: Record the exec line k3s was installed with ansible.builtin.copy: dest: /etc/rancher/k3s/.ansible_install_exec content: "{{ k3s_agent_exec }}" owner: root group: root mode: "0600"