Files
cluster-knaster/platform/proxmox/ansible/roles/infra-stack/tasks/main.yml
T
Robert RappandClaude Opus 5.5 456fce2386
ci / test (push) Successful in 28s
infra-stack: Schutz gegen veralteten ZFS-Seiten-Cache nach HA-Umzug, Betriebsabschnitt 7
Bei der HA-Probe startete dockerd auf pve48 nicht (bbolt „invalid freelist page“): Nach zfs receive
liefert der Zielknoten für früher gemappte Dateien alten Inhalt aus dem Seiten-Cache. Ein oneshot-Dienst
im LXC verwirft vor containerd/docker den Cache aller Dateien (posix_fadvise DONTNEED).
BETRIEB.md Abschnitt 7: URLs, Geheimnisse (ohne Werte), file_sd auffrischen, Wiederherstellung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:49:49 +02:00

158 lines
5.7 KiB
YAML
Raw 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.
# Compose-Stack infra: Router, TTS, Postgres, Prometheus, Alertmanager, Grafana, pve-exporter, node-exporter.
# Idempotent: Geheimnisse nur anlegen, wenn sie fehlen; compose up ändert nur, was sich geändert hat.
- name: Werkzeuge
ansible.builtin.apt:
name: [rsync, openssl, curl]
state: present
update_cache: true
cache_valid_time: 3600
- name: Verzeichnisse
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
mode: "{{ item.mode }}"
loop:
- {path: /opt/knaster, mode: "0755"}
- {path: "{{ infra_repo_dir }}", mode: "0755"}
- {path: "{{ infra_state_dir }}", mode: "0700"}
- {path: "{{ infra_state_dir }}/secrets", mode: "0700"}
# Nur die Teile, die Build und Konfiguration brauchen. Nie .git, .venv, tofu-State oder .env-Dateien.
- name: Repo-Auszug von ops abgleichen
ansible.posix.synchronize:
src: "{{ infra_repo_src }}/"
dest: "{{ infra_repo_dir }}/"
delete: true
rsync_opts:
# Der Clone auf ops ist teils 0600/0700; Container-Benutzer (nobody, grafana, knaster) müssen lesen können
- "--chmod=go+rX,go-w"
- "--exclude=__pycache__"
- "--exclude=.pytest_cache"
- "--exclude=*.egg-info"
- "--exclude=.env"
- "--exclude=secrets/"
- "--include=/core/***"
- "--include=/config/***"
- "--include=/catalog/***"
- "--include=/skills/***"
- "--include=/sites/***"
- "--include=/deploy/***"
- "--exclude=*"
- name: Einstellungen in .env
ansible.builtin.lineinfile:
path: "{{ infra_state_dir }}/.env"
regexp: "^{{ item.key }}="
line: "{{ item.key }}={{ item.value }}"
create: true
mode: "0600"
loop: "{{ infra_settings | dict2items }}"
# Gibt nur Namen aus, nie Werte
- name: Fehlende Geheimnisse im Container erzeugen
ansible.builtin.shell: |
set -eu
umask 077
f={{ infra_state_dir }}/.env
for k in {{ infra_secrets | join(' ') }}; do
grep -q "^$k=" "$f" || { echo "$k=$(openssl rand -hex 24)" >> "$f"; echo "neu: $k"; }
done
chmod 0600 "$f"
args:
executable: /bin/bash
register: secrets_gen
changed_when: "'neu:' in secrets_gen.stdout"
- name: Router-Token für Alertmanager (= KNASTER_API_TOKEN, lesbar für nobody im Container)
ansible.builtin.shell: |
set -eu
umask 077
cd {{ infra_state_dir }}
v=$(sed -n 's/^KNASTER_API_TOKEN=//p' .env)
t=secrets/router_token
if [ ! -f "$t" ] || [ "$(cat "$t")" != "$v" ]; then printf '%s' "$v" > "$t"; echo geändert; fi
chown 65534:65534 "$t"
chmod 0400 "$t"
args:
executable: /bin/bash
register: router_token
changed_when: "'geändert' in router_token.stdout"
no_log: true
- name: Proxmox-Lese-Token für den pve-exporter
ansible.builtin.copy:
src: "{{ infra_pve_exporter_env }}"
dest: "{{ infra_state_dir }}/secrets/pve-exporter.env"
mode: "0600"
no_log: true
- name: file_sd-Ziele
ansible.builtin.include_tasks: targets.yml
# HA-Umzug: Nach zfs receive liefert der Zielknoten für früher gemappte Dateien veralteten Seiten-Cache
# (12.10.2026 belegt). Vor jedem Docker-Start den Cache dieses Containers verwerfen. BETRIEB.md Abschnitt 7.
- name: Schutz gegen veralteten Seiten-Cache – Skript
ansible.builtin.copy:
src: knaster-drop-stale-cache.py
dest: /usr/local/sbin/knaster-drop-stale-cache
mode: "0755"
- name: Schutz gegen veralteten Seiten-Cache – systemd-Dienst vor containerd/docker
ansible.builtin.copy:
src: knaster-drop-stale-cache.service
dest: /etc/systemd/system/knaster-drop-stale-cache.service
mode: "0644"
register: dropcache_unit
- name: Schutz gegen veralteten Seiten-Cache – aktivieren
ansible.builtin.systemd:
name: knaster-drop-stale-cache.service
enabled: true
daemon_reload: "{{ dropcache_unit.changed }}"
- name: Stack bauen und starten
ansible.builtin.command: >
docker compose -p {{ infra_compose_project }} --env-file {{ infra_state_dir }}/.env
-f {{ infra_compose_file }} up -d --build --remove-orphans
register: compose_up
changed_when: compose_up.stderr is search('Container \S+\s+(Created|Recreated|Started)')
- name: Prometheus und Alertmanager laden geänderte Konfiguration (bind-mount, kein Neustart nötig)
ansible.builtin.command: "curl -fsS -m 10 -X POST http://127.0.0.1:{{ item }}/-/reload"
loop: [9090, 9093]
register: reload
retries: 15
delay: 4
until: reload.rc == 0
changed_when: false
- name: Grafana-Konto kiosk (Viewer) anlegen, Passwort aus .env
ansible.builtin.shell: |
set -eu
cd {{ infra_state_dir }}
A=$(sed -n 's/^GRAFANA_ADMIN_PASSWORD=//p' .env)
K=$(sed -n 's/^GRAFANA_KIOSK_PASSWORD=//p' .env)
umask 077
cfg=$(mktemp)
trap 'rm -f "$cfg"' EXIT
printf 'user = "admin:%s"\n' "$A" > "$cfg" # Passwort nicht in der Prozessliste
g() { curl -sS -K "$cfg" -H 'Content-Type: application/json' "$@"; }
for i in $(seq 60); do curl -fsS -m 3 http://127.0.0.1:3000/api/health >/dev/null 2>&1 && break; sleep 2; done
code=$(g -o /dev/null -w '%{http_code}' 'http://127.0.0.1:3000/api/users/lookup?loginOrEmail=kiosk')
if [ "$code" = 404 ]; then
printf '{"name":"Kiosk","login":"kiosk","password":"%s"}' "$K" \
| g -f -X POST --data @- http://127.0.0.1:3000/api/admin/users >/dev/null
echo angelegt
elif [ "$code" != 200 ]; then
echo "Grafana-API antwortet $code" >&2
exit 1
fi
id=$(g -f 'http://127.0.0.1:3000/api/users/lookup?loginOrEmail=kiosk' | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
g -f -X PATCH --data '{"role":"Viewer"}' "http://127.0.0.1:3000/api/org/users/$id" >/dev/null
args:
executable: /bin/bash
register: kiosk
changed_when: "'angelegt' in kiosk.stdout"
no_log: true