Im IT-Alltag sind Container längst angekommen – bei der Eigenentwicklung von Anwendungen wie auch dem Betrieb von Drittanbieter-Produkten. Als Platzhirsch hat sich hier Kubernetes etabliert. Doch ist der Aufwand für den Betrieb von Kubernetes in vielen Fällen groß. Mit Google Cloud Run beleuchten wir eine leichtgewichtige Alternative und zeigen, wie sich diese aufsetzen lässt.
Genauso wie bei Kubernetes gibt es eine Reihe von Anfoderungen, denen sich Cloud Run [1] stellen muss. Zum einen soll sich Cloud Run um das komplette Deployment und Management über den gesamten Lebenszyklus kümmern – von der Provisionierung über das Scheduling bis hin zum Löschen – und somit den Aufwand für den Betrieb von containerisierten Anwendungen deutlich reduzieren.
Wichtig ist zudem die Skalierbarkeit. Container werden in der Regel zustandslos implementiert, sodass je nach Last entweder eine Vielzahl von Instanzen startet oder diese bis auf Null herunterskalieren. Natürlich muss die Anwendung auch erreichbar sein, was einen Loadbalancer nötig macht, um den Traffic auf die Instanzen im Backend zu verteilen. Damit eine Skalierung überhaupt möglich ist, ist ein Monitoring der zugrundeliegenden Auslastung gefragt – in der Regel betrifft dies die CPU- sowie Speicherauslastung. Damit lässt sich eine Überprovisionierung vermeiden, aber gleichzeitig sicherstellen, dass jeder Container an die von ihm benötigten Ressourcen gelangt.
Für den Betrieb von Anwendungen spielt zudem die Hochverfügbarkeit eine wichtige Rolle. Falls ein Container ausfällt, soll dieser automatisch neu starten. Sollte der zugrundeliegende Knoten ein Problem haben, muss der Neustart auf einen anderen Host erfolgen. Nicht vernachlässigen dürfen Sie auch das Netzwerk – insbesondere, wenn Applikationen hochverfügbar sowie skalierbar laufen sollen. Während es einfach ist, Container-Umgebungen auf einen einzelnen Knoten zu administrieren, bringt die manuelle Verwaltung von größeren Umgebungen viel mehr Aufwand in Sachen Netzwerk mit sich – dies muss der Container-Orchestrierer abfangen.
Genauso wie bei Kubernetes gibt es eine Reihe von Anfoderungen, denen sich Cloud Run [1] stellen muss. Zum einen soll sich Cloud Run um das komplette Deployment und Management über den gesamten Lebenszyklus kümmern – von der Provisionierung über das Scheduling bis hin zum Löschen – und somit den Aufwand für den Betrieb von containerisierten Anwendungen deutlich reduzieren.
Wichtig ist zudem die Skalierbarkeit. Container werden in der Regel zustandslos implementiert, sodass je nach Last entweder eine Vielzahl von Instanzen startet oder diese bis auf Null herunterskalieren. Natürlich muss die Anwendung auch erreichbar sein, was einen Loadbalancer nötig macht, um den Traffic auf die Instanzen im Backend zu verteilen. Damit eine Skalierung überhaupt möglich ist, ist ein Monitoring der zugrundeliegenden Auslastung gefragt – in der Regel betrifft dies die CPU- sowie Speicherauslastung. Damit lässt sich eine Überprovisionierung vermeiden, aber gleichzeitig sicherstellen, dass jeder Container an die von ihm benötigten Ressourcen gelangt.
Für den Betrieb von Anwendungen spielt zudem die Hochverfügbarkeit eine wichtige Rolle. Falls ein Container ausfällt, soll dieser automatisch neu starten. Sollte der zugrundeliegende Knoten ein Problem haben, muss der Neustart auf einen anderen Host erfolgen. Nicht vernachlässigen dürfen Sie auch das Netzwerk – insbesondere, wenn Applikationen hochverfügbar sowie skalierbar laufen sollen. Während es einfach ist, Container-Umgebungen auf einen einzelnen Knoten zu administrieren, bringt die manuelle Verwaltung von größeren Umgebungen viel mehr Aufwand in Sachen Netzwerk mit sich – dies muss der Container-Orchestrierer abfangen.
Cloud Run als Kubernetes-Alternative
Cloud Run ist als dedizierte Kubernetes-Alternative für viele Verwendungszwecke gedacht, wie die Dokumentation [2] zu der Umgebung verdeutlicht. Es ist dafür ausgelegt, statuslose HTTP- oder ereignisbasierte Anwendungen zu hosten und gleichzeitig basierend auf eingehenden Anfragen oder Events zu skalieren – inklusive einer Null-Skalierung, sodass keine Kosten anfallen. Die Abrechnung erfolgt nutzungsbasiert, weshalb keine Mindestkosten wie zum Beispiel bei Kubernetes anfallen.
Technologisch basiert Cloud Run auf der Open-Source-Technologie Knative, wodurch wie bei vielen Managed Services von Google auch bei Cloud Run kein Vendor Lock-in droht. Knative wurde ursprünglich von Google in Zusammenarbeit mit Red Hat, IBM und anderen ins Leben gerufen, basiert auf Kubernetes und abstrahiert dessen Komplexität für Entwickler.
Cloud Run bietet zwei Betriebsmodi: Zum einen ist das Cloud Run für Jobs, das für einmalige oder batchbasierte Aufgaben ausgelegt ist. Dies könnte ein einfaches Skript oder Tool sein, um beispielsweise Datenbankmigrationen oder andere operative Aufgaben auszuführen. Auch eine Parallelisierung von Aufgaben ist möglich, wie zum Beispiel das Abarbeiten von Daten, die in einem Cloud-Storage liegen. Ein Scheduling von Jobs ist auch möglich. Der andere Betriebsmodus nennt sich Cloud Run Services und richtet sich an Use-Cases wie etwa Websites und Webanwendungen, APIs und Microservices, Streaminganwendungen, asynchrone Arbeitslasten mit Messaging-Komponenten oder KI-Inferenz.
Die Nutzung von Cloud Run ist konzeptionell einfach gestaltet.
Bild 1: Die Paketierung eines Container-Images ist einfach gestaltet.
Wie bei jeder anderen Container-Technologie bauen Sie ein Container-Image und verpacken darin alle Build-Artefakte, Assets und Systempakete (Bild 1). Entsprechend kann Cloud Run prinzipiell mit jedem Container-Image laufen – ein exklusives Bauen für Cloud Run ist nicht notwendig.
Erste Schritte
Die ersten Schritte mit Cloud Run sind relativ einfach, wie wir im Folgenden am Beispiel einer Anwendung mit Python Flask – ein Web-API – zeigen. Um loszulegen, wählen Sie zuerst ein Google-Projekt in der Console aus und stellen sicher, dass Sie die notwendigen Rechte besitzen – dies wären Cloud Run Admin, Cloud Run Developer und Logs Viewer. Anschließend starten Sie die Cloud Shell und aktivieren Cloud Run mit:
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com
Nun können Sie sich daran machen, eine Beispielanwendung zu schreiben. Dazu erstellen Sie ein Verzeichnis und wechseln in dieses:
mkdir it-admin
cd it-admin
Erstellen Sie jetzt eine Datei namens "main.py" und legen Sie folgenden Quellcode darin ab:
import os
from flask import Flask
app = Flask(__name__)
AT-ZEICHENapp.route("/")
def hello_itadmin():
"""Example IT Admin route."""
name = os.environ.get("NAME",
"IT Admin")
return f"Hello {name}!"
if __name__ == "__main__":
app.run(debug=True,
host="0.0.0.0", port=int
(os.environ.get("PORT", 8080)))
Der Code antwortet auf Anfragen mit der Begrüßung "Hello IT Admin". Die HTTP-Verarbeitung erfolgt über den integrierten Webserver im Container, der durch die Flask-Bibliothek bereitgestellt wird und standardmäßig auf Port 8080 lauscht. Nun müssen Sie noch dafür sorgen, dass beim Container-Bau alle notwendigen Bibliotheken installiert werden. In Python geht dies, indem Sie die Datei "requirements.txt" mit folgendem Inhalt anlegen:
Flask==3.0.3
gunicorn==23.0.0
Werkzeug==3.0.3
Bei der Flask-Abhängigkeit handelt es sich wie beschrieben um das Framework zum Entwickeln von Webanwendungen. Das Bibliothekswerkzeug wird im Code nicht direkt genutzt, sondern von Flask benötigt, um HTTP-Requests und -Responses zu bearbeiten. Zwar liefert Flask schon von Haus aus einen Development-Webserver. Dieser ist aber für Produktivzwecke nicht geeignet, sodass die dritte Abhängigkeit "gunicorn" ins Spiel kommt und einen Webserver für den Produktiveinsatz liefert.
Nachdem das geklärt ist, machen wir uns an das Bauen der Anwendung und deployen diese. Dies gelingt mit folgenden Befehl im "it-admin"-Verzeichnis:
gcloud run deploy --source .
Nun folgt die Frage nach dem Dienstnamen sowie unter Umständen die Aufforderung, die Google Artifact Registry zu aktivieren, die in Cloud Run das zu bauende Image hochlädt. Eine Region müssen Sie auch noch angeben – wenn Sie nach Frankfurt deployen möchten, wählen Sie "europe-west3" aus. Soll der Webservice öffentlich erreichbar sein, bestätigen Sie dies anschließend auch noch.
Das gezeigte Python-Beispiel kommt ohne Docker-File aus und kann direkt aus dem Quellcodeverzeichnis in Cloud Run deployt werden. Dies ist möglich, da Python automatisch durch ein Google-Cloud-Buildpack erkannt werden kann. Bei Buildpacks handelt es sich um eine Toolkette, die den Quellcode einer Anwendung analysiert und automatisch in ausführbare Container-Images umwandelt, ohne dass Sie manuell ein Docker-File schreiben müssen. Ursprünglich wurden sie in den PaaS-Systemen Heroku und Cloud Foundry um das Jahr 2011 entwickelt, sind aber mittlerweile Teil des Ökosystems der Cloud Native Computing Foundation (CNCF). Neben Python sind in Google auch die Sprachen Go, Java, Node.js, Ruby, .NET. Core und PHP unterstützt – alle anderen müssen mit expliziten Docker-Files integriert werden.
Cloud Run absichern
In vielen Fällen möchten Admins ihre Cloud-Run-Anwendungen absichern und nicht frei zugänglich im Internet präsentieren. Eine Möglichkeit hierfür bietet der Identity-Aware-Proxy (IAP), ein Google-Dienst, der den Zugriff auf Anwendungen – darunter auch durch Cloud Run gehostete Apps – durch Authentifizierung und Autorisierung absichert, ohne dass hierfür ein VPN und ein Zero-Trust-Zugriffsmodell nötig sind. Dies geschieht dadurch, dass IAP jede Anfrage anhand der Nutzeridentität und dessen IAM-Rollen überprüft – optional lässt sich ein Zugriff auch an Attributen wie etwa der IP-Adresse festmachen (Bild 2).
Bild 2: Cloud Run lässt sich mittels des Identity-Aware-Proxies absichern.
Um IAP für eine Cloud-Run-Instanz zu aktivieren, steht zuerst die Konfiguration von OAuth an. Dazu wechseln Sie in der Google-Console zuerst auf die Seite "API & Services" (erreichbar durch Suche) und klicken anschließend in der linken Navigation auf "OAuth Consent Screen". Durch die Auswahl von "Get Started" beginnen Sie nun mit der OAuth-Einrichtung. Zuerst geben Sie einen Namen und eine User-Support-E-Mail an. Anschließend definieren Sie, ob die Anwendung intern für User in der Google-Organisation zur Verfügung steht oder für jede Person mit einem Google-Konto. Nun fehlt noch eine Kontaktinformation und der Vorgang ist abgeschlossen.
Jetzt können Sie IAP für Ihre Cloud-Run-Anwendung aktivieren. Dazu gehen Sie in der Google-Cloud-Konsole auf die Cloud-Run-Instanz und wechseln dort auf die Registerkarte "Security", um anschließend die Checkbox für IAP zu setzen. Falls Sie weitere Einschränkungen (zum Beispiel Quell-IP-Adressen) definieren möchten, klicken Sie noch auf "Edit Policy" und konfigurieren im sich öffnenden Fenster die Context-Aware-Access-Policies für die User. Damit ein Anwender Zugriff erhält, muss er nur noch die entsprechenden Berechtigungen besitzen. Dies lässt sich im Bereich des IAM konfigurieren, indem Sie die Rolle "IAP-secured Web App User" vergeben.
Cloud Run und Loadbalancer
Viele Unternehmen entscheiden sich, Cloud-Run-Anwendungen nicht direkt, sondern über einen Loadbalancer zugänglich zu machen. Ein solches Setup hat verschiedene Vorteile. Zum einen schaffen Sie damit eine globale Verfügbarkeit sowie Redundanz, indem Sie die Anwendung in mehr als eine Region ausrollen. Darüber hinaus integrieren sich Loadbalancer mit der Google Web Application Firewall (WAF) Cloud Armor und bieten somit mehr Schutz vor Angriffen. Auch besteht die Möglichkeit, einen Domain (zum Beispiel "it-admin.sclabs.cloud") auf die Cloud-Run-Anwendungen zu mappen und entsprechend eigene SSL/TLS-Zertifikate zu nutzen.
Allerdings gibt es auch einige Faktoren, die Sie vorher beachten sollten: Zum einen fallen zusätzliche Kosten für einen Loadbalancer an und zum anderen bringt ein solches Setup eine gewisse Komplexität mit sich. In Bild 3 ist ein solches Set-up für das Szenario eines externen regionalen Loadbalancer visualisiert, das aus einer Reihe von Komponenten besteht:
- Am Anfang des eingehenden Datenverkehrs steht die Forwarding-Rule. Dies ist eine Regel, die den Datenverkehr auf Basis einer IP-Adresse, eines Port und eines Protokolls an einen Target-Proxy weiterleitet.
- Der Target-Proxy nimmt eingehende Anfragen an und leitet sie anhand der URL-Map an den richtigen Backendservice weiter. Falls Sie den Dienst für HTTPS-Verkehr absichern möchten, muss vorher ein SSL-Zertifikat vorhanden sein.
- Google-Target-Proxies und somit die regionalen Loadbalancer basieren auf dem quelloffenen Reverse-Proxy Envoy. Für dessen Rollout ist ein dediziertes Subnet notwendig, aus dem der Proxy seine IP-Adressen erhält. Dieses Subnet muss sich in der gleichen Region wie die Cloud-Run-Anwendung befinden.
- In der Google-Cloud gibt es zwei Typen von SSL/TLS-Zertifikaten, die sich für einen externen regionalen Loadbalancer verwenden lassen: Google-Managed-Certificates, die die Google-Cloud automatisch erstellt, verwaltet und erneuert. Sie sind aber nur für Domains verfügbar, die über Cloud-DNS oder eine andere DNS-Zone mit korrektem Setup verwaltet werden. Daneben gibt es selbstverwaltete Zertifikate wie etwa von Let's Encrypt.
- Die URL-Map definiert die Weiterleitung der Anfragen an die Backendservices mittels Hostnamen und -pfaden.
- Der Backendservice stellt die Verbindung zwischen URL-Map und Cloud-Run-Instanz dar. Als Administrator können Sie den zu nutzenden Port des Backends, Health Checks, Cloud Armor oder IAP konfigurieren.
- Am Ende der Kette steht das eigentliche Backend – in diesem Fall die Cloud-Run-Instanz, dessen Endpunkt durch eine "Serverless Network Endpoint Group" (Serverless NEG) repräsentiert wird.
Bild 3: Die Komponenten eines regionalen externen Loadbalancers in der Google-Cloud.
Nachdem wir den Aufbau der Loadbalancer konzeptionell besprochen haben, machen wir uns an den Aufbau. Für eine Dokumentation und um ihn wiederholbar zu gestalten, lohnen sich Scripting beziehungsweise Automatisierungstechniken hierfür. Zuerst sollten Sie die Cloud-Run-Instanz neu deployen und eingehenden Verkehr auf interne und Loadbalancer-Anfragen einschränken:
gcloud run deploy it-admin \
--platform=managed \
--allow-unauthenticated \
--ingress=internal-and-cloud-
load-balancing \
--region=europe-west3 \
--source .
Falls Sie noch kein VPC und ein Proxy-only-Subnetz haben, erzeugen Sie dieses:
Die Subnetz-Range kann dabei beliebig gewählt werden. Nachdem die Vorarbeiten abgeschlossen sind, machen wir uns an das Erstellen des Loadbalancers. Als Erstes benötigen wir eine statische externe IP-Adresse für unseren Lastverteiler:
Das Anlegen der URL-Map ist einfach, da der Loadbalancer in unserem Beispiel nur ein Backend bedient und somit alle Anfragen an dieses weiterleitet:
gcloud compute url-maps create
url-map-it-admin \
--default-service=backend-
it-admin \
--region=europe-west3
Im nächsten Schritt kümmern wir uns um die Zertifikate. Wenn Sie schon eines vorliegen haben, können Sie dieses einspielen, indem Sie das Zertifikat sowie den zugehörigen privaten Schlüssel hochladen:
Um abschließend alles zu testen, benötigen Sie natürlich noch die IP-Adresse. Diese lässt sich aber schnell finden, wenn Sie in der Google-Konsole die Seite "Load Balancing" öffnen – dort sehen Sie die IP-Adresse, indem Sie auf den erstellten Loadbalancer klicken. Wer möchte, kann diese Adresse anschließend noch in sein DNS-System eintragen.
KI-Anwendungen integrieren
Die Funktionalität und Flexibilität von Cloud Run hat sich in den letzten Jahren so gesteigert, dass sich immer mehr Anwendungsfälle direkt implementieren lassen. Dabei stehen auch immer mehr KI-bezogene Anwendungsfälle im Vordergrund – Grund genug, um als abschließendes Beispiel zu zeigen, wie Sie in Cloud Run einen Model-Context-Protocol-(MCP)-Server hosten und diesen über das Gemini-CLI abfragen.
MCP ist dabei schnell erklärt: Es handelt sich um einen offenen Standard, der 2024 von Anthropic eingeführt wurde, um die Interaktion von KI-Agenten (etwa Large Language Models wie Gemini) mit externen Tools, Datenquellen und Diensten zu standardisieren. MCP ermöglicht es, KI-Modelle mit strukturierten Funktionen und Daten zu verbinden, ohne für jede Integration individuelle Lösungen programmieren zu müssen. Die Implementierung folgt dabei dem altbekannten Client-Server-Modell. Use-Cases für MCP Server gibt es genug – so beispielsweise der Zugriff auf Google-Cloud-SQL-Daten, um Berichte zu generieren, eine Interaktion mit Cloud-Storage für Objektsuchen oder auch der Aufruf für Workflows zur Automatisierung.
Im Folgenden zeigen wir, wie Sie einen einfachen MCP-Server in Python implementieren. Dabei verwenden wir den Python-Paketmanager als Alternative zum bekannten pip und erzeugen mit folgendem Befehl ein Python-Projekt – samt der "pyproject.taml"-Datei zur Verwaltung von Abhängigkeiten:
mkdir mcp-on-cloudrun
cd mcp-on-cloudrun
uv init --name "mcp-on-cloudrun"
--description "Beispiel-MCP-Server mit Cloud Run" --bare --python 3.10
Um einen einfachen MCP-Server zu implementieren, der einen simplen Text zurückgibt, fügen wir als Nächstes die FastMCP-Bibliothek in der Datei "pyproject.tom" hinzu:
uv add fastmcp==2.8.0 --no-sync
Nun machen wir uns an die Implementierung des Servers und erstellen die Datei "server.py" mit folgendem Inhalt:
"""Returns a friendly greeting from IT Administrator"""
return f"Hello {name}! Der IT-
Administrator-MCP-Server
begruesst Sie"
if __name__ == "__main__":
logger.info(f"MCP server started on port {os.getenv('PORT', 8080)}")
asyncio.run(
mcp.run_async(
transport="streamable-http",
host="0.0.0.0",
port=os.getenv("PORT", 8080),
)
)
Der Code ist schnell erklärt: Nach dem Import der Bibliotheken annotieren wir die zu exponierenden Funktionen mit den Python-Decorator "AT-ZEICHENmcp_tool()" und starten aus der main-Funktion den MCP-Server. Um nun den Container zu bauen, verwenden wir folgendes Docker-File:
Anschließend erzeugen wir einen Cloud-Run-Proxy, der einen authentifizierten Tunnel zu 127.0.0.1:8080 aufbaut:
gcloud run services proxy mcp-server --region=europe-west3
Haben Sie die Gemini-CLI installiert, können Sie anschließend den MCP-Server über die Datei "~/.gemini/mcp.json" konfigurieren:
{
"mcpServers": {
"mcp-server": {
"command": "curl",
"args": ["http://127.0.0.1:8080/mcp"]
}
}
}
Nun ist es einfach möglich, den MCP-Server zu testen. Eine Eingabe von "/greet TestUser" sollte eine Aktion des Cloud-Run-Containers bewirken.
Fazit
Cloud Run entwickelt sich für viele Anwendungsfälle immer mehr zur Alternative zu einer Kubernetes-Installation. Die Tatsache, dass aufgrund des Serverless-Paradigmas der Aufwand deutlich sinkt sowie die Kosten vielfach niedriger und die Lernkurve im Vergleich zu Kubernetes deutlich flacher ausfallen, sollte als Anreiz genügen, Anwendungen künftig auf Cloud Run anstatt Kubernetes auszurollen.