GNAI-007: ROCm-Probelauf hinzugefügt.

This commit is contained in:
2026-09-21 12:40:17 +02:00
parent 2f2dbc3252
commit 83668557e5
8 changed files with 355 additions and 31 deletions
+4 -4
View File
@@ -2,7 +2,7 @@
Dokumentation für die Infrastruktur eines privaten Homelabs mit öffentlich erreichbaren Webdiensten, einem WireGuard-Zugang und einem dedizierten KI-Server. Dieses Repository hält Architekturentscheidungen, den belegten Betriebsstand und Verfahren für Einrichtung, Betrieb und Sicherheitsabnahme fest.
> **Projektstand: 20.09.2026.** Die Dokumentationsrevisionen sind zusammengeführt. Mehrere Sicherheitsmaßnahmen und technische Endabnahmen stehen noch aus. Auf dem KI-Server sind Host-Baseline, Podman, getrennte rootless Workload-Konten und der Gerätezugriff der KI-Konten auf beide AMD-GPUs eingerichtet; LLM- und Encoding-Anwendungen sind noch nicht installiert.
> **Projektstand: 20.09.2026.** Die Dokumentationsrevisionen sind zusammengeführt. Mehrere Sicherheitsmaßnahmen und technische Endabnahmen stehen noch aus. Auf dem KI-Server sind Host-Baseline, Podman, getrennte rootless Workload-Konten und der Gerätezugriff der KI-Konten auf beide AMD-GPUs eingerichtet. Ein gepinnter `llama.cpp`-ROCm-Build erkennt beide Karten im rootless Testing-Container; dauerhafte LLM- und Encoding-Anwendungen sind noch nicht installiert.
## Überblick
@@ -26,7 +26,7 @@ Die drei vorgesehenen VPN-Netzwerkrollen sind **Familie** (gesamtes Heimnetz), *
| Bereich | Belegter Stand | Nächster Nachweis oder Schritt |
| --- | --- | --- |
| KI-Server | Debian-Basissystem, Deployment-Zugang, Podman 5.4.2, drei getrennte rootless Workload-Konten und geprüfter Zugriff beider KI-Konten auf `/dev/kfd` sowie zwei AMD-Render-Nodes | ROCm im rootless `llama.cpp`-Container prüfen und danach den Testing-Stack bereitstellen |
| KI-Server | Debian-Basissystem, Deployment-Zugang, Podman 5.4.2, drei getrennte rootless Workload-Konten sowie zwei als `gfx1030` und als `llama.cpp`-ROCm-Geräte geprüfte RX 6900 XT | `llama.cpp` als Testing-Quadlet mit geprüftem Modellprofil bereitstellen |
| VPN | wg-easy v15.4.0 auf CT 105 aktiv; ein externer Laptop-Teiltest liegt vor | Rollenrechte serverseitig umsetzen und mit erlaubten sowie gesperrten Zielen testen |
| Reverse Proxy | NPM auf CT 103 dokumentiert; Fail2Ban laut Betreiber fest gepinnt und wieder in Betrieb | Effektive Jails, Sperren und Wiederanlauf prüfen |
| Identität | Keycloak/OIDC laut Betreiber produktiv für Vaultwarden | Öffentlich erreichbare Keycloak-Administration sperren und den OIDC-Login erneut prüfen |
@@ -41,11 +41,11 @@ Der [Dokumentationsindex](docs/GNAI-000-DOC_Index.md) enthält die datierten Que
| [Plattform-Dokumentation](docs/platform/README.md) | Hostbasis, Zugriffsmodell, Reverse Proxy und VPN |
| [KI-Dokumentation](docs/ai/README.md) | KI-Zielarchitektur und nicht finale Ansible-Deployment-Planung |
| [Video-Encoding](docs/video-encoding/GNENC-000-DOC_Index.md) | getrennter Planungs- und späterer SOP-Bereich für den CPU-Encoding-Workload |
| [Ansible-Control-Projekt](ansible/README.md) | lokale Einrichtung, Preflight, Deployment-Account, Host-Baseline, Podman, Workload-Konten und AMD-GPU-Zugriff |
| [Ansible-Control-Projekt](ansible/README.md) | lokale Einrichtung, Preflight, Deployment-Account, Host-Baseline, Podman, Workload-Konten, AMD-GPU-Zugriff und rootless ROCm-Probe |
## Arbeiten mit dem Repository
Dieses Repository enthält Dokumentation und ein Ansible-Control-Projekt. Es prüft Inventar, SSH-Zugang, Hostidentität, Betriebssystem und die dokumentierten GPUs. Gemeinsame Rollen verwalten Plattform, Podman und getrennte Workload-Identitäten. KI- und Encoding-Fachdokumentation bleiben in getrennten Bereichen; Images und Container sind noch nicht bereitgestellt. Vor einer Infrastrukturänderung den Ist-Stand am betroffenen Host prüfen, die passende Fachanleitung lesen und die dort genannten Abnahmeschritte dokumentieren.
Dieses Repository enthält Dokumentation und ein Ansible-Control-Projekt. Es prüft Inventar, SSH-Zugang, Hostidentität, Betriebssystem und die dokumentierten GPUs. Gemeinsame Rollen verwalten Plattform, Podman und getrennte Workload-Identitäten. KI- und Encoding-Fachdokumentation bleiben in getrennten Bereichen. Im Testing-Store liegt nur das gepinnte ROCm-Probeimage; dauerhafte Anwendungscontainer sind noch nicht bereitgestellt. Vor einer Infrastrukturänderung den Ist-Stand am betroffenen Host prüfen, die passende Fachanleitung lesen und die dort genannten Abnahmeschritte dokumentieren.
WireGuard-Profile enthalten private Schlüssel. Sie gehören nicht in Git, Ausgaben oder freigegebene Dokumente. Das lokale Verzeichnis `docs/platform/GNAI-006-profiles/` schließt Profil-Dateien über eine eigene `.gitignore` aus; es ist kein Verteiler- oder Backup-Ort für Zugangsdaten.
+44 -4
View File
@@ -184,7 +184,47 @@ On the current host, the verified devices are `/dev/kfd`,
remains outside that group. The final convergence run reported
`ok=55 changed=0 unreachable=0 failed=0`.
This proves host-level device permissions only. No ROCm userspace image has
been pulled and no GPU workload has run yet. The next workload check must pass
these devices into a rootless container with `GroupAdd=keep-groups` and prove
that `llama.cpp` detects both cards as `gfx1030`.
This proves host-level device permissions. The separate container probe below
verifies the next layer without creating a permanent service.
## Rootless ROCm container probe
The dedicated verification playbook uses `gnai-testing` and an immutable amd64
manifest of the official `llama.cpp` ROCm image:
```text
version: b11058
revision: f072b103714dfa1eee531f80b24512faf38e3dd2
digest: sha256:b429b8be10d3d0353a09c98f4ab840fe516f779858a28f9fd4e5bdf10bc63cb4
```
It passes `/dev/kfd` and both discovered render nodes with
`--group-add=keep-groups`. `rocminfo` must report exactly two `gfx1030` agents,
and `llama-server --list-devices` must expose exactly two ROCm devices. No
architecture override is set.
Run the probe from the `ansible/` directory:
```bash
../.venv/bin/ansible-playbook \
--inventory inventories/host/hosts.yml \
playbooks/verify-rocm-container.yml \
--syntax-check
../.venv/bin/ansible-playbook \
--inventory inventories/host/hosts.yml \
playbooks/verify-rocm-container.yml \
--check \
--private-key ~/.ssh/id_ed25519_ghostnet_ai_ansible_deploy
../.venv/bin/ansible-playbook \
--inventory inventories/host/hosts.yml \
playbooks/verify-rocm-container.yml \
--private-key ~/.ssh/id_ed25519_ghostnet_ai_ansible_deploy
```
The verified live run on 2026-09-20 reported
`ok=33 changed=0 unreachable=0 failed=0`. The ephemeral probe containers are
removed; the pinned image remains in the separate Testing image store for the
next deployment step. This proves ROCm discovery and the `llama.cpp` backend,
but not model loading, multi-GPU splitting or inference.
@@ -0,0 +1,11 @@
---
- name: Verify rootless ROCm access for the AI Testing account
hosts: llm_servers
become: true
gather_facts: true
gather_subset:
- min
roles:
- role: amd_gpu_access
- role: rocm_container_probe
@@ -0,0 +1,17 @@
# Rootless ROCm container probe
This verification role pulls one immutable amd64 manifest of the official
`llama.cpp` `server-rocm` image into the `gnai-testing` rootless Podman store.
It verifies the OCI image revision and build version, then runs
`rocminfo` and `llama-server --list-devices` in ephemeral containers.
The probe uses the same security-relevant options planned for the permanent
Quadlet: `/dev/kfd`, only the discovered AMD render nodes and
`GroupAdd=keep-groups`. It sets no graphics-architecture override, publishes no
port, mounts no model and removes the probe container after execution. The
pinned image remains in the Testing store for the subsequent `llama.cpp`
deployment.
Success proves that ROCm sees two `gfx1030` agents and that `llama.cpp` exposes
both as usable ROCm devices to the rootless Testing container. It does not yet
prove model loading, multi-GPU splitting or inference.
@@ -0,0 +1,12 @@
---
rocm_probe_account:
name: gnai-testing
uid: 981
home: /var/lib/ghostnet-ai/testing
rocm_probe_image: >-
ghcr.io/ggml-org/llama.cpp@sha256:b429b8be10d3d0353a09c98f4ab840fe516f779858a28f9fd4e5bdf10bc63cb4
rocm_probe_expected_image_revision: f072b103714dfa1eee531f80b24512faf38e3dd2
rocm_probe_expected_image_version: b11058
rocm_probe_expected_architecture: gfx1030
rocm_probe_expected_device_count: 2
@@ -0,0 +1,204 @@
---
- name: Verify ROCm probe declarations and discovered devices
ansible.builtin.assert:
that:
- rocm_probe_account.name | length > 0
- rocm_probe_account.uid | int > 0
- rocm_probe_account.home is match("^/")
- rocm_probe_image is match("^ghcr\.io/.+@sha256:[0-9a-f]{64}$")
- rocm_probe_expected_image_revision is match("^[0-9a-f]{40}$")
- rocm_probe_expected_image_version | length > 0
- rocm_probe_expected_architecture is match("^gfx[0-9]+$")
- rocm_probe_expected_device_count | int > 0
- amd_gpu_render_devices | length == rocm_probe_expected_device_count | int
fail_msg: ROCm probe inputs or AMD render-device discovery are invalid.
- name: Read rootless Podman OCI runtime
ansible.builtin.command:
argv:
- /usr/sbin/runuser
- --user
- "{{ rocm_probe_account.name }}"
- --
- /usr/bin/env
- "HOME={{ rocm_probe_account.home }}"
- "XDG_RUNTIME_DIR=/run/user/{{ rocm_probe_account.uid }}"
- /usr/bin/podman
- info
- --format=json
chdir: "{{ rocm_probe_account.home }}"
changed_when: false
check_mode: false
register: rocm_probe_podman_info_command
- name: Parse rootless Podman OCI runtime
ansible.builtin.set_fact:
rocm_probe_podman_info: "{{ rocm_probe_podman_info_command.stdout | from_json }}"
- name: Require crun for rootless keep-groups support
ansible.builtin.assert:
that:
- rocm_probe_podman_info.host.ociRuntime.name == "crun"
- rocm_probe_podman_info.host.security.rootless
fail_msg: The ROCm probe requires rootless Podman with the crun OCI runtime.
- name: Check whether the pinned ROCm image is already present
ansible.builtin.command:
argv:
- /usr/sbin/runuser
- --user
- "{{ rocm_probe_account.name }}"
- --
- /usr/bin/env
- "HOME={{ rocm_probe_account.home }}"
- "XDG_RUNTIME_DIR=/run/user/{{ rocm_probe_account.uid }}"
- /usr/bin/podman
- image
- exists
- "{{ rocm_probe_image }}"
chdir: "{{ rocm_probe_account.home }}"
changed_when: false
failed_when: rocm_probe_image_exists.rc not in [0, 1]
check_mode: false
register: rocm_probe_image_exists
- name: Pull the pinned ROCm image into the Testing store
ansible.builtin.command:
argv:
- /usr/sbin/runuser
- --user
- "{{ rocm_probe_account.name }}"
- --
- /usr/bin/env
- "HOME={{ rocm_probe_account.home }}"
- "XDG_RUNTIME_DIR=/run/user/{{ rocm_probe_account.uid }}"
- /usr/bin/podman
- pull
- "{{ rocm_probe_image }}"
chdir: "{{ rocm_probe_account.home }}"
changed_when: true
when:
- not ansible_check_mode
- rocm_probe_image_exists.rc == 1
- name: Inspect the pinned ROCm image
ansible.builtin.command:
argv:
- /usr/sbin/runuser
- --user
- "{{ rocm_probe_account.name }}"
- --
- /usr/bin/env
- "HOME={{ rocm_probe_account.home }}"
- "XDG_RUNTIME_DIR=/run/user/{{ rocm_probe_account.uid }}"
- /usr/bin/podman
- image
- inspect
- --format=json
- "{{ rocm_probe_image }}"
chdir: "{{ rocm_probe_account.home }}"
changed_when: false
register: rocm_probe_image_inspect_command
when: not ansible_check_mode
- name: Parse the pinned ROCm image metadata
ansible.builtin.set_fact:
rocm_probe_image_metadata: >-
{{ (rocm_probe_image_inspect_command.stdout | from_json) | first }}
when: not ansible_check_mode
- name: Verify the pinned ROCm image metadata
ansible.builtin.assert:
that:
- >-
rocm_probe_image_metadata.Labels['org.opencontainers.image.revision'] ==
rocm_probe_expected_image_revision
- >-
rocm_probe_image_metadata.Labels['org.opencontainers.image.version'] ==
rocm_probe_expected_image_version
fail_msg: The pulled ROCm image metadata does not match the pinned build.
when: not ansible_check_mode
- name: Detect both AMD GPU architectures through ROCm in a rootless container
ansible.builtin.command:
argv: >-
{{
[
'/usr/sbin/runuser',
'--user', rocm_probe_account.name,
'--',
'/usr/bin/env',
'HOME=' + rocm_probe_account.home,
'XDG_RUNTIME_DIR=/run/user/' + (rocm_probe_account.uid | string),
'/usr/bin/podman',
'run', '--rm', '--pull=never',
'--group-add=keep-groups'
]
+ ((['/dev/kfd'] + amd_gpu_render_devices)
| map('regex_replace', '^', '--device=') | list)
+ [
'--entrypoint=/usr/bin/rocminfo',
rocm_probe_image
]
}}
chdir: "{{ rocm_probe_account.home }}"
changed_when: false
register: rocm_probe_rocminfo_output
when: not ansible_check_mode
- name: Verify ROCm reported both expected GPU architectures
ansible.builtin.assert:
that:
- >-
(rocm_probe_rocminfo_output.stdout + rocm_probe_rocminfo_output.stderr)
| regex_findall("(?m)^\\s*Name:\\s+" ~ rocm_probe_expected_architecture ~ "\\s*$")
| length == rocm_probe_expected_device_count | int
fail_msg: >-
rocminfo did not report the expected architecture for both AMD GPUs.
when: not ansible_check_mode
- name: Detect both AMD GPUs through llama.cpp in a rootless container
ansible.builtin.command:
argv: >-
{{
[
'/usr/sbin/runuser',
'--user', rocm_probe_account.name,
'--',
'/usr/bin/env',
'HOME=' + rocm_probe_account.home,
'XDG_RUNTIME_DIR=/run/user/' + (rocm_probe_account.uid | string),
'/usr/bin/podman',
'run', '--rm', '--pull=never',
'--group-add=keep-groups'
]
+ ((['/dev/kfd'] + amd_gpu_render_devices)
| map('regex_replace', '^', '--device=') | list)
+ [rocm_probe_image, '--list-devices']
}}
chdir: "{{ rocm_probe_account.home }}"
changed_when: false
register: rocm_probe_device_output
when: not ansible_check_mode
- name: Verify llama.cpp reported both expected ROCm devices
ansible.builtin.assert:
that:
- >-
(rocm_probe_device_output.stdout + rocm_probe_device_output.stderr)
| regex_findall("(?m)^\s*ROCm[0-9]+:")
| unique | length == rocm_probe_expected_device_count | int
fail_msg: >-
The rootless llama.cpp ROCm image did not report both expected GPUs.
when: not ansible_check_mode
- name: Report verified rootless ROCm devices
ansible.builtin.debug:
msg:
account: "{{ rocm_probe_account.name }}"
image: "{{ rocm_probe_image }}"
image_version: "{{ rocm_probe_expected_image_version }}"
image_revision: "{{ rocm_probe_expected_image_revision }}"
architecture: "{{ rocm_probe_expected_architecture }}"
devices: "{{ amd_gpu_render_devices }}"
when: not ansible_check_mode
+14 -2
View File
@@ -47,7 +47,7 @@ Der KI-Server heißt laut lesendem SSH-Abgleich vom 18.09.2026 `ghostnet-ki`; da
Die getrennten Schlüsselzugänge für `ghost` und `ghost-agent` wurden am 19.09.2026 erfolgreich getestet. Der persönliche Login wurde vom Betreiber interaktiv bestätigt; der Agentenlogin wurde technisch gegen Benutzername und Hostname geprüft.
Der KI-Server wurde als frisches Debian-Basissystem begonnen. Inzwischen sind die dokumentierten Ansible-Zugänge, die minimale Host-Baseline und Podman eingerichtet. Die LLM-Anwendungen sind weiterhin nicht installiert; GNAI-003 und GNAI-004 beschreiben für sie ein Zielbild.
Der KI-Server wurde als frisches Debian-Basissystem begonnen. Inzwischen sind die dokumentierten Ansible-Zugänge, die minimale Host-Baseline und Podman eingerichtet. Ein gepinntes ROCm-Probeimage liegt im rootless Testing-Store und hat beide GPUs erkannt; dauerhafte LLM-Anwendungen sind weiterhin nicht installiert. GNAI-003 und GNAI-004 beschreiben für sie ein Zielbild.
Der [Ansible-Deployment-Entwurf](ai/GNAI-007-PLAN_Ansible-Deployment.md) persistiert den seit dem 19.09.2026 fortgeschriebenen Planungs- und Implementierungsstand. Er ist ausdrücklich keine verbindliche Spezifikation und kein Nachweis einer vollständig eingerichteten Deploymentkette. Die dort genannten Runner-, Freigabe- und Secret-Verfahren sind bis zu ihrer Prüfung und formalen Übernahme vorläufig.
@@ -61,7 +61,9 @@ Die Rolle `podman_runtime` wurde am 20.09.2026 angewendet. Sie installierte Podm
Die Rolle `workload_accounts` richtete am 20.09.2026 die gesperrten Konten `gnai-production` (UID/GID 980), `gnai-testing` (981) und `gn-encoding` (982) mit festen, getrennten SubID-Bereichen ein. Konfiguration bleibt rootverwaltet; Daten, rootless Podman-Stores und persistente systemd-User-Manager sind pro Workload getrennt. Der korrigierte Gesamtlauf meldete `ok=36 changed=0 unreachable=0 failed=0` und bestätigte drei unterschiedliche rootless Graph Roots. Images und Container wurden nicht angelegt.
Die Rolle `amd_gpu_access` bestätigte am 20.09.2026 zwei Sapphire-Navi-21-Geräte `1002:73bf` mit dem Kernel-Treiber `amdgpu`, `/dev/kfd` sowie die zugehörigen Render-Nodes `/dev/dri/renderD128` und `/dev/dri/renderD129`. Alle drei Geräte verwenden die Gruppe `render`. `gnai-production` und `gnai-testing` besitzen nachweislich Lese-/Schreibzugriff; `gn-encoding` erhielt keine GPU-Gruppe. Nach Beseitigung einer konkurrierenden Gruppenverwaltung endete der Gesamtlauf mit `ok=55 changed=0 unreachable=0 failed=0`. ROCm im Container und tatsächliche Inferenz sind damit noch nicht nachgewiesen.
Die Rolle `amd_gpu_access` bestätigte am 20.09.2026 zwei Sapphire-Navi-21-Geräte `1002:73bf` mit dem Kernel-Treiber `amdgpu`, `/dev/kfd` sowie die zugehörigen Render-Nodes `/dev/dri/renderD128` und `/dev/dri/renderD129`. Alle drei Geräte verwenden die Gruppe `render`. `gnai-production` und `gnai-testing` besitzen nachweislich Lese-/Schreibzugriff; `gn-encoding` erhielt keine GPU-Gruppe. Nach Beseitigung einer konkurrierenden Gruppenverwaltung endete der Gesamtlauf mit `ok=55 changed=0 unreachable=0 failed=0`. Dieser Rollenlauf allein wies ROCm im Container oder tatsächliche Inferenz noch nicht nach.
Das getrennte Playbook `verify-rocm-container.yml` lud am 20.09.2026 für `gnai-testing` den offiziellen `llama.cpp`-ROCm-Build `b11058` als unveränderliches amd64-Manifest `sha256:b429b8be10d3d0353a09c98f4ab840fe516f779858a28f9fd4e5bdf10bc63cb4`. Mit `/dev/kfd`, beiden Render-Nodes und `keep-groups` meldete `rocminfo` genau zwei `gfx1030`-Agents; `llama-server --list-devices` meldete `ROCm0` und `ROCm1` als Radeon RX 6900 XT. Der abschließende Lauf endete mit `ok=33 changed=0 unreachable=0 failed=0`. Die Probecontainer wurden entfernt; dauerhafter Container-, Modell- und Inferenzbetrieb sind damit noch nicht abgenommen.
## 3. Sicherheitsbefunde mit Priorität
@@ -116,4 +118,14 @@ deckte auf, dass `workload_accounts` ergänzende Gruppen wieder entfernte. Nach
Der Abschlusslauf war mit `changed=0` idempotent; Images und Container blieben
weiterhin leer.
Der anschließende rootless ROCm-Probelauf verwendete das Image ausschließlich
über seinen amd64-Manifest-Digest. Die OCI-Labels bestätigten Build `b11058`
und Revision `f072b103714dfa1eee531f80b24512faf38e3dd2`. Zwei kurzlebige
Container prüften mit denselben minimalen Geräteoptionen zunächst die
Architektur über `rocminfo` und anschließend die Geräteerkennung von
`llama-server`. Beide RX 6900 XT wurden als `gfx1030` und als getrennte
`ROCm0`-/`ROCm1`-Geräte erkannt. Der finale Wiederholungslauf meldete
`changed=0`; das Image bleibt im Testing-Store, laufende Container, Modelle
und Inferenz wurden nicht eingerichtet.
Die WireGuard-Evidenz bleibt der Teiltest vom 12.09.2026: CachyOS-Laptop von WAN, Handshake, Ping auf Gateway/Proxmox und direkter IPv4-Internetpfad bestanden; KI-Server war ausgeschaltet. Neue Rollen, weitere Clientvarianten, Gateway-GUI-Zugriff, WAN-/IPv6-Isolation, Neustart und Restore sind noch nicht abgenommen. GNAI-006 ist erst nach Klärung der offenen Werte, Umsetzung und dokumentierter Abnahme technisch abgeschlossen.
+49 -21
View File
@@ -30,6 +30,7 @@
| 2026-09-20 | 0.9 | spektr / Codex | getrennte rootless Konten für AI Production, AI Testing und CPU-Encoding eingerichtet; Parallelitäts- und Repository-Grenzen ergänzt |
| 2026-09-20 | 0.10 | spektr / Codex | ROCm als Backend für zwei RX 6900 XT, initialen `llama.cpp`-Modellstand und Layer-Split mit gleicher GPU-Gewichtung festgehalten |
| 2026-09-20 | 0.11 | spektr / Codex | AMD-Gerätezugriff für beide rootless KI-Konten implementiert, angewendet und idempotent geprüft |
| 2026-09-20 | 0.12 | spektr / Codex | gepinnten rootless ROCm-Probelauf für Testing implementiert; zwei `gfx1030`-Agents und zwei `llama.cpp`-ROCm-Geräte nachgewiesen |
---
@@ -122,7 +123,7 @@ Planungsrichtung und noch nicht bestätigten Implementierungsdetails.
| Thema | Aktueller Planungsstand | Verbindlichkeit / Nachweis |
| --- | --- | --- |
| Konfigurationsmanagement | Ansible beschreibt Basissystem, Laufzeitumgebung, Dienste und Konfiguration | Control-Projekt, Preflight, `host_baseline`, `podman_runtime` und `workload_accounts` vorhanden und angewendet; GPU- und Anwendungsrollen fehlen noch |
| Konfigurationsmanagement | Ansible beschreibt Basissystem, Laufzeitumgebung, Dienste und Konfiguration | Control-Projekt, Preflight, `host_baseline`, `podman_runtime`, `workload_accounts`, `amd_gpu_access` und der ROCm-Container-Probelauf vorhanden und angewendet; Anwendungsrollen fehlen noch |
| Quell- und Freigabeverfahren | Änderungen über Gitea-Branches und Pull Requests; kein regulärer Direkt-Push auf `main` | vorgesehen; Branch-Schutz noch nicht geprüft oder eingerichtet |
| CI | Pull Requests erhalten Lint-, YAML- und Ansible-Syntaxprüfungen ohne produktive Zugangsdaten | vorgesehen; Workflow noch nicht vorhanden |
| Produktionsausführung | Gitea Actions startet Ansible über eine dedizierte Production-Berechtigungsstufe | bevorzugte Lösung; Gitea-Version, Runner-Trennung und Actions-Funktion noch zu prüfen |
@@ -391,8 +392,11 @@ Als Ausgangspunkt dient eine bereits auf einer RX 7900 XTX verwendete
Podman-Compose-Konfiguration. Die Serverumsetzung wird daraus mit folgenden
Abweichungen als rootless Quadlet erzeugt:
- das Image `ghcr.io/ggml-org/llama.cpp:server-rocm` wird auf eine geprüfte
Version und den zugehörigen Digest festgelegt;
- das Image `ghcr.io/ggml-org/llama.cpp:server-rocm` ist für den ersten
Testing-Stand als Build `b11058`, Revision
`f072b103714dfa1eee531f80b24512faf38e3dd2` und amd64-Manifest
`sha256:b429b8be10d3d0353a09c98f4ab840fe516f779858a28f9fd4e5bdf10bc63cb4`
festgelegt;
- `/dev/kfd` und die tatsächlich benötigten `/dev/dri`-Geräte werden explizit
eingebunden; `GroupAdd=keep-groups` erhält die nötigen ergänzenden
Geräte-Gruppen im rootless Container;
@@ -442,12 +446,13 @@ angebundenen Slot läuft. `row` wird wegen seiner Ablösung im aktuellen
mehr Kommunikation zwischen den Karten und ist mit dem geplanten
quantisierten V-KV-Cache derzeit nicht kompatibel.
Vor dem dauerhaften Start muss ein begrenzter Test `gfx1030`, beide GPUs,
Device-Reihenfolge, verfügbaren VRAM und die tatsächliche 1:1-Verteilung in
den `llama.cpp`-Startlogs bestätigen. Zusätzlich werden Prompt-Verarbeitung,
Token-Generierung, VRAM-Nutzung und Stabilität bei 51.200 Token Kontext
gemessen. Der 1:1-Wert ist erst nach diesem Test ein abgenommener
Betriebsparameter.
Der rootless Container-Probelauf hat inzwischen zwei `gfx1030`-Agents sowie
`ROCm0` und `ROCm1` mit jeweils rund 16 GiB VRAM bestätigt. Vor dem dauerhaften
Start muss ein begrenzter Modelltest noch die Device-Reihenfolge und die
tatsächliche 1:1-Verteilung in den `llama.cpp`-Startlogs bestätigen. Zusätzlich
werden Prompt-Verarbeitung, Token-Generierung, VRAM-Nutzung und Stabilität bei
51.200 Token Kontext gemessen. Der 1:1-Wert ist erst nach diesem Test ein
abgenommener Betriebsparameter.
---
@@ -627,8 +632,9 @@ nicht als Nachweis einer erfolgreichen Einrichtung.
- Podman- und Quadlet-Grundruntime sowie getrennte rootless Workload-Konten
eingerichtet und geprüft;
- rootless Host-Gerätezugriff auf beide RX 6900 XT eingerichtet und geprüft;
- ROCm-Funktion im rootless Container prüfen;
- `llama.cpp` und lokaler Funktionstest;
- ROCm-Funktion und `llama.cpp`-Geräteerkennung im rootless Testing-Container
mit gepinntem Image geprüft;
- `llama.cpp` mit Modell und lokalem Inferenztest;
- Wiederanlauf nach geplantem Reboot prüfen.
### Phase E – Anwendungen und Veröffentlichung
@@ -676,9 +682,9 @@ Vor der technischen Spezifikation sind mindestens folgende Punkte zu klären:
Wiederanlauf von Production sicher, wenn Runner oder Testing ausfallen?
15. Welche internen Hostnamen und Ports erhält Testing, und welche LAN-/VPN-
Rollen dürfen darauf zugreifen?
16. Funktioniert der benötigte AMD-GPU-Zugriff zuverlässig aus den getrennten
rootless Konten, und welche Gruppen-, Device- und Containeroptionen sind
dafür minimal erforderlich?
16. Muss der für Testing nachgewiesene AMD-GPU-Zugriff vor der ersten
Production-Freigabe mit demselben gepinnten Image separat unter
`gnai-production` abgenommen werden?
17. Wie wird ein Testing-Deployment eines Pull-Request-Commits in der
eingesetzten Gitea-Version autorisiert, ohne Production-Secrets oder
Production-Runner für veränderbaren PR-Code verfügbar zu machen?
@@ -844,26 +850,48 @@ bleibt ohne GPU-Gruppe. Der korrigierte Gesamtlauf endete mit
`ok=55 changed=0 unreachable=0 failed=0`. Weder ein ROCm-Image noch ein
Container oder eine Inferenz wurden dabei ausgeführt.
Danach wurde `verify-rocm-container.yml` mit der eigenständigen Rolle
`rocm_container_probe` ergänzt. Das Playbook wiederholt zunächst den
Host-Gerätenachweis und arbeitet anschließend ausschließlich im rootless
Podman-Store von `gnai-testing`. Es verwendet das offizielle
`llama.cpp`-ROCm-Image als unveränderliches amd64-Manifest
`sha256:b429b8be10d3d0353a09c98f4ab840fe516f779858a28f9fd4e5bdf10bc63cb4`
und prüft dessen OCI-Labels auf Build `b11058` und Revision
`f072b103714dfa1eee531f80b24512faf38e3dd2`.
Die ephemeren Probecontainer erhielten nur `/dev/kfd`, die beiden zuvor
ermittelten Render-Nodes und `keep-groups`; ein
`HSA_OVERRIDE_GFX_VERSION` wurde nicht gesetzt. `rocminfo` meldete genau zwei
GPU-Agents mit `gfx1030`. `llama-server --list-devices` meldete getrennt
`ROCm0` und `ROCm1`, beide als AMD Radeon RX 6900 XT mit jeweils rund 16 GiB
VRAM. Der Abschlusslauf endete mit
`ok=33 changed=0 unreachable=0 failed=0`. Die Probecontainer wurden durch
`--rm` entfernt; das gepinnte Image bleibt für den folgenden Testing-Aufbau im
Store. Modellladen, Layer-Verteilung und Inferenz wurden noch nicht geprüft.
---
## 15. Abschlussgrenze dieses Entwurfs
Mit Version 0.11 sind der aktuelle Planungsstand, der ausdrücklich begrenzte
Mit Version 0.12 sind der aktuelle Planungsstand, der ausdrücklich begrenzte
Ansible-Preflight, der verifizierte Deployment-Account und die angewendete
minimale Host-Baseline, die Podman-/Quadlet-Grundruntime und die getrennten
Workload-Konten sowie deren begrenzter AMD-Gerätezugriff persistiert.
Workload-Konten, deren begrenzter AMD-Gerätezugriff sowie der rootless
ROCm-/`llama.cpp`-Gerätenachweis für Testing persistiert.
Insbesondere wurden noch nicht:
- ein Gitea Runner angelegt,
- Gitea Actions oder Schutzregeln konfiguriert,
- eine ROCm-Container- oder Anwendungsrolle, ein Production-Inventar oder ein
- eine dauerhafte `llama.cpp`-Anwendungsrolle, ein Production-Inventar oder ein
Vault erstellt,
- eine Production- oder Testing-Umgebung eingerichtet oder voneinander
abgenommen,
- ROCm-Userspace, GPU-Container oder Anwendungen auf dem KI-Server installiert,
- ein dauerhafter GPU-Container, ein Modell oder eine Anwendung auf dem
KI-Server eingerichtet,
- Backups oder Rollbacks praktisch getestet oder
- die geplante Deploymentkette technisch abgenommen.
Der nächste technische Schritt ist ein begrenzter rootless ROCm-Container-Test
für beide KI-Konten, der beide Karten als `gfx1030` erkennen muss. Darauf bauen
die `llama.cpp`-Rolle, das initiale Testing-Modellprofil und später LiteLLM auf.
Der nächste technische Schritt ist die `llama.cpp`-Rolle für Testing. Sie soll
das gepinnte Image als rootless Quadlet betreiben, das initiale Modell mit
geprüfter Checksumme einbinden und den vorgesehenen Layer-Split sowie eine
reale Inferenz abnehmen. Darauf baut anschließend LiteLLM auf.