Files
k3s-ansible/roles/k3s_server/tasks/main.yml
anon-software 040d37878b Prevent multiple tokens in k3s.service.env (#364)
* Prevent multiple tokens in k3s.service.env

If site.yml playbook is executed multiple times with different tokens,
they will all accumulate in k3s.service.env. They won't do any harm
because the last one wins, however it is a matter of good housekeeping
to delete the old before inserting a new one.

Signed-off-by: Marko Vukovic <8951449+anon-software@users.noreply.github.com>

* Selectively remove existing token from the environment file

If the existing token in the environment file is the same as the token
used for the playbook run, leave it in the file to avoid false changed
status from the task.

Signed-off-by: Marko Vukovic <8951449+anon-software@users.noreply.github.com>

---------

Signed-off-by: Marko Vukovic <8951449+anon-software@users.noreply.github.com>
2024-10-07 09:44:28 -07:00

291 lines
9.9 KiB
YAML

---
- name: Get k3s installed version
ansible.builtin.command: k3s --version
register: k3s_version_output
changed_when: false
ignore_errors: true
- name: Set k3s installed version
when: k3s_version_output.rc == 0
ansible.builtin.set_fact:
installed_k3s_version: "{{ k3s_version_output.stdout_lines[0].split(' ')[2] }}"
# If airgapped, all K3s artifacts are already on the node.
# We should be downloading and installing the newer version only if we are in one of the following cases :
# - we couldn't get k3s installed version in the first task of this role
# - the installed version of K3s on the nodes is older than the requested version in ansible vars
- name: Download artifact only if needed
when: airgap_dir is undefined and ( k3s_version_output.rc != 0 or installed_k3s_version is version(k3s_version, '<') )
block:
- name: Download K3s install script
ansible.builtin.get_url:
url: https://get.k3s.io/
timeout: 120
dest: /usr/local/bin/k3s-install.sh
owner: root
group: root
mode: "0755"
- name: Download K3s binary
ansible.builtin.command:
cmd: /usr/local/bin/k3s-install.sh
environment:
INSTALL_K3S_SKIP_START: "true"
INSTALL_K3S_VERSION: "{{ k3s_version }}"
changed_when: true
- name: Add K3s autocomplete to user bashrc
ansible.builtin.lineinfile:
path: "~{{ ansible_user }}/.bashrc"
regexp: '\.\s+<\(k3s completion bash\)'
line: ". <(k3s completion bash) # Added by k3s-ansible"
- name: Setup optional config file
when: server_config_yaml is defined
block:
- name: Make config directory
ansible.builtin.file:
path: "/etc/rancher/k3s"
mode: "0755"
state: directory
- name: Copy config values
ansible.builtin.copy:
content: "{{ server_config_yaml }}"
dest: "/etc/rancher/k3s/config.yaml"
mode: "0644"
- name: Init first server node
when: inventory_hostname == groups[server_group][0]
block:
- name: Copy K3s service file [Single]
when: groups[server_group] | length == 1 or use_external_database
ansible.builtin.template:
src: "k3s-single.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_single
- name: Copy K3s service file [HA]
when:
- groups[server_group] | length > 1
- not use_external_database
ansible.builtin.template:
src: "k3s-cluster-init.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_ha
- name: Add service environment variables
when: extra_service_envs is defined
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "{{ item }}"
with_items: "{{ extra_service_envs }}"
- name: Delete any existing token from the environment if different from the new one
ansible.builtin.lineinfile:
state: absent
path: "{{ systemd_dir }}/k3s.service.env"
regexp: "^K3S_TOKEN=\\s*(?!{{ token }}\\s*$)"
# Add the token to the environment.
- name: Add token as an environment variable
no_log: true # avoid logging the server token
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "K3S_TOKEN={{ token }}"
- name: Restart K3s service
when:
- ansible_facts.services['k3s.service'] is defined
- ansible_facts.services['k3s.service'].state == 'running'
- service_file_single.changed or service_file_ha.changed
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: restarted
- name: Enable and check K3s service
when: ansible_facts.services['k3s.service'] is not defined or ansible_facts.services['k3s.service'].state != 'running'
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: started
enabled: true
- name: Pause to allow first server startup
when: (groups[server_group] | length) > 1
ansible.builtin.pause:
seconds: 10
- name: Check whether kubectl is installed on control node
ansible.builtin.command: 'kubectl'
register: kubectl_installed
ignore_errors: true
delegate_to: 127.0.0.1
become: false
changed_when: false
# Copy the k3s config to a second file to detect changes.
# If no changes are found, we can skip copying the kubeconfig to the control node.
- name: Copy k3s.yaml to second file
ansible.builtin.copy:
src: /etc/rancher/k3s/k3s.yaml
dest: /etc/rancher/k3s/k3s-copy.yaml
mode: "0600"
remote_src: true
register: copy_k3s_yaml_file
- name: Apply K3S kubeconfig to control node
when:
- kubectl_installed.rc == 0
- copy_k3s_yaml_file.changed
block:
- name: Copy kubeconfig to control node
ansible.builtin.fetch:
src: /etc/rancher/k3s/k3s.yaml
dest: "{{ kubeconfig }}"
flat: true
- name: Change server address in kubeconfig on control node
ansible.builtin.shell: |
KUBECONFIG={{ kubeconfig }} kubectl config set-cluster default --server=https://{{ api_endpoint }}:{{ api_port }}
delegate_to: 127.0.0.1
become: false
register: csa_result
changed_when:
- csa_result.rc == 0
- name: Setup kubeconfig context on control node - {{ cluster_context }}
when: kubeconfig != "~/.kube/config"
ansible.builtin.replace:
path: "{{ kubeconfig }}"
regexp: 'name: default'
replace: 'name: {{ cluster_context }}'
delegate_to: 127.0.0.1
become: false
- name: Merge with any existing kubeconfig on control node
when: kubeconfig != "~/.kube/config"
ansible.builtin.shell: |
TFILE=$(mktemp)
KUBECONFIG={{ kubeconfig }} kubectl config set-context {{ cluster_context }} --user={{ cluster_context }} --cluster={{ cluster_context }}
KUBECONFIG={{ kubeconfig }} kubectl config view --flatten > ${TFILE}
mv ${TFILE} {{ kubeconfig }}
delegate_to: 127.0.0.1
become: false
register: mv_result
changed_when:
- mv_result.rc == 0
- name: Start other server if any and verify status
when:
- (groups[server_group] | length) > 1
- inventory_hostname != groups[server_group][0]
block:
- name: Delete any existing token from the environment if different from the new one
ansible.builtin.lineinfile:
state: absent
path: "{{ systemd_dir }}/k3s.service.env"
regexp: "^K3S_TOKEN=\\s*(?!{{ token }}\\s*$)"
- name: Add the token for joining the cluster to the environment
no_log: true # avoid logging the server token
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "{{ item }}"
with_items:
- "K3S_TOKEN={{ token }}"
- name: Copy K3s service file [HA]
when: not use_external_database
ansible.builtin.template:
src: "k3s-ha.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_ha
- name: Copy K3s service file [External DB]
when: use_external_database
ansible.builtin.template:
src: "k3s-single.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_external_db
- name: Restart K3s service
when:
- ansible_facts.services['k3s.service'] is defined
- ansible_facts.services['k3s.service'].state == 'running'
- service_file_ha.changed or service_file_external_db.changed
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: restarted
- name: Enable and check K3s service
when: ansible_facts.services['k3s.service'] is not defined or ansible_facts.services['k3s.service'].state != 'running'
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: started
enabled: true
- name: Verify that all server nodes joined
when: (groups[server_group] | length) > 1
ansible.builtin.command:
cmd: >
k3s kubectl get nodes -l "node-role.kubernetes.io/control-plane=true" -o=jsonpath="{.items[*].metadata.name}"
register: nodes
until: nodes.rc == 0 and (nodes.stdout.split() | length) == (groups[server_group] | length)
retries: 20
delay: 10
changed_when: false
- name: Setup kubectl for user
when: user_kubectl
block:
- name: Create kubectl symlink
when: lookup('fileglob', '/usr/local/bin/kubectl', errors='warn') | length == 0
ansible.builtin.file:
src: /usr/local/bin/k3s
dest: /usr/local/bin/kubectl
state: link
- name: Create directory .kube
ansible.builtin.file:
path: ~{{ ansible_user }}/.kube
state: directory
owner: "{{ ansible_user }}"
mode: "u=rwx,g=rx,o="
- name: Copy config file to user home directory
ansible.builtin.copy:
src: /etc/rancher/k3s/k3s.yaml
dest: ~{{ ansible_user }}/.kube/config
remote_src: true
owner: "{{ ansible_user }}"
mode: "u=rw,g=,o="
- name: Configure default KUBECONFIG for user
ansible.builtin.lineinfile:
path: ~{{ ansible_user }}/.bashrc
regexp: 'export KUBECONFIG=~/.kube/config'
line: 'export KUBECONFIG=~/.kube/config # Added by k3s-ansible'
state: present
- name: Configure kubectl autocomplete
ansible.builtin.lineinfile:
path: ~{{ ansible_user }}/.bashrc
regexp: '\.\s+<\(kubectl completion bash\)'
line: ". <(kubectl completion bash) # Added by k3s-ansible"