mirror of
https://github.com/k3s-io/k3s-ansible.git
synced 2026-10-23 03:22:03 +02:00
* feat: make the server config file mode configurable /etc/rancher/k3s/config.yaml holds the cluster token. The server and upgrade roles write it at 0644, so every local account on a server node can read the credential that joins a node to the cluster. k3s_server_config_mode sets the mode of that file in both roles. It defaults to 0644, so behaviour is unchanged unless it is set. Signed-off-by: Kristofer <kristofer@atlascloud.is> * docs: describe the server config file contents accurately /etc/rancher/k3s/config.yaml does not always carry the cluster token. A first server that lets K3s generate one writes the file without it, so the file can contain the token rather than always holding it. Correct that claim in the README, the inventory sample and the role default, and use the US spelling of "honors". Signed-off-by: Kristofer <kristofer@atlascloud.is> * Name the floor the config file mode can be narrowed to Saying any mode root can read works leaves the reader to work out what that means in practice. The file is read only by k3s, running as root, so 0600 is the tightest mode that still works. Signed-off-by: Kristofer <kristofer@atlascloud.is> * Run the basic integration job with a non-default config file mode The templated mode was only ever rendered with its default in CI, which is the one value that cannot tell a working template from a broken one. The basic inventory sets 0640 and the job reads the mode back off the installed file. Signed-off-by: Kristofer <kristofer@atlascloud.is> --------- Signed-off-by: Kristofer <kristofer@atlascloud.is>
190 lines
8.6 KiB
YAML
190 lines
8.6 KiB
YAML
---
|
|
# with_fileglob doesn't work with remote_src, it tries to find the file on the
|
|
# local control-plane instead of the remote host. Shell supports wildcards.
|
|
- name: Get k3s installed version
|
|
ansible.builtin.command: k3s --version
|
|
register: k3s_upgrade_version_output
|
|
changed_when: false
|
|
check_mode: false
|
|
|
|
- name: Set k3s installed version
|
|
ansible.builtin.set_fact:
|
|
k3s_upgrade_current_version: "{{ k3s_upgrade_version_output.stdout_lines[0].split(' ')[2] }}"
|
|
check_mode: false
|
|
|
|
# We update the node configuration in the following cases:
|
|
# - the installed version of K3s on the nodes is older than the requested version in ansible vars
|
|
# - the installed version equals the requested version (to apply config changes like extra_server_args/extra_agent_args)
|
|
- name: Update node only if needed
|
|
when: k3s_upgrade_current_version is version(k3s_version, '<=')
|
|
block:
|
|
- name: Stage airgap artifacts for upgrade
|
|
when: airgap_dir is defined
|
|
ansible.builtin.include_role:
|
|
name: airgap
|
|
tasks_from: main.yml
|
|
apply:
|
|
tags:
|
|
- distribute_artifacts
|
|
|
|
# We must stop the service because we want to modify the service file before starting it again.
|
|
# INSTALL_K3S_SKIP_START does work on upgrades, because the service is already installed and started.
|
|
- name: Stop K3s service
|
|
when: k3s_upgrade_current_version is version(k3s_version, '<')
|
|
ansible.builtin.service:
|
|
state: stopped
|
|
name: "{{ (server_group in group_names) | ternary('k3s', 'k3s-agent') }}"
|
|
|
|
# We only save the token if the user did not provide one, leading to an auto-generated token on first install.
|
|
# If you want the actual token value, you need to use the k3s_upgrade_old_token.stdout
|
|
- name: Save the existing K3s token if needed
|
|
when:
|
|
- token is not defined
|
|
- inventory_hostname == groups[server_group][0] or ansible_host == groups[server_group][0]
|
|
ansible.builtin.command: cut -d':' -f4 /var/lib/rancher/k3s/server/node-token
|
|
register: k3s_upgrade_old_token
|
|
changed_when: false
|
|
|
|
- name: Construct Server config
|
|
when: server_group in group_names
|
|
block:
|
|
# Start with an empty config
|
|
- name: Set empty server config
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: {}
|
|
|
|
# If token is provided, add it to the config
|
|
- name: Add token to server config
|
|
when: token is defined
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: "{{ k3s_server_config | combine({'token': token}) }}"
|
|
|
|
# If token is not defined, use the old token
|
|
- name: Add old token to server config
|
|
when: token is not defined
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: "{{ k3s_server_config | combine({'token': k3s_upgrade_old_token.stdout}) }}"
|
|
|
|
- name: Determine if tls-san is already in config or args
|
|
# noqa var-naming[no-role-prefix]
|
|
ansible.builtin.set_fact:
|
|
_api_endpoint_in_config: >-
|
|
{% if server_config_yaml is defined and api_endpoint is defined and server_config_yaml | regex_search('tls-san:.*' + api_endpoint | regex_escape(), ignorecase=True) %}
|
|
true
|
|
{% else %}
|
|
false
|
|
{% endif %}
|
|
_api_endpoint_in_args: >-
|
|
{% if api_endpoint is defined and extra_server_args | regex_search('--tls-san[=\s]+' + api_endpoint | regex_escape(), ignorecase=True) %}
|
|
true
|
|
{% else %}
|
|
false
|
|
{% endif %}
|
|
|
|
- name: Add TLS SAN to config if needed
|
|
when:
|
|
- api_endpoint is defined
|
|
- api_endpoint != ansible_facts['hostname']
|
|
- not (_api_endpoint_in_config | trim | bool)
|
|
- not (_api_endpoint_in_args | trim | bool)
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: "{{ k3s_server_config | combine({'tls-san': api_endpoint}) }}"
|
|
|
|
- name: Add cluster-init to server config for first server in HA-IC setup
|
|
when:
|
|
- (groups[server_group] | length) > 1
|
|
- inventory_hostname == groups[server_group][0] or ansible_host == groups[server_group][0]
|
|
- not use_external_database
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: "{{ k3s_server_config | combine({'cluster-init': true}) }}"
|
|
|
|
# If not the first server in an HA-IC setup, setup the server: URL for joining the cluster
|
|
# server: https://{{ api_endpoint }}:{{ api_port }}
|
|
- name: Add server URL to server config for joining servers in HA-IC setup
|
|
when: (groups[server_group] | length) > 1 and inventory_hostname != groups[server_group][0] and not use_external_database
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: "{{ k3s_server_config | combine({'server': 'https://' + (api_endpoint | ansible.utils.ipwrap) + ':' + api_port | string}) }}"
|
|
|
|
# If the user has provided additional server config, merge it with the generated config
|
|
- name: Merge user server config with generated server config
|
|
when: server_config_yaml is defined
|
|
ansible.builtin.set_fact:
|
|
k3s_server_config: "{{ k3s_server_config | combine(server_config_yaml | from_yaml) }}"
|
|
|
|
- name: Convert server config to YAML and write to file
|
|
when: not ansible_check_mode
|
|
ansible.builtin.copy:
|
|
content: "{{ k3s_server_config | to_nice_yaml }}"
|
|
dest: "/etc/rancher/k3s/config.yaml"
|
|
mode: "{{ k3s_server_config_mode }}"
|
|
register: k3s_server_config_result
|
|
|
|
- name: Install new K3s Version [server]
|
|
# For some reason, ansible-lint thinks using enviroment with command is an error
|
|
# even though its valid https://ansible.readthedocs.io/projects/lint/rules/inline-env-var/#correct-code
|
|
# Skip if only reconfiguring (no version change needed)
|
|
when:
|
|
- k3s_upgrade_current_version is version(k3s_version, '<')
|
|
- server_group in group_names
|
|
ansible.builtin.command: # noqa inline-env-var
|
|
cmd: /usr/local/bin/k3s-install.sh
|
|
environment: >-
|
|
{{ extra_install_envs
|
|
| combine({
|
|
"INSTALL_K3S_SKIP_START": "true",
|
|
"INSTALL_K3S_VERSION": k3s_version,
|
|
"INSTALL_K3S_EXEC": extra_server_args,
|
|
})
|
|
| combine(airgap_dir is defined and {"INSTALL_K3S_SKIP_DOWNLOAD": "true"} or {}) }}
|
|
changed_when: true
|
|
|
|
- name: Get the token from the first server
|
|
# noqa var-naming[no-role-prefix]
|
|
when:
|
|
- agent_group in group_names
|
|
- token is not defined
|
|
ansible.builtin.set_fact:
|
|
k3s_upgrade_old_server_token: "{{ hostvars[groups[server_group][0]].k3s_upgrade_old_token }}"
|
|
|
|
- name: Install new K3s Version [agent]
|
|
# For some reason, ansible-lint thinks using enviroment with command is an error
|
|
# even though its valid https://ansible.readthedocs.io/projects/lint/rules/inline-env-var/#correct-code
|
|
# Unlike server, we always run the install command, because we are using it to reconfigure the ENV and Args passed to k3s-agent.
|
|
# Instead we just skip the download/replace if airgapped or no version change is needed.
|
|
when:
|
|
- agent_group in group_names
|
|
# noqa var-naming[no-role-prefix]
|
|
ansible.builtin.command:
|
|
cmd: /usr/local/bin/k3s-install.sh
|
|
environment: "{{ _install_envs }}"
|
|
vars:
|
|
_base_envs:
|
|
INSTALL_K3S_SKIP_DOWNLOAD: "{{ (airgap_dir is defined or k3s_upgrade_current_version == k3s_version) | ternary('true', 'false') }}"
|
|
INSTALL_K3S_SKIP_START: "true"
|
|
INSTALL_K3S_SYSTEMD_DIR: "{{ systemd_dir }}"
|
|
INSTALL_K3S_VERSION: "{{ k3s_version }}"
|
|
INSTALL_K3S_EXEC: "agent --server https://{{ api_endpoint | ansible.utils.ipwrap }}:{{ api_port }} {{ extra_agent_args }}"
|
|
K3S_TOKEN: "{{ token if token is defined else k3s_upgrade_old_server_token.stdout }}"
|
|
# We overrides the extra_install_envs with required keys from _base_envs on purpose
|
|
_install_envs: "{{ extra_install_envs | default({}) | combine(_base_envs) }}"
|
|
changed_when: true
|
|
|
|
- name: Reload systemd daemon
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_facts['service_mgr'] == 'systemd'
|
|
ansible.builtin.systemd:
|
|
daemon_reload: true
|
|
|
|
- name: Restart K3s service [server]
|
|
when: server_group in group_names
|
|
ansible.builtin.service:
|
|
state: restarted
|
|
name: k3s
|
|
|
|
- name: Restart K3s service [agent]
|
|
when: agent_group in group_names
|
|
ansible.builtin.service:
|
|
state: restarted
|
|
name: k3s-agent
|