Serverless Microservices: Skalierung in Google Cloud Run mit GitHub Actions

Inhalt
- 1. Architektur-Grundlagen: Scale-to-Zero & schlüsselloses CI/CD
- 2. Schritt-für-Schritt-Einrichtung von Workload Identity Federation
- 3. Schritt-für-Schritt-Konfiguration der GitHub-Actions-Workflow-YAML
- 4. Schritt-für-Schritt-Skalierungs- & Concurrency-Engineering
- 5. Zusammenfassung & Mehrwert
- Fragen und Antworten
- Quellen
Der Betrieb von Microservices auf statischen virtuellen Maschinen oder dauerhaft laufenden Kubernetes-Clustern verursacht kontinuierliche Basis-Infrastrukturkosten, selbst in langen Phasen völliger Inaktivität. Die Bereitstellung zustandsloser (stateless) Container-Web-APIs auf Google Cloud Run ermöglicht eine vollständig verwaltete, serverlose Architektur, die außerhalb der Geschäftszeiten automatisch auf null Instanzen skaliert und bei plötzlichen Lastspitzen sofort Tausende von Containern parallel bereitstellt. Die Verknüpfung dieses Deployment-Modells mit GitHub Actions und Workload Identity Federation etabliert eine wartungsfreie, hochsichere CI/CD-Pipeline, ohne dass langlebige Service-Account-JSON-Schlüssel in externen Repositories gespeichert werden müssen.
1. Architektur-Grundlagen: Scale-to-Zero & schlüsselloses CI/CD
Eine professionelle serverlose Bereitstellungsarchitektur auf der Google Cloud basiert auf drei entkoppelten Komponenten:
- Google Cloud Run Container-Ausführung: Zustandslose Container werden ausschließlich bei eingehenden HTTP-Anfragen gestartet. Konkurrenz-Einstellungen (Concurrency) erlauben es einer einzigen Container-Instanz, bis zu 80 gleichzeitige Requests (Voreinstellung, einstellbar bis 1000) zu verarbeiten, bevor die horizontale Skalierung weitere Instanzen startet.
- Workload Identity Federation (WIF): Ersetzt statische, exportierbare Service-Account-JSON-Schlüssel durch einen OpenID-Connect-Tokenaustausch (OIDC) zwischen GitHub und Google Cloud IAM, was Sicherheitsrisiken durch geleakte Credentials eliminiert.
- GitHub Actions Pipeline: Ein automatisierter Workflow baut das Anwendungs-Docker-Image, überträgt es in die Google Artifact Registry und aktualisiert die Cloud-Run-Revision ohne Ausfallzeit.
2. Schritt-für-Schritt-Einrichtung von Workload Identity Federation
Um eine schlüssellose Authentifizierung für GitHub Actions einzurichten, wird über die Google Cloud CLI ein Workload Identity Pool samt Provider bereitgestellt:
# 1. Workload Identity Pool anlegen
gcloud iam workload-identity-pools create "github-actions-pool" \
--project="enterprise-ai-project" \
--location="global" \
--display-name="GitHub Actions Pool"
# 2. OIDC Identity Provider für GitHub erstellen
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
--project="enterprise-ai-project" \
--location="global" \
--workload-identity-pool="github-actions-pool" \
--display-name="GitHub Provider" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
--attribute-condition="assertion.repository_owner == 'enterprise-org'" \
--issuer-uri="https://token.actions.githubusercontent.com"
# 3. Service Account mit dem GitHub-Repository verknüpfen
gcloud iam service-accounts add-iam-policy-binding "ci-cd-deployer@enterprise-ai-project.iam.gserviceaccount.com" \
--project="enterprise-ai-project" \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/github-actions-pool/attribute.repository/enterprise-org/microservice-repo"
3. Schritt-für-Schritt-Konfiguration der GitHub-Actions-Workflow-YAML
Die automatisierte Deployment-Pipeline erfordert eine strukturierte YAML-Konfiguration im Pfad .github/workflows/deploy.yml. Dieser Workflow authentifiziert sich per OIDC, erstellt das Container-Image und führt das Deployment in Cloud Run mit expliziten Skalierungs- und Concurrency-Parametern aus:
name: Deploy to Google Cloud Run
on:
push:
branches:
- main
permissions:
contents: 'read'
id-token: 'write'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
workload_identity_provider: 'projects/1234567890/locations/global/workloadIdentityPools/github-actions-pool/providers/github-provider'
service_account: 'ci-cd-deployer@enterprise-ai-project.iam.gserviceaccount.com'
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2
- name: Configure Docker for Artifact Registry
run: gcloud auth configure-docker us-central1-docker.pkg.dev
- name: Build and Push Docker Image
run: |
docker build -t us-central1-docker.pkg.dev/enterprise-ai-project/services/api-service:${{ github.sha }} .
docker push us-central1-docker.pkg.dev/enterprise-ai-project/services/api-service:${{ github.sha }}
- name: Deploy to Cloud Run
run: |
gcloud run deploy api-service \
--image us-central1-docker.pkg.dev/enterprise-ai-project/services/api-service:${{ github.sha }} \
--region us-central1 \
--platform managed \
--allow-unauthenticated \
--min-instances 0 \
--max-instances 50 \
--concurrency 80 \
--memory 512Mi \
--cpu 1
4. Schritt-für-Schritt-Skalierungs- & Concurrency-Engineering
Um eine optimale Ressourcenauslastung zu gewährleisten und Kaltstart-Latenzen (Cold Starts) zu minimieren, müssen die Cloud-Run-Laufzeitparameter präzise konfiguriert werden:
- Scale-to-Zero-Verifizierung (
--min-instances=0): Erlaubt Cloud Run, den Dienst ohne Verkehr auf null Instanzen herunterzufahren; ungenutzte Instanzen können bis zu 15 Minuten vorgehalten werden, werden bei der voreingestellten anfragebasierten Abrechnung aber nicht berechnet, wodurch die Laufzeitkosten in Ruhephasen exakt auf 0,00 Euro sinken. - Concurrency-Tuning (
--concurrency=80): Ermöglicht es einer einzelnen Container-CPU, bis zu 80 Anfragen gleichzeitig zu bearbeiten, was den Speicherbedarf und das permanente Starten neuer Container im Vergleich zu Single-Concurrency-Modellen drastisch senkt. - CPU-Drosselungs-Allokation: Standardmäßig wird die CPU außerhalb aktiver HTTP-Requests gedrosselt. Falls Hintergrundprozesse nach einer HTTP-Antwort weiterlaufen müssen, ist der Parameter `–no-cpu-throttling` in Kombination mit `–min-instances=1` zu setzen.
5. Zusammenfassung & Mehrwert
Was sich damit erreichen lässt: Die erfolgreiche Bereitstellung einer vollautomatisierten, schlüssellosen CI/CD-Deployment-Pipeline für Container-Microservices auf Google Cloud Run unter Nutzung von GitHub Actions und Workload Identity Federation.
Resultierender Mehrwert: Die Hosting-Kosten werden minimiert, da die Serverausgaben in Inaktivitätszeiten komplett entfallen, während die Architektur bei Verkehrsspitzen innerhalb von Sekunden automatisch skaliert. Der Verzicht auf statische JSON-Schlüssel eliminiert Sicherheitsrisiken durch geleakte Zugangsdaten, und die präzise Concurrency-Konfiguration maximiert die Containereffizienz für einen komplett wartungsfreien Backend-Betrieb.
Fragen und Antworten
Kostet ein Dienst, der auf null Instanzen skaliert, wirklich nichts?
Die Laufzeit kostet nichts, der Rest der Kette schon. Jeder Lauf der Pipeline legt ein neues Image mit dem Commit-Hash als Tag in der Artifact Registry ab, und dieser Speicher wird nach Menge berechnet, ob der Dienst läuft oder nicht. Eine Bereinigungsregel in der Artifact Registry, die alte Images löscht und einige neuere behält, damit der Rücksprung auf eine frühere Revision möglich bleibt, hält diesen Posten klein.
Welche Rollen braucht der Service Account ci-cd-deployer außer der Workload-Identity-Bindung?
Die Bindung mit roles/iam.workloadIdentityUser erlaubt GitHub nur, sich als dieses Konto auszuweisen. Was das Konto danach tun darf, legen weitere Rollen fest, und der Workflow braucht drei davon:
- Schreibzugriff auf das Repository der Artifact Registry, üblicherweise
roles/artifactregistry.writer; ohne ihn scheitertdocker push. - Eine Cloud-Run-Rolle zum Bereitstellen.
roles/run.developergenügt fürgcloud run deploy, nicht aber für--allow-unauthenticated: Dieser Schalter ändert die IAM-Richtlinie des Dienstes, und das darf erstroles/run.admin. roles/iam.serviceAccountUserauf dem Service Account, unter dem der Dienst läuft; ohne eigene Angabe ist das das Compute-Engine-Standardkonto des Projekts. Ohne diese Rolle darf der Deployer keine Revision anlegen, die unter einer anderen Identität läuft.
Sinnvoll ist, diese Rollen so eng wie möglich zu vergeben, also auf das eine Repository und den einen Dienst statt auf das ganze Projekt. Ein geleakter Schlüssel ist ausgeschlossen, ein fehlerhafter Workflow nicht, und die Rollen bestimmen, wie weit sein Schaden reicht.
Genügt die Bindung an das Repository, oder kann jeder Branch bereitstellen?
Die Bindung gilt für das ganze Repository. Der Workflow startet zwar nur bei einem Push auf main, aber jede andere Workflow-Datei im selben Repository, auch auf einem anderen Branch, kann mit id-token: write ein Token anfordern, und Google nimmt es an, weil das Attribut repository passt.
Enger wird es über den Branch, den das OIDC-Token von GitHub im Feld ref trägt. Eine Bedingung am Provider wie assertion.ref == 'refs/heads/main' (per && an --attribute-condition angehängt) oder ein zusätzlich abgebildetes Attribut, an das der Service Account gebunden wird, lässt nur noch Läufe von main durch. Die in Abschnitt 2 gesetzte Bedingung auf assertion.repository_owner sorgt außerdem dafür, dass der Pool Tokens fremder Organisationen gar nicht erst annimmt.
Was kostet die Kombination aus –no-cpu-throttling und –min-instances=1?
Den Vorteil, mit dem der Artikel beginnt. Eine Mindestinstanz mit dauerhaft zugeteilter CPU läuft rund um die Uhr und wird auch dann berechnet, wenn keine Anfrage kommt; die Laufzeitkosten fallen in Ruhephasen also nicht mehr auf null. Für Arbeit nach der Antwort ist deshalb oft eine eigene Warteschlange oder ein Cloud Run Job die günstigere Wahl, sodass der Webdienst selbst weiter auf null skalieren kann.