GitLab Runner in Azure betreiben: Container Apps, App Service oder VM?
Dieser Beitrag zeigt dir, wie GitLab Runner sicher und produktionsfähig in Azure betrieben werden können und vergleicht dafür die Hosting-Optionen Azure Container Apps, App Service und virtuelle Maschinen.

Warum Shared Runner oft nicht reichen
Sobald Pipelines gegen private Azure-Ressourcen laufen sollen wie zum Beispiel Key Vaults mit Private Endpoint, interner Azure Kubernetes Service oder Azure Container Registry ohne Public Access werden Shared Runner schnell zum Engpass.
In diesem Blog-Beitrag möchte ich die Möglichkeiten darlegen wie Gitlab Runner in Azure gehostet werden können. Dieses Thema kam bereits mehrfach in unseren Projekteinsätzen auf, da die Funktionsumfänge von GitLab zum häufigen Einsatz der jeweiligen GitLab-Funktionen führt. Aus diesem Grund soll dabei dargelegt werden welche Optionen und wo die jeweiligen Vor- und Nachteile liegen.
Um die volle Kontrolle über Netzwerkpfade, die Laufzeitumgebung und Identitäten zu bekommen ist ein Self-Hosted Runner die ideale Lösung diese Anforderungen zu erfüllen.
Self-Hosted Runner in Azure lösen dabei genau diese drei Punkte:
- Runner laufen im eigenen Tenant und in der eigenen Subscription.
- Netzwerkzugriff folgt der eigenen Landing-Zone-Architektur.
- Azure-Zugriffe laufen über Managed Identity statt statischer Secrets.
Die entscheidende Frage ist nicht ob self-hosted, sondern welches Hosting-Modell operativ und sicherheitstechnisch zu euren Workloads passt.
Entscheidungslogik statt Feature-Liste
Um die Entscheidungsfindung zu vereinfachen, nutze ich bei Projekteinsätzen die folgenden Fragestellungen:
1. Frage: Ist eine Isolation pro Job erforderlich?
-> Wenn ja: Container-orientierte Lösungen bevorzugen, um ja nach Bedarf die Anzahl der Runner skalieren zu können.
2. Frage: Brauchen Builds privilegierte Docker-Operationen oder hohe I/O?
-> Wenn ja: VM-basierte GitLab-Runner nutzen, um beispielsweise App-Builds, Container-Images etc. zu erstellen.
3. Frage: Wie stark schwankt die Last über den Tag hinweg?
-> Bei starker Volatilität: Verwendung von Auto-Scaling Rules für VMs oder Container Apps. Die Skalierung von App Service ist leider nicht intuitiv in Azure möglich.
4. Frage: Wer betreibt und wartet die GitLab-Runner dauerhaft?
-> Kleines Platform-Team: Managed Runtime wie Azure Container Apps oder App Services bevorzugen. Die Verwendung von gehärteten Container-Images und die Wartung dieser Images ist besser verwaltbare als die Wartung von virtuellen Maschinen.
Im Allgemeinen landet man damit meist bei drei validen Optionen in Azure Container Apps, App Service, VM/VMSS. Das Hosting von GitLab Runnern habe ich bewusst ausgelassen, da ich für die Verwendung von Container-Workloads die Azure-Managed Lösungen klar bevorzuge.
Option A: Azure Container Apps (Standardempfehlung)
Die Verwendung von Azure Container Apps ist in vielen Enterprise-Setups der beste Ausgangspunkt. Dabei existiert wenig Betriebsaufwand, die Option für VNet-Integration und eine klare Skalierungsmechanik, um bei steigenden Anforderungen in kürzester Zeit die Instanzen zu skalieren.
Wann es gut passt:
- Standardisierte Container-Builds und Testjobs
- Wechselnde Last zum Beispiel tagsüber hohe CI-Last und nachts wenig Nutzung
- Plattformteams, die Betrieb vereinfachen wollen
Technische Kernpunkte:
- Zugriff auf Azure-Ressourcen über User- oder System-Assigned Managed Identity
- Secrets wie Runner-Token oder Registry-Creds aus Key Vault statt im Klartext referenzieren
- Erstellung von custom Images, um die Standard Gitlab-Runner Images zusätzlich abzusichern.
Produktionsimplikationen
- Netzwerk: eigenes Subnet für Container Apps nutzen und ggf. UDR/Firewall-Regeln früh sauber definieren.
- Security: privilegierte Container strikt begrenzen, sodass wenn Docker-in-Docker notwendig ist, der Scope eingeschränkt wird.
- Beobachtbarkeit: Log Analytics + Metriken nutzen, um Queue-Zeiten, Job-Fehlerraten oder Startlatenzen messen zu können.
- Lifecycle: Runner-Image versionieren, nicht blind
latestverwenden.
Terraform-Beispiel (verkürzt)
resource "azurerm_container_app" "runner" {
name = "ca-gitlab-runner-${var.env}"
resource_group_name = var.rg_name
container_app_environment_id = var.cae_id
revision_mode = "Single"
identity {
type = "UserAssigned"
identity_ids = [var.runner_uami_id]
}
secret {
name = "runner-auth-token"
value = var.runner_auth_token
}
template {
min_replicas = 1
max_replicas = 10
container {
name = "runner"
image = var.runner_image
cpu = 1.0
memory = "2Gi"
env {
name = "CI_SERVER_URL"
value = var.gitlab_url
}
env {
name = "RUNNER_TOKEN"
secret_name = "runner-auth-token"
}
}
}
}Option B: Azure App Service (nur für klar begrenzte Szenarien)
Die Verwendung von App Services wirkt zunächst attraktiv, ist für Runner aber oft ein Kompromiss. Für einfache, immer laufende Workloads kann es funktionieren, jedoch ist es für heterogene CI/CD-Lasten meist zu starr. Das skaliert grundsätzlich an der fehlenden Unterstützung zur variablen Skalierung von Containern. Im Grunde existiert immer nur eine Instanz des Runners.
Wann es gut passt:
- Kleine Teams mit konstant niedriger Last
- Wenig Bedarf an tiefer Laufzeitkontrolle
- Fokus auf „schnell stabil online“ statt maximaler Flexibilität
Typische Grenzen in der Praxis:
- Kein sinnvoller Scale-to-zero-Pfad für Runner-Szenarien
- Docker-spezifische Spezialfälle (privilegiert Tasks oder nested Workloads) sind unhandlich
- Weniger Freiheitsgrade bei Betrieb und Debugging als auf Virtual Machine oder Virtual Machine Scale Set
Wenn App Services bereits primär als Compute-Standard sind, kann es als Übergang dienen. Als strategische Zielplattform für Runner sehe ich es selten, da sie zu unflexibel sind.
Option C: Azure VM / VM Scale Set (für schwere oder spezielle Workloads)
VMs sind die richtige Wahl, wenn Pipelines bewusst „nah am Betriebssystem“ arbeiten müssen. Dazu gehören große Docker-Builds, spezielle Kernel- oder Tooling-Anforderungen, hohe Disk-I/O oder komplexe Caching-Strategien.
Wann es gut passt:
- Build-Jobs mit hoher CPU/RAM/IO-Last
- Shell-Executor oder stark angepasstes Runner-Setup
- Bedarf an tiefer Diagnose auf Host-Ebene
Wie oft die Betriebsrealität aussieht:
- Patch- und Vulnerability-Management liegt bei euch für die ganze virtuelle Maschine.
- Autoskalierung über VM Scale Set braucht saubere Regeln und Health-Modell.
- Ohne konsequentes Hardening steigt die Angriffsfläche schnell.
Minimales Hardening-Set sollte folgendes beinhalten:
- SSH nur über Bastion/JIT und keine offenen Management-Ports
- OS-Hardening + Defender for Cloud + regelmäßige Image-Rotation
- Runner als unprivilegierter Service-User
- Egress restriktiv steuern (ACR, GitLab oder Azure APIs gezielt erlauben)
Vergleich aus Architekturperspektive
| Kriterium | Container Apps | App Service | VM/VMSS |
|---|---|---|---|
| Betriebsaufwand | Niedrig | Niedrig bis mittel | Hoch |
| Laufzeitkontrolle | Mittel | Niedrig | Sehr hoch |
| Eignung für volatile Last | Hoch | Mittel | Mittel |
| Eignung für schwere Builds | Mittel | Niedrig | Hoch |
| Security-Hardening-Tiefe | Mittel | Mittel | Sehr hoch (aber Eigenaufwand) |
Meine Empfehlung für die Praxis
Für die meisten Teams sind Container Apps die sinnvolle Standardwahl. Für schwere, systemnahe Builds hingegen eignen sich virtuelle Maschinen oder Virtual Machine Scale Sets besser. App Services sollte nur verwendet werden, wenn sie organisatorisch bereits etabliert sind und die Anforderungen es erfordern.
Wichtiger als die konkrete Plattformwahl ist jedoch, dass ihr frühzeitig drei grundlegende Aspekte sauber modelliert:
1. Identity-Modell: Managed Identity, Key Vault und die Vermeidung von Secret-Sprawl.
2. Netzwerkmodell: Private Endpoints, kontrollierter Egress und zuverlässige DNS-Auflösung.
3. Betriebsmodell: Monitoring, Image-Lifecycle und Incident-Runbooks.
Wenn diese drei Fundamente stehen, ist der Runner keine Baustelle mehr, sondern ein stabiler und belastbarer Bestandteil der Plattform.
Azure- und CI/CD-Plattform überprüfen und absichern
Self-Hosted GitLab Runner sind ein zentraler Bestandteil moderner Cloud-Plattformen gleichzeitig entstehen Risiken oft in Identity-Konfiguration, Netzwerkpfaden oder im Betriebsmodell.
Mit unserem Cloud Audit analysieren wir eure Azure- und CI/CD-Umgebung strukturiert und identifizieren konkrete Verbesserungen in den Bereichen Sicherheit, Architektur und Betriebsstabilität.
Ihr erhaltet klare Handlungsempfehlungen, priorisierte Maßnahmen und eine belastbare Grundlage, um eure Plattform sicher und skalierbar weiterzuentwickeln.

