From 5f50a6007144ec03ba75fc1e52f2c55a5f3aebc6 Mon Sep 17 00:00:00 2001 From: Scrublord MacBad Date: Thu, 14 May 2026 21:43:01 +0200 Subject: [PATCH] feat: Automate ConfigMap checksum updates via Git pre-commit hook - Add pre-commit hook (scripts/hooks/pre-commit) that automatically calculates MD5 checksums of ConfigMaps (element-values.yaml, synapse-values.yaml) - Update annotations in kustomization.yaml to trigger Flux CD HelmRelease syncs - Add install script (scripts/install-hooks.sh) for easy hook setup - Add comprehensive documentation (docs/ops-configmap-sync.md) explaining: * Why Flux doesn't auto-detect ConfigMap changes * How the checksum-based workaround works * How to install and use the hook * Troubleshooting and manual sync procedures - Update README.md with post-clone hook installation step This solves the issue where Flux CD doesn't automatically re-deploy when external ConfigMaps are modified. Users no longer need manual checksum updates. Co-Authored-By: Claude Haiku 4.5 --- README.md | 6 + docs/ops-configmap-sync.md | 296 +++++++++++++++++++++++++++++++++++++ scripts/hooks/pre-commit | 41 +++++ scripts/install-hooks.sh | 27 ++++ 4 files changed, 370 insertions(+) create mode 100644 docs/ops-configmap-sync.md create mode 100755 scripts/hooks/pre-commit create mode 100755 scripts/install-hooks.sh diff --git a/README.md b/README.md index 99236a9..abc1d1b 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,12 @@ winget install Kubernetes.kubectl FluxCD.Flux Mozilla.sops age-encryption.age He 1. **Kubeconfig:** Stelle sicher, dass die Datei `~/.kube/config` mit den Zugangsdaten zu deinem K3s-Cluster gefüllt ist. Test: `kubectl get nodes`. 2. **SOPS Key:** Du benötigst den privaten `age`-Key (oder GPG-Key), der in der `.sops.yaml` des Repositories hinterlegt ist, um Secrets bearbeiten zu können. +3. **Git Hooks installieren:** Nach dem Klonen dieses Repositories müssen Git Hooks installiert werden, um ConfigMap-Änderungen automatisch zu tracken: + ```bash + cd prod/gitops + ./scripts/install-hooks.sh + ``` + Siehe [📖 GitOps ConfigMap Auto-Sync](docs/ops-configmap-sync.md) für Details. ----- diff --git a/docs/ops-configmap-sync.md b/docs/ops-configmap-sync.md new file mode 100644 index 0000000..4998eea --- /dev/null +++ b/docs/ops-configmap-sync.md @@ -0,0 +1,296 @@ +# 🔄 GitOps ConfigMap Auto-Sync via Checksums + +Dieses Dokument erklärt ein Kernproblem mit **Flux CD** und **externe Konfigurationen** – und wie wir es gelöst haben. + +--- + +## 📋 Das Problem: Flux erkennt ConfigMap-Änderungen nicht + +### Die Situation + +Unsere HelmRelease (`element-server-suite.yaml`) nutzt `valuesFrom`, um Konfigurationen aus externen **ConfigMaps** zu laden: + +```yaml +spec: + valuesFrom: + - kind: ConfigMap + name: ess-element-custom # ← Diese ConfigMap + valuesKey: values.yaml + - kind: ConfigMap + name: ess-synapse-custom # ← Diese ConfigMap + valuesKey: values.yaml +``` + +Diese ConfigMaps entstehen aus Dateien im Git-Repo (`apps/production/custom-configs/*.yaml`) und werden von Kustomize in den Cluster deployed. + +### Das Kernproblem + +**Flux CD reagiert NICHT automatisch, wenn sich eine ConfigMap ändert.** + +Warum? Flux überwacht nur das Git-Repository auf Änderungen. Wenn du `element-values.yaml` änderst: + +1. ✅ Flux sieht die Änderung im Git-Repo +2. ✅ Kustomize erzeugt eine neue ConfigMap mit den neuen Werten +3. ❌ Aber Helm (der Helm-Controller in Flux) erkennt **nicht**, dass sich die externe ConfigMap geändert hat +4. ❌ Helm deployt das Chart nicht neu → Die alten Themes/Configs bleiben aktiv + +Das ist kein Bug, sondern by-design: Helm achtet nur auf: +- Chart-Version (z.B. `26.4.0`) +- Änderungen in den direkten `values:` Blöcken +- Nicht auf externe Quellen wie ConfigMaps + +--- + +## 🔑 Die Lösung: Checksums als Trigger + +Wir nutzen **Annotations mit Checksums** als Workaround: + +```yaml +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + annotations: + element-config-checksum: "401f8a87d0ef5d91d2e5032d4aede42c" # ← Hash der element-values.yaml + synapse-config-checksum: "e98fe81141f52e7ea833596ca39853b9" # ← Hash der synapse-values.yaml +``` + +Wenn sich der Annotation-Wert ändert, sieht Flux, dass die **HelmRelease selbst** sich geändert hat – und deployt neu. + +### Automatisierung via Git Pre-Commit Hook + +Das Problem: Wer aktualisiert die Checksums, wenn man `element-values.yaml` editiert? + +**Lösung:** Ein Git **pre-commit Hook** tut das automatisch: + +```bash +$ vi apps/production/custom-configs/element-values.yaml +# (Farbe ändern, Theme hinzufügen, …) + +$ git add apps/production/custom-configs/element-values.yaml +$ git commit -m "feat: new theme" +# ← Der Hook läuft jetzt: +# 1. Berechnet MD5-Hash der neuen element-values.yaml +# 2. Aktualisiert die Annotation in kustomization.yaml +# 3. Added kustomization.yaml zum Commit automatisch +``` + +Der User muss **nichts Zusätzliches tun** – alles läuft automatisch. + +--- + +## 🚀 Installation + +Nach dem Repository **klonen**, führe dieses Skript aus: + +```bash +cd prod/gitops +./scripts/install-hooks.sh +``` + +Das Skript: +- ✅ Erstellt einen Symlink `.git/hooks/pre-commit` → `scripts/hooks/pre-commit` +- ✅ Macht die Hook-Datei ausführbar +- ✅ Gibt dir eine Bestätigungsmeldung + +**Einmalig pro lokales Repository.** Neue Klone müssen den Hook auch installieren. + +--- + +## 📝 Workflow: ConfigMaps ändern + +So sieht die Praxis aus: + +### 1️⃣ Änderung machen + +```bash +vi apps/production/custom-configs/element-values.yaml +# Edit: Themes, Farben, Logging-Level, etc. +``` + +### 2️⃣ Committen (Hook läuft automatisch) + +```bash +git add apps/production/custom-configs/element-values.yaml +git commit -m "feat: add Dark Purple theme variant" + +# Pre-Commit Hook läuft automatisch: +# → Berechnet neuen Hash +# → Updated kustomization.yaml +# → Added kustomization.yaml zum Commit +``` + +### 3️⃣ Überprüfung (optional) + +```bash +# Schaue, was committet wird: +git show --stat + +# Output sollte zeigen: +# element-values.yaml (modified) +# kustomization.yaml (modified) ← vom Hook hinzugefügt +``` + +### 4️⃣ Pushen & Deployen + +```bash +git push +# ← Flux sieht die Änderung an kustomization.yaml +# ← HelmRelease wird neu-synced mit den neuen Checksums +# ← Die neue Config ist in ~5 Minuten aktiv +``` + +--- + +## 🔧 Technische Details + +### Welche Dateien sind "überwacht"? + +Der Hook beobachtet: + +| Datei | Annotation | Ziel | +|-------|-----------|------| +| `apps/production/custom-configs/element-values.yaml` | `element-config-checksum` | Element Web Themes, Branding | +| `apps/production/custom-configs/synapse-values.yaml` | `synapse-config-checksum` | Synapse Logging, Federation | + +### Hook-Implementation + +Der Hook (`scripts/hooks/pre-commit`) macht folgendes: + +1. Prüft, ob eine der überwachten Dateien geändert wurde (`git diff --cached`) +2. Berechnet den MD5-Hash der Datei (kompatibel mit macOS/Linux) +3. Ersetzt den Hash-Wert in `apps/production/kustomization.yaml` via `sed` +4. Added `kustomization.yaml` automatisch zum Commit mit `git add` + +```bash +# Beispiel: element-values.yaml ändert sich von +value: "401f8a87d0ef5d91d2e5032d4aede42c" # element-config +# zu +value: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" # element-config +``` + +--- + +## ⚠️ Häufige Fragen + +### F: Was passiert, wenn der Hook fehlschlägt? + +A: Der Commit wird **abgebrochen**. Du siehst eine Fehlermeldung. Typische Gründe: +- `md5` oder `md5sum` nicht installiert (sehr unwahrscheinlich) +- `sed` Syntax-Fehler (sehr selten) + +Lass dich nicht entmutigen – rufe denen auf, die das Setup machen 🚀 + +### F: Kann ich den Hook deaktivieren? + +A: Ja, aber bitte nicht! Wenn du temporär ohne Hook arbeiten möchtest: + +```bash +git commit --no-verify +``` + +Das umgeht den Hook einmalig. Danach musst du die Checksums manuell aktualisieren. + +### F: Der Hook touched `kustomization.yaml`, obwohl ich sie nicht editiert habe? + +A: Das ist **Absicht**. Der Hook updated **nur** die Checksums, nicht den Rest der Datei. Das ist sauber und Git-freundlich. + +### F: Was wenn ich mehrere ConfigMaps gleichzeitig ändere? + +A: Der Hook aktualisiert **alle** deren Checksums in einem Pass. Keine Probleme. + +--- + +## 🧪 Verifikation: Hook funktioniert? + +Teste es selbst: + +```bash +# 1. Hook installieren +./scripts/install-hooks.sh + +# 2. Eine Teständerung machen +echo "# Test" >> apps/production/custom-configs/element-values.yaml + +# 3. Committen +git add apps/production/custom-configs/element-values.yaml +git commit -m "test: verify hook" + +# 4. Überprüfung: Wurde kustomization.yaml auto-updated? +git diff HEAD~1 apps/production/kustomization.yaml | grep -i checksum + +# Output sollte zeigen, dass ein Checksum sich geändert hat +``` + +Wenn ja → Hook funktioniert! ✅ +Wenn nein → Rufe uns an 📞 + +--- + +## 📚 Zusammenhang mit Flux CD + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Git Repository (axion1337.chat-gitops) │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ apps/production/custom-configs/ │ +│ ├── element-values.yaml (du änderst das) │ +│ ├── synapse-values.yaml │ +│ └── mas-secret.yaml │ +│ │ +│ apps/production/ │ +│ └── kustomization.yaml (Hook updated die Checksums hier) │ +│ │ +│ apps/production/ │ +│ └── element-server-suite.yaml (HelmRelease mit Annotations)│ +│ │ +└─────────────────────────────────────────────────────────────┘ + ↓ git push +┌─────────────────────────────────────────────────────────────┐ +│ FluxCD im Kubernetes-Cluster │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ 1. GitRepository Source │ +│ └─ Fetcht dein Repo alle 10 Minuten │ +│ │ +│ 2. Kustomization production-apps │ +│ └─ Applyt die Kustomize-Overlays │ +│ └─ Erzeugt ConfigMaps mit neuen Werten │ +│ │ +│ 3. HelmRelease matrix-stack │ +│ └─ Sieht neue Annotations (Checksums) │ +│ └─ Deployt Helm-Chart mit neuen Werten │ +│ │ +│ 4. Element Web Pods │ +│ └─ Restarten automatisch │ +│ └─ Laden neue Config aus der ConfigMap │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## 🚨 Notfall: Manuelle Checksum-Aktualisierung + +Falls der Hook ausfällt (z.B. weil Git Hooks in CI deaktiviert sind), kannst du Checksums manuell aktualisieren: + +```bash +# 1. Neuen Hash berechnen +md5sum apps/production/custom-configs/element-values.yaml +# Output: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 apps/production/custom-configs/element-values.yaml + +# 2. Annotation in kustomization.yaml updaten +vi apps/production/kustomization.yaml +# Ändere: value: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" # element-config + +# 3. Committen +git add apps/production/kustomization.yaml +git commit -m "fix: manual checksum update" +git push +``` + +--- + +**Version:** 1.0 +**Letztes Update:** 2026-05-14 +**Kompatibilität:** FluxCD 2.x, Kustomize 5.x+ diff --git a/scripts/hooks/pre-commit b/scripts/hooks/pre-commit new file mode 100755 index 0000000..a12bd2f --- /dev/null +++ b/scripts/hooks/pre-commit @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# GitOps ConfigMap Checksum Hook +# Automatically updates checksum annotations in kustomization.yaml when ConfigMaps change. +# This ensures Flux CD re-deploys the HelmRelease when external ConfigMap sources are modified. +# +# See: docs/ops-configmap-sync.md + +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel)" +ELEMENT_VALUES="$REPO_ROOT/apps/production/custom-configs/element-values.yaml" +SYNAPSE_VALUES="$REPO_ROOT/apps/production/custom-configs/synapse-values.yaml" +KUSTOMIZATION="$REPO_ROOT/apps/production/kustomization.yaml" + +# Function to calculate MD5 hash (handles both GNU md5sum and BSD md5) +get_md5() { + local file="$1" + if command -v md5sum &> /dev/null; then + md5sum "$file" | awk '{print $1}' + elif command -v md5 &> /dev/null; then + md5 -q "$file" + else + echo "ERROR: Neither md5sum nor md5 found" >&2 + exit 1 + fi +} + +# Update checksums for ConfigMaps that exist and are staged +if git diff --cached --name-only | grep -q "element-values.yaml"; then + ELEMENT_HASH=$(get_md5 "$ELEMENT_VALUES") + sed -i.bak "s/value: \"[0-9a-f]\{32\}\" *# element-config/value: \"$ELEMENT_HASH\" # element-config/" "$KUSTOMIZATION" + rm -f "$KUSTOMIZATION.bak" + git add "$KUSTOMIZATION" +fi + +if git diff --cached --name-only | grep -q "synapse-values.yaml"; then + SYNAPSE_HASH=$(get_md5 "$SYNAPSE_VALUES") + sed -i.bak "s/value: \"[0-9a-f]\{32\}\" *# synapse-config/value: \"$SYNAPSE_HASH\" # synapse-config/" "$KUSTOMIZATION" + rm -f "$KUSTOMIZATION.bak" + git add "$KUSTOMIZATION" +fi diff --git a/scripts/install-hooks.sh b/scripts/install-hooks.sh new file mode 100755 index 0000000..d70051f --- /dev/null +++ b/scripts/install-hooks.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Install Git Hooks for GitOps automation +# Must be run after cloning the repository + +REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || { + echo "❌ Not in a git repository" + exit 1 +} + +HOOKS_DIR="$REPO_ROOT/.git/hooks" +HOOK_SOURCE="$REPO_ROOT/scripts/hooks/pre-commit" +HOOK_DEST="$HOOKS_DIR/pre-commit" + +# Verify source exists +if [ ! -f "$HOOK_SOURCE" ]; then + echo "❌ Hook source not found: $HOOK_SOURCE" + exit 1 +fi + +# Create symlink (force if exists) +mkdir -p "$HOOKS_DIR" +ln -sf "../../scripts/hooks/pre-commit" "$HOOK_DEST" +chmod +x "$HOOK_SOURCE" + +echo "✅ Git hooks installed:" +echo " • pre-commit: ConfigMap checksum auto-update" +echo " See: docs/ops-configmap-sync.md"