Files
cluster/k3s/ansible/create-cluster.yml
Khwezi Mngoma 0410dc3950 first commit
2026-02-22 16:43:17 +02:00

256 lines
7.7 KiB
YAML

---
- name: Gather IPv4 address facts for all hosts
hosts: all
gather_facts: yes
vars:
dns_server: "192.168.1.151"
tasks:
- name: Configure systemd-resolved to use custom DNS
become: true
copy:
dest: /etc/systemd/resolved.conf
content: |
[Resolve]
DNS={{ dns_server }}
FallbackDNS=192.168.1.1
Domains=mngoma.lab
DNSStubListener=yes
owner: root
group: root
mode: "0644"
- name: Ensure systemd-resolved service is enabled and restarted
become: true
systemd:
name: systemd-resolved
state: restarted
enabled: yes
- name: Ensure host IPv4 address is available and stored as fact
set_fact:
node_ipv4: "{{ ansible_default_ipv4.address }}"
when: ansible_default_ipv4 is defined and ansible_default_ipv4.address is defined
- name: Fail if IPv4 address could not be determined
fail:
msg: "Could not determine IPv4 address for {{ inventory_hostname }}. Please check network configuration."
when: node_ipv4 is not defined
- name: Ensure /home/{{ ansible_user }}/k3s directory exists
become: yes
file:
path: /home/{{ ansible_user }}/k3s
state: directory
owner: root
group: root
mode: '0777'
- name: Initialise the K3s control plane (manager)
hosts: manager
become: yes
vars:
k3s_version: v1.29.4+k3s1
kubeconfig_dir: "/home/{{ ansible_user }}/.kube"
kubeconfig_file: "{{ kubeconfig_dir }}/config"
tasks:
- name: Install required apt dependencies
apt:
name:
- curl
- python3-pip
- python3-venv
state: present
update_cache: yes
- name: Create a Python virtual environment for Ansible k8s modules
command: python3 -m venv /opt/ansible-venv
args:
creates: /opt/ansible-venv
- name: Install Kubernetes and OpenShift libraries in the venv
command: /opt/ansible-venv/bin/pip install kubernetes openshift
- name: Install k3s on manager (control plane)
shell: |
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION={{ k3s_version }} sh -
args:
creates: /usr/local/bin/k3s
- name: Gather architecture for kubectl
set_fact:
kubectl_arch: |
{% if ansible_architecture == "x86_64" %}
amd64
{% elif "armv7l" in ansible_architecture %}
arm
{% elif "aarch64" in ansible_architecture %}
arm64
{% else %}
{{ ansible_architecture }}
{% endif %}
- name: Download latest kubectl binary
shell: |
curl -Lo /usr/local/bin/kubectl "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/{{ kubectl_arch }}/kubectl"
args:
creates: /usr/local/bin/kubectl
- name: Make kubectl executable
file:
path: /usr/local/bin/kubectl
mode: '0755'
owner: root
group: root
- name: Validate kubectl version
shell: kubectl version --client --output=yaml
register: kubectl_version
changed_when: false
- name: Show kubectl version
debug:
var: kubectl_version.stdout
- name: Ensure .kube directory exists for ansible user
become_user: "{{ ansible_user }}"
file:
path: "{{ kubeconfig_dir }}"
state: directory
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0700'
- name: Copy kubeconfig file to ansible user home
become: true
copy:
src: /etc/rancher/k3s/k3s.yaml
dest: "{{ kubeconfig_file }}"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: '0600'
remote_src: yes
- name: Replace server IP in kubeconfig with manager's IP address
become_user: "{{ ansible_user }}"
lineinfile:
path: "{{ kubeconfig_file }}"
regexp: 'server: https://127\\.0\\.0\\.1:6443'
line: " server: https://{{ node_ipv4 }}:6443"
- name: Get the cluster join token
shell: cat /var/lib/rancher/k3s/server/node-token
register: k3s_token
changed_when: false
- name: Set fact for join token and manager IP
set_fact:
k3s_node_token: "{{ k3s_token.stdout }}"
manager_ip: "{{ node_ipv4 }}"
- name: Add the join token and manager IP to hostvars for workers
add_host:
name: "cluster_primary"
groups: join_info
k3s_node_token: "{{ k3s_node_token }}"
k3s_manager_ip: "{{ manager_ip }}"
- name: Install and join worker nodes to the control plane
hosts: workers
become: yes
vars:
k3s_version: v1.29.4+k3s1
tasks:
- name: Install required dependencies
apt:
name: [curl]
state: present
update_cache: yes
- name: Ensure /home/{{ ansible_user }}/k3s directory exists
file:
path: /home/{{ ansible_user }}/k3s
state: directory
owner: root
group: root
mode: '0777'
- name: Set manager join information
set_fact:
k3s_node_token: "{{ hostvars[groups['join_info'][0]]['k3s_node_token'] }}"
k3s_manager_ip: "{{ hostvars[groups['join_info'][0]]['k3s_manager_ip'] }}"
- name: Fail if manager's IP is not available
fail:
msg: "Could not determine manager's IP for joining cluster!"
when: k3s_manager_ip is not defined
- name: Install k3s agent (worker)
shell: |
curl -sfL https://get.k3s.io | K3S_URL=https://{{ k3s_manager_ip }}:6443 K3S_TOKEN={{ k3s_node_token }} INSTALL_K3S_VERSION={{ k3s_version }} sh -
args:
creates: /usr/local/bin/k3s-agent
- name: Gather architecture for kubectl
set_fact:
kubectl_arch: |
{% if ansible_architecture == "x86_64" %}
amd64
{% elif "armv7l" in ansible_architecture %}
arm
{% elif "aarch64" in ansible_architecture %}
arm64
{% else %}
{{ ansible_architecture }}
{% endif %}
- name: Download latest kubectl binary (worker)
shell: |
curl -Lo /usr/local/bin/kubectl "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/{{ kubectl_arch }}/kubectl"
args:
creates: /usr/local/bin/kubectl
- name: Make kubectl executable (worker)
file:
path: /usr/local/bin/kubectl
mode: '0755'
owner: root
group: root
- name: Verify cluster nodes from manager node and configure storage
hosts: manager
become: yes
vars:
kubeconfig_file: "/home/{{ ansible_user }}/.kube/config"
tasks:
- name: Wait for all worker nodes to join the cluster
become_user: "{{ ansible_user }}"
shell: |
for i in {1..10}; do
[ $(kubectl --kubeconfig={{ kubeconfig_file }} get nodes | grep -c worker) -ge 1 ] && exit 0
sleep 15
done
exit 1
register: wait_worker
failed_when: wait_worker.rc != 0
- name: List all k3s nodes
become_user: "{{ ansible_user }}"
shell: kubectl --kubeconfig={{ kubeconfig_file }} get nodes -o wide
register: all_nodes
- name: Show current k3s cluster nodes
debug:
var: all_nodes.stdout
- name: Create StorageClass for /home/ansible/k3s INLINE
vars:
ansible_python_interpreter: /opt/ansible-venv/bin/python
kubernetes.core.k8s:
kubeconfig: "{{ kubeconfig_file }}"
definition:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-pvs
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer