Add GitOps runtime image drift alert
This commit is contained in:
@@ -17,6 +17,16 @@ Dieses Dokument ist nur noch ein historischer Verlauf. Der aktuelle operative Ab
|
|||||||
|
|
||||||
## Historische Meilensteine
|
## Historische Meilensteine
|
||||||
|
|
||||||
|
### 2026-05-31 - Komodo Deploy-Drift strukturell abgesichert
|
||||||
|
|
||||||
|
Nach dem Renovate-Block wurde die Ursache fuer den kurzzeitigen `nextcloud-postgres`-Drift nachgezogen: Komodo hatte den `nextcloud`-Stack beim Postgres-17.10-Deploy gestartet, aber `docker compose up -d` scheiterte zunaechst an einem Docker-Recreate-Namenskonflikt (`nextcloud-postgres` Ersatzcontainer). Der Workspace war dadurch bereits auf dem neuen Commit, waehrend der laufende DB-Container noch das alte Image nutzte. Der spaetere gezielte `docker compose up -d` aus dem aktualisierten Workspace hat den Zwischenzustand sauber aufgeloest; es blieben keine exited/dead Containerreste.
|
||||||
|
|
||||||
|
- Komodo-Update-Historie bestaetigt: ein fehlgeschlagener `DeployStack` fuer `nextcloud` mit Compose-Up-Konflikt, danach ein erfolgreicher `DeployStack`.
|
||||||
|
- Aktueller Runtime-Stand nach Pruefung: `nextcloud`, `nextcloud-postgres`, `nextcloud-redis`, `postgresql17`, `mealie-postgres`, `gitea`, `bentopdf`, `ddns-updater` und Komodo-Self-Stack laufen ohne `unhealthy`-Status; die erwarteten Images stimmen mit den Compose-Dateien ueberein.
|
||||||
|
- `services/posture-check/export-prometheus-textfile.sh` exportiert jetzt `homelab_gitops_runtime_image_match{name,project,service}` fuer laufende Compose-Container. Die Metrik vergleicht das Image aus `docker compose config --format json` gegen `docker inspect .Config.Image` des laufenden Containers und faengt damit genau den Zustand "Workspace/Compose neu, Runtime alt" ab.
|
||||||
|
- Neue Prometheus-Regel `HomelabGitOpsRuntimeImageDrift`: feuert als Warning, wenn ein laufender Compose-Container laenger als 10 Minuten nicht dem Compose-Image entspricht.
|
||||||
|
- Smoke: Exporter-Test in `/tmp/kallilab-textfile-test/homelab.prom` lieferte fuer alle erkannten Compose-Container `homelab_gitops_runtime_image_match = 1`; `promtool check rules` meldete `SUCCESS: 17 rules found`.
|
||||||
|
|
||||||
### 2026-05-31 - Renovate PRs #1 bis #5 gemerged und deployed
|
### 2026-05-31 - Renovate PRs #1 bis #5 gemerged und deployed
|
||||||
|
|
||||||
Die ersten fuenf Renovate-PRs wurden einzeln in `master` uebernommen, mit Policy-Check und Live-Smoke nach den Datenhalter-Aenderungen. Major-Branches wurden bewusst nicht gemerged.
|
Die ersten fuenf Renovate-PRs wurden einzeln in `master` uebernommen, mit Policy-Check und Live-Smoke nach den Datenhalter-Aenderungen. Major-Branches wurden bewusst nicht gemerged.
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
|||||||
| `ops/glance/config/glance.yml` | Glance Dashboard-Konfiguration fuer Homelab-Monitore, Internet-/DNS-/VPN-Widgets, Community-Widgets, Docker-Containergruppen, Zeitfortschritt, Host-Snapshot, Bookmarks und zweite Infrastruktur-Seite |
|
| `ops/glance/config/glance.yml` | Glance Dashboard-Konfiguration fuer Homelab-Monitore, Internet-/DNS-/VPN-Widgets, Community-Widgets, Docker-Containergruppen, Zeitfortschritt, Host-Snapshot, Bookmarks und zweite Infrastruktur-Seite |
|
||||||
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Host-seitiges Dump-Skript fuer PostgreSQL, SQLite-Container-Dumps und Komodo Mongo |
|
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Host-seitiges Dump-Skript fuer PostgreSQL, SQLite-Container-Dumps und Komodo Mongo |
|
||||||
| `services/posture-check/posture-check.sh` | Host-seitiger Posture-Check fuer Filesystem, Mover-Drift, NVMe-SMART, Fuellstand, Authelia-Repo<->Host-Drift und ntfy-Alarmierung |
|
| `services/posture-check/posture-check.sh` | Host-seitiger Posture-Check fuer Filesystem, Mover-Drift, NVMe-SMART, Fuellstand, Authelia-Repo<->Host-Drift und ntfy-Alarmierung |
|
||||||
|
| `services/posture-check/export-prometheus-textfile.sh` | Host-seitiger Textfile-Exporter fuer Borg-, Critical-Container- und GitOps-Runtime-Image-Drift-Metriken |
|
||||||
| `services/posture-check/docker-critical-events.sh` | Host-seitiger Docker-Event-Watcher fuer kritische ntfy-Alarme |
|
| `services/posture-check/docker-critical-events.sh` | Host-seitiger Docker-Event-Watcher fuer kritische ntfy-Alarme |
|
||||||
| `services/posture-check/posture_check.sh` | Kompatibilitaets-Wrapper fuer die historische Schreibweise aus `STORAGE_LAYOUT.draft.md` |
|
| `services/posture-check/posture_check.sh` | Kompatibilitaets-Wrapper fuer die historische Schreibweise aus `STORAGE_LAYOUT.draft.md` |
|
||||||
| `services/authelia-diff.sh` | Vergleicht `access_control:`-Sektion zwischen Repo-Baseline und Host-Datei; wird vom Posture-Check als Check `authelia_config_drift` aufgerufen |
|
| `services/authelia-diff.sh` | Vergleicht `access_control:`-Sektion zwischen Repo-Baseline und Host-Datei; wird vom Posture-Check als Check `authelia_config_drift` aufgerufen |
|
||||||
@@ -237,6 +238,7 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Unraid Host, nicht Borg-UI Inline-Hook | erzeugt aktuelle Dumps unter `/mnt/user/backups/borg/dumps/latest` |
|
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Unraid Host, nicht Borg-UI Inline-Hook | erzeugt aktuelle Dumps unter `/mnt/user/backups/borg/dumps/latest` |
|
||||||
| `services/posture-check/posture-check.sh` | Unraid Host | schreibt `/mnt/user/services/posture-check/last.json` und alarmiert via ntfy bei Warning/Critical |
|
| `services/posture-check/posture-check.sh` | Unraid Host | schreibt `/mnt/user/services/posture-check/last.json` und alarmiert via ntfy bei Warning/Critical |
|
||||||
|
| `services/posture-check/export-prometheus-textfile.sh` | Unraid Host, Cron/Textfile-Collector | schreibt Borg-, Critical-Container- und GitOps-Runtime-Image-Drift-Metriken fuer Prometheus |
|
||||||
| `services/posture-check/docker-critical-events.sh` | Unraid Host | beobachtet Docker `die`/`oom`/`kill` Events und alarmiert via `homelab-alerts` |
|
| `services/posture-check/docker-critical-events.sh` | Unraid Host | beobachtet Docker `die`/`oom`/`kill` Events und alarmiert via `homelab-alerts` |
|
||||||
|
|
||||||
Das Skript liest Secret-Dateien auf dem Host und schreibt Dump-Artefakte. Bei Analyse niemals Secret-Inhalte ausgeben.
|
Das Skript liest Secret-Dateien auf dem Host und schreibt Dump-Artefakte. Bei Analyse niemals Secret-Inhalte ausgeben.
|
||||||
|
|||||||
@@ -140,6 +140,15 @@ groups:
|
|||||||
summary: "Critical container is down: {{ $labels.name }}"
|
summary: "Critical container is down: {{ $labels.name }}"
|
||||||
description: "The host textfile exporter reports that critical container {{ $labels.name }} is not running."
|
description: "The host textfile exporter reports that critical container {{ $labels.name }} is not running."
|
||||||
|
|
||||||
|
- alert: HomelabGitOpsRuntimeImageDrift
|
||||||
|
expr: homelab_gitops_runtime_image_match == 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
summary: "Runtime image drift: {{ $labels.name }}"
|
||||||
|
description: "Container {{ $labels.name }} is not running the image declared by its Compose config in project {{ $labels.project }}."
|
||||||
|
|
||||||
- name: homelab-meta
|
- name: homelab-meta
|
||||||
rules:
|
rules:
|
||||||
- alert: HomelabPrometheusTargetDown
|
- alert: HomelabPrometheusTargetDown
|
||||||
|
|||||||
@@ -15,6 +15,51 @@ trap cleanup EXIT
|
|||||||
|
|
||||||
now="$(date +%s)"
|
now="$(date +%s)"
|
||||||
|
|
||||||
|
emit_gitops_runtime_image_metrics() {
|
||||||
|
cat <<'EOF'
|
||||||
|
# HELP homelab_gitops_runtime_image_match Whether a running Compose container uses the image currently declared by its Compose config.
|
||||||
|
# TYPE homelab_gitops_runtime_image_match gauge
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if ! command -v jq >/dev/null 2>&1; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker ps \
|
||||||
|
--filter label=com.docker.compose.project \
|
||||||
|
--format '{{.Names}}\t{{.Label "com.docker.compose.project"}}\t{{.Label "com.docker.compose.service"}}\t{{.Label "com.docker.compose.project.config_files"}}\t{{.Label "com.docker.compose.project.environment_file"}}' |
|
||||||
|
while IFS="$(printf '\t')" read -r container project service config_files env_file; do
|
||||||
|
[ -n "$container" ] || continue
|
||||||
|
[ -n "$service" ] || continue
|
||||||
|
[ -n "$config_files" ] || continue
|
||||||
|
|
||||||
|
config_file="${config_files%%,*}"
|
||||||
|
[ -f "$config_file" ] || continue
|
||||||
|
|
||||||
|
compose_args=(-f "$config_file")
|
||||||
|
if [ -n "$env_file" ] && [ -f "$env_file" ]; then
|
||||||
|
compose_args+=(--env-file "$env_file")
|
||||||
|
fi
|
||||||
|
|
||||||
|
expected="$(
|
||||||
|
docker compose "${compose_args[@]}" config --format json 2>/dev/null |
|
||||||
|
jq -r --arg service "$service" '.services[$service].image // empty' 2>/dev/null || true
|
||||||
|
)"
|
||||||
|
[ -n "$expected" ] || continue
|
||||||
|
|
||||||
|
running="$(docker inspect -f '{{.Config.Image}}' "$container" 2>/dev/null || true)"
|
||||||
|
[ -n "$running" ] || continue
|
||||||
|
|
||||||
|
match="0"
|
||||||
|
if [ "$running" = "$expected" ]; then
|
||||||
|
match="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'homelab_gitops_runtime_image_match{name="%s",project="%s",service="%s"} %s\n' \
|
||||||
|
"$container" "$project" "$service" "$match"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
# HELP homelab_textfile_exporter_last_run_timestamp_seconds Unix timestamp of the last successful homelab textfile exporter run.
|
# HELP homelab_textfile_exporter_last_run_timestamp_seconds Unix timestamp of the last successful homelab textfile exporter run.
|
||||||
@@ -34,6 +79,8 @@ EOF
|
|||||||
printf 'homelab_critical_container_running{name="%s"} %s\n' "$container" "$running"
|
printf 'homelab_critical_container_running{name="%s"} %s\n' "$container" "$running"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
emit_gitops_runtime_image_metrics
|
||||||
|
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
# HELP homelab_borg_last_completed_timestamp_seconds Unix timestamp of the most recent completed Borg backup job known to Borg UI.
|
# HELP homelab_borg_last_completed_timestamp_seconds Unix timestamp of the most recent completed Borg backup job known to Borg UI.
|
||||||
# TYPE homelab_borg_last_completed_timestamp_seconds gauge
|
# TYPE homelab_borg_last_completed_timestamp_seconds gauge
|
||||||
|
|||||||
Reference in New Issue
Block a user