Goal: Prepare Linux nodes for k3s by disabling swap, setting required sysctl and kernel modules, and opening firewall ports via UFW. The actual k3s install starts in Day 4.
Reference environment: Kubuntu 25 host (fullstacklab.site
), SSH user stackadmin
; VMs: master 192.168.56.10
, workers 192.168.56.11
/.12
; networking as in Day 1–2.
Step 0 — Pre-flight (Ansible playbook)
This playbook disables swap (runtime and on boot), applies required sysctl values, and ensures kernel modules overlay
and br_netfilter
are loaded now and at boot.
# ansible/preflight.yml
---
- name: k3s preflight (swap, sysctl, modules)
hosts: k3s_master:k3s_workers
become: true
tasks:
- name: Disable swap now (if present)
ansible.builtin.command: swapoff -a
when: (ansible_swaptotal_mb | int) > 0
changed_when: false
- name: Comment swap entries in /etc/fstab
ansible.builtin.lineinfile:
path: /etc/fstab
regexp: '^[^#].*[[:space:]]swap[[:space:]]'
line: '# \g<0>'
backrefs: true
- name: Sysctl - enable IP forwarding
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: true
state: present
reload: true
- name: Sysctl - bridge nfcall (IPv4)
ansible.posix.sysctl:
name: net.bridge.bridge-nf-call-iptables
value: '1'
sysctl_set: true
state: present
reload: true
- name: Sysctl - bridge nfcall (IPv6)
ansible.posix.sysctl:
name: net.bridge.bridge-nf-call-ip6tables
value: '1'
sysctl_set: true
state: present
reload: true
- name: Ensure modules load at boot
ansible.builtin.copy:
dest: /etc/modules-load.d/k8s.conf
mode: '0644'
content: |
overlay
br_netfilter
- name: Load modules now
ansible.builtin.modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
Run it:
ansible-playbook -i ansible/inventory/hosts.ini ansible/preflight.yml
Step 1 — Firewall (UFW via Ansible)
We use UFW for simplicity. SSH port 22 is explicitly allowed first, then k3s ports: API (master: 6443/TCP), VXLAN (all nodes: 8472/UDP), and NodePort range (all nodes: 30000–32767/TCP+UDP) for future services.
Note: If you have a different SSH port, adjust port: "22"
accordingly.
# ansible/firewall.yml
---
- name: Ensure UFW installed and SSH allowed
hosts: all
become: true
tasks:
- name: Install UFW
ansible.builtin.package:
name: ufw
state: present
- name: Allow SSH (22/tcp) before enabling firewall
community.general.ufw:
rule: allow
port: "22"
proto: tcp
- name: Enable UFW (keep default policies)
community.general.ufw:
state: enabled
logging: 'on'
- name: Master rules (API + VXLAN + NodePort)
hosts: k3s_master
become: true
tasks:
- community.general.ufw:
rule: allow
port: "6443"
proto: tcp
- community.general.ufw:
rule: allow
port: "8472"
proto: udp
- community.general.ufw:
rule: allow
port: "30000:32767"
proto: tcp
- community.general.ufw:
rule: allow
port: "30000:32767"
proto: udp
- name: Worker rules (VXLAN + NodePort)
hosts: k3s_workers
become: true
tasks:
- community.general.ufw:
rule: allow
port: "8472"
proto: udp
- community.general.ufw:
rule: allow
port: "30000:32767"
proto: tcp
- community.general.ufw:
rule: allow
port: "30000:32767"
proto: udp
Run it: (First install the collection if needed)
ansible-galaxy collection install community.general
ansible-playbook -i ansible/inventory/hosts.ini ansible/firewall.yml
What’s next (Day 4)
We’ll set a strong k3s token, run the Ansible k3s role to install the master and join workers, and verify the cluster with kubectl
.