From 0bf7f0f59737be70f8e0330fd28e7dde2cec2dc5 Mon Sep 17 00:00:00 2001 From: Nik Afiq Date: Wed, 20 May 2026 23:17:23 +0900 Subject: [PATCH] feat: add configuration for GPU node setup and update Ollama role for cross-platform support --- ansible/host_vars/debian.yaml | 7 ++++ ansible/host_vars/minisforum.yaml | 2 + ansible/inventory.yaml | 7 ++++ ansible/playbooks/setup-gpu-node.yaml | 12 ++++++ ansible/roles/k3s-agent/tasks/main.yaml | 22 ++++++++-- ansible/roles/ollama/handlers/main.yaml | 15 +++++-- ansible/roles/ollama/tasks/main.yaml | 40 ++++++++++++++++++- .../ollama/templates/ollama-override.conf.j2 | 5 +++ 8 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 ansible/host_vars/debian.yaml create mode 100644 ansible/host_vars/minisforum.yaml create mode 100644 ansible/playbooks/setup-gpu-node.yaml create mode 100644 ansible/roles/ollama/templates/ollama-override.conf.j2 diff --git a/ansible/host_vars/debian.yaml b/ansible/host_vars/debian.yaml new file mode 100644 index 0000000..f11b48d --- /dev/null +++ b/ansible/host_vars/debian.yaml @@ -0,0 +1,7 @@ +# Host vars for: debian (k3s storage agent) +ansible_python_interpreter: /usr/bin/python3.11 + +k3s_node_labels: + node-role: storage + +k3s_node_taints: [] \ No newline at end of file diff --git a/ansible/host_vars/minisforum.yaml b/ansible/host_vars/minisforum.yaml new file mode 100644 index 0000000..9d000be --- /dev/null +++ b/ansible/host_vars/minisforum.yaml @@ -0,0 +1,2 @@ +# Host vars for: minisforum (k3s server) +ansible_python_interpreter: /usr/bin/python3.13 diff --git a/ansible/inventory.yaml b/ansible/inventory.yaml index fabadc5..c59b64e 100644 --- a/ansible/inventory.yaml +++ b/ansible/inventory.yaml @@ -23,3 +23,10 @@ all: mac-mini: ansible_host: 192.168.7.96 ansible_python_interpreter: /usr/bin/python3 + + gpu_workstation: + hosts: + gpu-node: + ansible_host: 192.168.7.98 + ansible_port: 430 + ansible_python_interpreter: /usr/bin/python3.12 \ No newline at end of file diff --git a/ansible/playbooks/setup-gpu-node.yaml b/ansible/playbooks/setup-gpu-node.yaml new file mode 100644 index 0000000..7f96eb6 --- /dev/null +++ b/ansible/playbooks/setup-gpu-node.yaml @@ -0,0 +1,12 @@ +# Config for: gpu-node workstation full setup +# Applied by: ansible-playbook -i ansible/inventory.yaml ansible/playbooks/setup-gpu-node.yaml +- name: gpu-node setup + hosts: gpu_workstation + become: true + + roles: + - role: common + - role: nvidia + - role: k3s-agent + - role: ollama + - role: glances \ No newline at end of file diff --git a/ansible/roles/k3s-agent/tasks/main.yaml b/ansible/roles/k3s-agent/tasks/main.yaml index 9f2fded..6971fe7 100644 --- a/ansible/roles/k3s-agent/tasks/main.yaml +++ b/ansible/roles/k3s-agent/tasks/main.yaml @@ -1,7 +1,8 @@ --- # Part of role: k3s-agent # Called by: ansible/playbooks/join-debian-agent.yaml -# Description: Installs K3s in agent mode, joins the cluster, and labels the node as storage. +# ansible/playbooks/setup-gpu-node.yaml +# Description: Installs K3s in agent mode, joins the cluster, labels and taints the node. - name: Download and install K3s agent ansible.builtin.shell: @@ -20,11 +21,24 @@ enabled: true become: true -- name: Label node as storage +- name: Apply node labels ansible.builtin.shell: cmd: > - k3s kubectl label node nik-debian - node-role=storage --overwrite + k3s kubectl label node {{ ansible_hostname }} + {{ item.key }}={{ item.value }} --overwrite + loop: "{{ k3s_node_labels | dict2items }}" delegate_to: minisforum become: true changed_when: false + when: k3s_node_labels is defined and k3s_node_labels | length > 0 + +- name: Apply node taints + ansible.builtin.shell: + cmd: > + k3s kubectl taint node {{ ansible_hostname }} + {{ item }} --overwrite + loop: "{{ k3s_node_taints }}" + delegate_to: minisforum + become: true + changed_when: false + when: k3s_node_taints is defined and k3s_node_taints | length > 0 \ No newline at end of file diff --git a/ansible/roles/ollama/handlers/main.yaml b/ansible/roles/ollama/handlers/main.yaml index bca10ab..195b14f 100644 --- a/ansible/roles/ollama/handlers/main.yaml +++ b/ansible/roles/ollama/handlers/main.yaml @@ -1,8 +1,17 @@ --- # Part of role: ollama # Called by: ansible/playbooks/setup-ollama.yaml -# Description: Handlers for the ollama role. Restarts the ollama launchd daemon when the plist changes. - +# ansible/playbooks/setup-gpu-node.yaml +# Description: Handlers for the ollama role. Restarts ollama on config changes. - name: restart ollama become: true - command: launchctl kickstart -k system/com.ollama.ollama \ No newline at end of file + command: launchctl kickstart -k system/com.ollama.ollama + when: ansible_system == 'Darwin' + +- name: restart ollama linux + ansible.builtin.systemd: + name: ollama + state: restarted + daemon_reload: true + become: true + when: ansible_system == 'Linux' \ No newline at end of file diff --git a/ansible/roles/ollama/tasks/main.yaml b/ansible/roles/ollama/tasks/main.yaml index b85e065..1c924c2 100644 --- a/ansible/roles/ollama/tasks/main.yaml +++ b/ansible/roles/ollama/tasks/main.yaml @@ -1,12 +1,16 @@ --- # Part of role: ollama # Called by: ansible/playbooks/setup-ollama.yaml -# Description: Installs Ollama via Homebrew, deploys the launchd plist so it starts on boot bound to all interfaces, and pulls configured models. +# ansible/playbooks/setup-gpu-node.yaml +# Description: Installs Ollama, configures it to bind to all interfaces, and pulls models. +# Supports macOS (Homebrew + launchd) and Linux (install script + systemd). +# ── macOS ────────────────────────────────────────────────────────────────────── - name: Install ollama via Homebrew community.general.homebrew: name: ollama state: present + when: ansible_system == 'Darwin' - name: Deploy ollama launchd plist template: @@ -17,6 +21,7 @@ mode: "0644" become: true notify: restart ollama + when: ansible_system == 'Darwin' - name: Load ollama launchd service become: true @@ -24,7 +29,36 @@ args: creates: /var/run/ollama.pid ignore_errors: true + when: ansible_system == 'Darwin' +# ── Linux ────────────────────────────────────────────────────────────────────── +- name: Install ollama via install script + ansible.builtin.shell: + cmd: curl -fsSL https://ollama.com/install.sh | sh + creates: /usr/local/bin/ollama + when: ansible_system == 'Linux' + +- name: Deploy ollama systemd override + ansible.builtin.template: + src: ollama-override.conf.j2 + dest: /etc/systemd/system/ollama.service.d/override.conf + owner: root + group: root + mode: "0644" + become: true + notify: restart ollama linux + when: ansible_system == 'Linux' + +- name: Enable and start ollama service + ansible.builtin.systemd: + name: ollama + state: started + enabled: true + daemon_reload: true + become: true + when: ansible_system == 'Linux' + +# ── shared ───────────────────────────────────────────────────────────────────── - name: Wait for ollama to be ready uri: url: "http://localhost:{{ ollama_port }}" @@ -41,7 +75,9 @@ register: ollama_tags - name: Pull ollama models - command: /opt/homebrew/bin/ollama pull {{ item }} + command: > + {{ '/opt/homebrew/bin/ollama' if ansible_system == 'Darwin' else '/usr/local/bin/ollama' }} + pull {{ item }} loop: "{{ ollama_models }}" when: item not in (ollama_tags.json.models | map(attribute='name') | list) environment: diff --git a/ansible/roles/ollama/templates/ollama-override.conf.j2 b/ansible/roles/ollama/templates/ollama-override.conf.j2 new file mode 100644 index 0000000..1e1d7ae --- /dev/null +++ b/ansible/roles/ollama/templates/ollama-override.conf.j2 @@ -0,0 +1,5 @@ +# Managed by Ansible — do not edit manually +[Service] +Environment="OLLAMA_HOST=0.0.0.0" +Environment="OLLAMA_PORT={{ ollama_port }}" +Environment="OLLAMA_MODELS={{ ollama_models_dir | default('/usr/share/ollama/.ollama/models') }}" \ No newline at end of file