Files
2026-10-15 17:26:00 +02:00

197 lines
7.1 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
- name: Site-Datei laden
ansible.builtin.set_fact:
knaster_pve: "{{ lookup('ansible.builtin.file', pve_site_file) | from_yaml }}"
run_once: true
delegate_to: localhost
- name: Bootloader erkennen (systemd-boot bei ZFS-Root, sonst GRUB)
ansible.builtin.stat:
path: /etc/kernel/cmdline
register: kernel_cmdline
- name: IOMMU aktivieren (systemd-boot)
ansible.builtin.replace:
path: /etc/kernel/cmdline
regexp: '^((?!.*intel_iommu=on).*)$'
replace: '\1 {{ pve_iommu_cmdline }}'
when: kernel_cmdline.stat.exists
notify: refresh boot
- name: IOMMU aktivieren (GRUB)
ansible.builtin.lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX_DEFAULT="((?!.*intel_iommu=on).*)"$'
line: 'GRUB_CMDLINE_LINUX_DEFAULT="\1 {{ pve_iommu_cmdline }}"'
backrefs: true
when: not kernel_cmdline.stat.exists
notify: refresh boot
- name: VFIO-Module laden
ansible.builtin.copy:
dest: /etc/modules-load.d/vfio.conf
content: "{{ pve_vfio_modules | join('\n') }}\n"
mode: "0644"
notify: update initramfs
# IDs auf dem Knoten lesen, nicht aus dem Gedächtnis: Grafik- und Audio-Funktion jeder Karte
- name: NVIDIA-Funktionen des Knotens lesen
ansible.builtin.shell: |
set -o pipefail
lspci -n -d 10de: | awk '{print $3}' | sort -u | paste -sd,
args:
executable: /bin/bash
register: nvidia_ids
check_mode: false
changed_when: false
failed_when: nvidia_ids.rc != 0 or nvidia_ids.stdout == ''
- name: Karten an vfio-pci binden, bevor ein Grafik- oder Audiotreiber zugreift
ansible.builtin.copy:
dest: /etc/modprobe.d/vfio.conf
content: |
options vfio-pci ids={{ nvidia_ids.stdout }}
softdep nouveau pre: vfio-pci
softdep nvidia pre: vfio-pci
softdep nvidiafb pre: vfio-pci
softdep snd_hda_intel pre: vfio-pci
mode: "0644"
notify: update initramfs
- name: NVIDIA-Treiber auf dem Host sperren (GPU gehört der VM)
ansible.builtin.copy:
dest: /etc/modprobe.d/blacklist-nvidia.conf
content: |
blacklist nouveau
blacklist nvidia
blacklist nvidiafb
mode: "0644"
notify: update initramfs
# ZFS-ARC begrenzen: Standard wären 10 % des RAM (3,2 GB), bei Pool-Anlage 4 GB gesetzt. Die GPU-VMs liegen auf
# local-lvm, tank trägt nur Replikate und die kleinen Infra-Gäste – 2 GB reichen, der Rest geht an die VMs.
- name: ZFS-ARC-Obergrenze (modprobe, gilt nach initramfs beim nächsten Start)
ansible.builtin.copy:
dest: /etc/modprobe.d/zfs.conf
content: "options zfs zfs_arc_max={{ knaster_pve.cluster.zfs_arc_max_mb * 1024 * 1024 }}
"
mode: "0644"
when: knaster_pve.cluster.zfs_arc_max_mb is defined
notify: update initramfs
- name: ZFS-ARC-Obergrenze sofort setzen
ansible.builtin.shell: >
[ -w /sys/module/zfs/parameters/zfs_arc_max ] || exit 0;
v={{ knaster_pve.cluster.zfs_arc_max_mb * 1024 * 1024 }};
[ "$(cat /sys/module/zfs/parameters/zfs_arc_max)" = "$v" ] && exit 0;
echo "$v" > /sys/module/zfs/parameters/zfs_arc_max && echo gesetzt
register: arc
changed_when: "'gesetzt' in arc.stdout"
when: knaster_pve.cluster.zfs_arc_max_mb is defined
- name: Speicher local darf Snippets enthalten (clusterweite Einstellung, einmal)
ansible.builtin.shell: |
set -euo pipefail
c=$(pvesh get /storage/local --output-format json | python3 -c 'import json,sys; print(json.load(sys.stdin)["content"])')
case ",$c," in
*,snippets,*) echo unverändert ;;
*) pvesm set local --content "$c,snippets"; echo geändert ;;
esac
args:
executable: /bin/bash
register: snippets
changed_when: "'geändert' in snippets.stdout"
run_once: true
- name: Snippet-Verzeichnis
ansible.builtin.file:
path: "{{ pve_vendor_snippet | dirname }}"
state: directory
mode: "0755"
- name: cloud-init-Vendor-Daten für GPU-VMs (qemu-guest-agent meldet tofu die DHCP-Adresse)
ansible.builtin.copy:
dest: "{{ pve_vendor_snippet }}"
content: |
#cloud-config
packages: [qemu-guest-agent]
runcmd:
- [systemctl, enable, --now, qemu-guest-agent]
mode: "0644"
- name: Container auf diesem Knoten lesen
ansible.builtin.command: ls /etc/pve/lxc/
register: local_cts
check_mode: false
changed_when: false
- name: VMs auf diesem Knoten lesen
ansible.builtin.command: ls /etc/pve/qemu-server/
register: local_vms
check_mode: false
changed_when: false
# Infra-Gäste = Container (ct:) plus Dienst-VMs ohne GPU (vm:, D6); beide liegen auf tank mit HA
- name: Infra-Gäste zusammenstellen
ansible.builtin.set_fact:
pve_infra_guests: >-
{{ (knaster_pve.containers | dict2items | map('combine', {'kind': 'ct'}) | list)
+ (knaster_pve.service_vms | default({}) | dict2items | map('combine', {'kind': 'vm'}) | list) }}
pve_local_guest_confs: "{{ local_cts.stdout_lines + local_vms.stdout_lines }}"
- name: Bestehende Replikationsjobs lesen
ansible.builtin.command: pvesr list
register: pvesr_jobs
check_mode: false
changed_when: false
- name: ZFS-Replikation für Infra-Gäste (erst wenn der Container auf diesem Knoten existiert)
ansible.builtin.command: >
pvesr create-local-job {{ item.0.value.vmid }}-{{ idx }} {{ item.1 }}
--schedule '{{ knaster_pve.replication_schedule }}' --comment 'knaster {{ item.0.key }}'
loop: "{{ pve_infra_guests | subelements('value.replicate_to', skip_missing=True) }}"
vars:
idx: "{{ item.0.value.replicate_to.index(item.1) }}"
when:
- item.0.value.node == inventory_hostname
- (item.0.value.vmid | string) + '.conf' in pve_local_guest_confs
- (item.0.value.vmid | string) + '-' + (idx | string) not in pvesr_jobs.stdout
changed_when: true
- name: HA-Konfiguration lesen
ansible.builtin.command: ha-manager config
register: ha_config
check_mode: false
changed_when: false
- name: Infra-Gäste unter HA stellen (erst wenn der Container auf diesem Knoten existiert)
ansible.builtin.command: >
ha-manager add {{ item.kind }}:{{ item.value.vmid }} --state started --max_restart 1 --max_relocate 1
--comment 'knaster {{ item.key }}'
loop: "{{ pve_infra_guests }}"
when:
- item.value.ha | default(false)
- item.value.node == inventory_hostname
- (item.value.vmid | string) + '.conf' in pve_local_guest_confs
- (item.kind + ':' + (item.value.vmid | string)) not in ha_config.stdout
changed_when: true
- name: HA-Regeln lesen
ansible.builtin.command: ha-manager rules config
register: ha_rules
check_mode: false
changed_when: false
# Strikt: Die Gäste liegen auf tank, den gibt es nur auf dem Heimatknoten und den Replikationszielen
- name: Node-Affinity für Infra-Gäste (Heimatknoten bevorzugt, sonst Replikationsziele)
ansible.builtin.command: >
ha-manager rules add node-affinity knaster-{{ item.key }} --resources {{ item.kind }}:{{ item.value.vmid }}
--nodes {{ ([item.value.node ~ ':2'] + (item.value.replicate_to | map('regex_replace', '$', ':1') | list)) | join(',') }}
--strict 1 --comment 'knaster {{ item.key }}'
loop: "{{ pve_infra_guests }}"
when:
- item.value.ha | default(false)
- item.value.node == inventory_hostname
- (item.value.vmid | string) + '.conf' in pve_local_guest_confs
- ('knaster-' + item.key) not in ha_rules.stdout
changed_when: true