(Stand: 13. April 2025)
Die Bereitstellung von Anwendungen in Edge-Umgebungen stellt besondere Herausforderungen dar, insbesondere hinsichtlich Konnektivität, Bandbreite und der konsistenten Verteilung von Container-Images. In diesem Beitrag beschreibe ich einen End-to-End-Workflow, der GitOps (mit Rancher Fleet), eine automatisierte CI/CD-Pipeline (mit GitLab CI) und eine Lösung für die Image-Verteilung am Edge mittels einer lokalen Registry und eines automatisierten Synchronisations-Jobs kombiniert.
Workflow-Beschreibung Schritt für Schritt
-
Entwickler-Änderung: Ein Entwickler führt eine Code-Änderung an einer der Anwendungen (z.B. der Spring Boot App) durch und pusht diese in das dedizierte Anwendungs-Source-Code-Repository auf GitLab.
-
GitLab CI Pipeline (im App-Source-Repo):
- Der Push löst die Pipeline aus.
- Build & Push: Das Docker-Image der Anwendung wird gebaut und mit einem eindeutigen Tag (z.B. Commit SHA) versehen. Anschließend wird es in die zentrale GitLab Container Registry gepusht.
- Digest holen: Die Pipeline ermittelt den unveränderlichen SHA256-Digest des gepushten Images (z.B. via
skopeo inspect
). - GitOps Repo Update:
- Die Pipeline klont das zentrale GitOps-Repository (
fleet-config
) mittels sicherer Authentifizierung (z.B. SSH Deploy Key). - Sie aktualisiert die Helm-
values.yaml
der Anwendung (z.B.fleet-config/spring-app/values.yaml
) und setztimage.repository
auf den vollen Namen mit Digest (registry.gitlab.com/.../spring-app@sha256:...
) undimage.tag
auf""
. - Sie aktualisiert das
EdgeImageSet
-Manifest (fleet-config/edge-image-set.yaml
) und fügt den neuen Image-Digest für diese Anwendung hinzu oder aktualisiert den bestehenden Eintrag. - Die Pipeline committet und pusht diese Änderungen zurück in das GitOps-Repository.
- Die Pipeline klont das zentrale GitOps-Repository (
-
Fleet Controller (im K3s Cluster):
- Fleet überwacht das GitOps-Repository (
fleet-config
), wie in derGitRepo
-Ressource (prototype-apps
) definiert. - Fleet erkennt den neuen Commit von der CI-Pipeline.
- Fleet analysiert die in
spec.paths
definierten Verzeichnisse und Dateien (Helm Charts, rohe YAMLs). - Fleet erstellt/aktualisiert die zugehörigen Bundles und wendet die darin enthaltenen Kubernetes-Ressourcen im Cluster über den **K8s API Server** an. Dies beinhaltet das Update des Anwendungs-Deployments (mit neuem Digest), der
EdgeImageSet
-Ressource, sowie das Deployment der Edge Registry und des Image Sync CronJobs (falls geändert).
- Fleet überwacht das GitOps-Repository (
-
Image Sync CronJob (im K3s Cluster):
- Dieser CronJob wurde ebenfalls via Fleet deployed und läuft periodisch (z.B. alle 15 Min.).
- Der CronJob-Pod startet und führt das Sync-Skript aus.
- Das Skript liest die
EdgeImageSet
-Ressource (z.B.default-images
im Namespacefleet-local
) über den **K8s API Server**. - Das Skript gleicht die Liste der gewünschten Images (
spec.images
) mit dem Inhalt der lokalen Edge Registry ab (optional, oder kopiert einfach). - Für jedes (potenziell fehlende) Image führt das Skript im Pod
skopeo copy
aus. Dieser Befehl kopiert das Image (anhand des Digests) von der zentralen GitLab Registry in die lokale Edge Registry (über deren Service-Adresse).
-
K3s Node / Kubelet (auf der Edge VM):
- Das Kubelet erhält die (aktualisierte) Spezifikation des Anwendungs-Deployments vom **K8s API Server**.
- Es versucht, das Image zu pullen (z.B.
registry.gitlab.com/.../spring-app@sha256:...
). - Es konsultiert die Konfigurationsdatei
/etc/rancher/k3s/registries.yaml
. - Diese Datei leitet die Anfrage für
registry.gitlab.com
zur internen Edge Registry um. - Kubelet kann das Image erfolgreich von der Edge Registry ziehen (da der CronJob es bereits dorthin synchronisiert hat).
- Kubelet startet den neuen Anwendungs-Pod mit dem aktualisierten Image.
Visuelles Diagramm (ASCII – Erste Version)
+------------------+ +------------------+ +------------------+
| Developer | | GitLab CI | | K3s Cluster |
+------------------+ +------------------+ +------------------+
| | |
| 1. Push code | |
| change | |
v | |
+------------------+ | |
| App Source Repo |------------------------->| |
| (spring-app) | 2. Trigger pipeline | |
+------------------+ | |
| |
| 3. Build Docker image |
| |
v |
+------------------+ |
| Central Registry | |
| (GitLab) | |
+------------------+ |
| |
| 4. Push image |
| with digest |
| |
| 5. Get image digest |
| |
v |
+------------------+ |
| Clone GitOps | |
| Repository | |
+------------------+ |
| |
| 6. Update values.yaml |
| and edge-image-set.yaml |
| |
v |
+------------------+ |
| GitOps Repo |<--------------------------|
| (fleet-config) | 7. Fleet watches repo |
+------------------+ |
|
| 8. Apply changes
| (Helm/kubectl)
v
+------------------+
| K8s Resources |
| - Deployments |
| - EdgeImageSet |
+------------------+
|
| 9. Trigger
|
v
+------------------+
| Image Sync |
| CronJob |
+------------------+
|
| 10. Read ImageSet
| & copy images
|
+-------------------------------------------+ |
| | |
v v |
+------------------+ +------------------+ |
| Central Registry | | Edge Registry |<+
| (GitLab) |----------------------->| (in-cluster) |
+------------------+ 11. skopeo copy +------------------+
|
| 12. K3s nodes pull
| images from edge registry
v
+------------------+
| Application Pods |
| (spring-app) |
+------------------+