Skip to main content

Ansible

Why Ansible?

K3s cluster creation requires knowing server node IPs to connect other nodes. Since my router assigns IPs dynamically via DHCP, I can't hardcode them in cloud-init config.

The solution: Terraform process generates an inventory.yml with node IPs, then Ansible uses this to install and configure k3s.

Alternative Approach

A simpler alternative would be configuring a static IP for the first server node and referencing it in cloud-init configs for other nodes to join the cluster. This approach would eliminate the need for Ansible.

TODO: Test this approach.

Install

I use pipx to install Ansible.

# install pipx
sudo apt install -y pipx
pipx ensurepath

# install ansible
pipx install --include-deps ansible

Deployment

Required Files

  1. inventory.yml - Generated by Terraform with node IPs and k3s token.
  2. playbook.yml - Defines k3s installation and copying config file to local ~/.kube/config.
# inventory.yml
all:
hosts:
%{~ for name, details in nodes ~}
${name}:
ansible_host: ${details.ip}
%{~ endfor ~}
vars:
k3s_token: ${k3s_token}

k3s_servers:
hosts:
%{~ for name, details in nodes ~}
%{~ if details.role == "server" ~}
${name}:
%{~ endif ~}
%{~ endfor ~}

k3s_agents:
hosts:
%{~ for name, details in nodes ~}
%{~ if details.role == "agent" ~}
${name}:
%{~ endif ~}
%{~ endfor ~}
# playbook.yml
- hosts: k3s_servers
tasks:
- name: Install K3S server
shell: >
curl -sfL https://get.k3s.io |
sh -s - server --cluster-init
--disable servicelb
--kube-proxy-arg proxy-mode=ipvs
--kube-proxy-arg ipvs-strict-arp
environment:
K3S_TOKEN: '{{ k3s_token }}'
args:
creates: /usr/local/bin/k3s

- hosts: k3s_servers[0]
vars:
k3s_server: "{{ groups['k3s_servers'][0] }}"
k3s_url: "https://{{ hostvars[k3s_server]['ansible_host'] }}:6443"
tasks:
- name: Display K3S config
shell: k3s kubectl config view --raw
become: true
register: config_output
- name: Update server URL in config
set_fact:
updated_config: "{{ config_output.stdout | regex_replace('server: .*', 'server: ' + k3s_url) }}"
- name: Copy K3S config to local.
copy:
content: '{{ updated_config }}'
dest: '/home/viet/.kube/config'
delegate_to: localhost

- hosts: k3s_agents
vars:
k3s_server: "{{ groups['k3s_servers'][0] }}"
k3s_url: "https://{{ hostvars[k3s_server]['ansible_host'] }}:6443"
tasks:
- name: Install K3S agent
shell: >
curl -sfL https://get.k3s.io |
sh -s - agent
environment:
K3S_TOKEN: '{{ k3s_token }}'
K3S_URL: '{{ k3s_url }}'
args:
creates: /usr/local/bin/k3s

Execution

ANSIBLE_HOST_KEY_CHECKING=False is needed to avoid typing yes when Ansible connecting to the VM for the first time.

ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i inventory.yml playbook.yml