1. Übersicht
In diesem Lab werden Funktionen und Möglichkeiten vorgestellt, die den Entwicklungsablauf für Softwareentwickler optimieren sollen, die Python-Anwendungen in einer containerisierten Umgebung entwickeln. Für die typische Containerentwicklung muss der Nutzer Details zu Containern und zum Container-Build-Prozess kennen. Außerdem müssen Entwickler ihren Workflow in der Regel unterbrechen und ihre IDE verlassen, um ihre Anwendungen in Remote-Umgebungen zu testen und zu debuggen. Mit den in diesem Tutorial erwähnten Tools und Technologien können Entwickler effektiv mit containerisierten Anwendungen arbeiten, ohne ihre IDE zu verlassen.
Lerninhalte
In diesem Lab lernen Sie Methoden für die Entwicklung mit Containern in der GCP kennen, darunter:
- Neue Python-Starteranwendung erstellen
- Entwicklungsprozess durchlaufen
- Einfachen REST-CRUD-Dienst entwickeln
2. Einrichtung und Anforderungen
Umgebung zum selbstbestimmten Lernen einrichten
- Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.



- Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Es handelt sich um einen String, der nicht von Google APIs verwendet wird und den Sie jederzeit aktualisieren können.
- Die Projekt-ID muss für alle Google Cloud-Projekte eindeutig sein und ist unveränderlich (kann nach der Festlegung nicht mehr geändert werden). In der Cloud Console wird automatisch ein eindeutiger String generiert. Normalerweise ist es nicht wichtig, wie dieser aussieht. In den meisten Codelabs müssen Sie auf die Projekt-ID verweisen (die in der Regel als
PROJECT_IDangegeben wird). Wenn Ihnen die ID nicht gefällt, können Sie eine andere zufällige ID generieren oder eine eigene ID ausprobieren und sehen, ob sie verfügbar ist. Nachdem das Projekt erstellt wurde, wird es „eingefroren“. - Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten
- Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/-APIs verwenden zu können. Die Durchführung dieses Codelabs sollte keine oder nur geringe Kosten verursachen. Wenn Sie Ressourcen herunterfahren möchten, damit nach Abschluss dieses Codelabs keine Gebühren anfallen, folgen Sie den Bereinigungsanweisungen am Ende des Codelabs. Neue Nutzer von Google Cloud kommen für das Programm für kostenlose Testversionen mit einem Guthaben von 300$ infrage.
Cloud Shell-Editor starten
Dieses Lab wurde für die Verwendung mit Google Cloud Shell Editor entwickelt und getestet. So greifen Sie auf den Editor zu:
- Rufen Sie Ihr Google-Projekt unter https://console.cloud.google.com auf.
- Klicken Sie oben rechts auf das Cloud Shell Editor-Symbol.

- Unten im Fenster wird ein neuer Bereich geöffnet.
- Klicken Sie auf die Schaltfläche „Editor öffnen“.

- Der Editor wird mit einem Explorer auf der rechten Seite und dem Editor im mittleren Bereich geöffnet.
- Unten auf dem Bildschirm sollte auch ein Terminalbereich verfügbar sein.
- Wenn das Terminal NICHT geöffnet ist, verwenden Sie die Tastenkombination „Strg+``“, um ein neues Terminalfenster zu öffnen.
Umgebung einrichten
Legen Sie in Cloud Shell Ihre Projekt-ID und die Projektnummer für Ihr Projekt fest. Speichern Sie sie als die Variablen PROJECT_ID und PROJECT_ID.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format='value(projectNumber)')
Quellcode abrufen
- Der Quellcode für dieses Lab befindet sich im Repository „container-developer-workshop“ in der Organisation „GoogleCloudPlatform“ auf GitHub. Klonen Sie das Repository mit dem folgenden Befehl und wechseln Sie dann in das Verzeichnis.
git clone https://github.com/GoogleCloudPlatform/container-developer-workshop.git &&
cd container-developer-workshop/labs/python
mkdir music-service && cd music-service
cloudshell workspace .
Wenn das Terminal NICHT geöffnet ist, verwenden Sie die Tastenkombination „Strg+``“, um ein neues Terminalfenster zu öffnen.
Die in diesem Lab verwendete Infrastruktur bereitstellen
In diesem Lab stellen Sie Code in GKE bereit und greifen auf Daten zu, die in einer Spanner-Datenbank gespeichert sind. Das folgende Setupscript bereitet diese Infrastruktur für Sie vor. Der Bereitstellungsprozess dauert länger als 10 Minuten. Sie können mit den nächsten Schritten fortfahren, während die Einrichtung verarbeitet wird.
../setup.sh
3. Neue Python-Starteranwendung erstellen
- Erstellen Sie eine Datei mit dem Namen
requirements.txtund kopieren Sie den folgenden Inhalt hinein.
Flask
gunicorn
google-cloud-spanner
ptvsd==4.3.2
- Erstellen Sie eine Datei mit dem Namen
app.pyund fügen Sie den folgenden Code ein:
import os
from flask import Flask, request, jsonify
from google.cloud import spanner
app = Flask(__name__)
@app.route("/")
def hello_world():
message="Hello, World!"
return message
if __name__ == '__main__':
server_port = os.environ.get('PORT', '8080')
app.run(debug=False, port=server_port, host='0.0.0.0')
- Erstellen Sie eine Datei mit dem Namen „Dockerfile“ und fügen Sie Folgendes ein:
FROM python:3.8
ARG FLASK_DEBUG=0
ENV FLASK_DEBUG=$FLASK_DEBUG
ENV FLASK_APP=app.py
WORKDIR /app
COPY requirements.txt .
RUN pip install --trusted-host pypi.python.org -r requirements.txt
COPY . .
ENTRYPOINT ["python3", "-m", "flask", "run", "--port=8080", "--host=0.0.0.0"]
Hinweis: Mit FLASK_DEBUG=1 können Sie Codeänderungen in einer Python Flask-App automatisch neu laden. Mit diesem Dockerfile können Sie diesen Wert als Build-Argument übergeben.
Manifeste generieren
Führen Sie im Terminal den folgenden Befehl aus, um eine Standarddatei „skaffold.yaml“ und „deployment.yaml“ zu generieren.
- Initialisieren Sie Skaffold mit dem folgenden Befehl:
skaffold init --generate-manifests
Wenn Sie dazu aufgefordert werden, verwenden Sie die Pfeiltasten, um den Cursor zu bewegen, und die Leertaste, um die Optionen auszuwählen.
Wählen Sie aus:
8080für den Porty, um die Konfiguration zu speichern
Skaffold-Konfigurationen aktualisieren
- Standardmäßigen Anwendungsnamen ändern
skaffold.yamlöffnen- Wählen Sie den Bildnamen aus, der derzeit als
dockerfile-imagefestgelegt ist. - Klicken Sie mit der rechten Maustaste und wählen Sie „Alle Vorkommen ändern“ aus.
- Geben Sie den neuen Namen als
python-appein. - Bearbeiten Sie den Build-Abschnitt weiter, um
docker.buildArgszur KarteFLASK_DEBUG=1hinzufügen- Synchronisieren Sie die Einstellungen, um Änderungen an
*.py-Dateien aus der IDE in den laufenden Container zu laden.
Nach den Änderungen sieht der Build-Abschnitt in der Datei skaffold.yaml so aus:
build:
artifacts:
- image: python-app
docker:
buildArgs:
FLASK_DEBUG: 1
dockerfile: Dockerfile
sync:
infer:
- '**/*.py'
Kubernetes-Konfigurationsdatei ändern
- Standardname ändern
deployment.yaml-Datei öffnen- Wählen Sie den Bildnamen aus, der derzeit als
dockerfile-imagefestgelegt ist. - Klicken Sie mit der rechten Maustaste und wählen Sie „Alle Vorkommen ändern“ aus.
- Geben Sie den neuen Namen als
python-appein.
4. Entwicklungsprozess durchlaufen
Nachdem Sie die Geschäftslogik hinzugefügt haben, können Sie Ihre Anwendung bereitstellen und testen. Im folgenden Abschnitt wird die Verwendung des Cloud Code-Plug-ins beschrieben. Dieses Plug-in ist unter anderem in Skaffold integriert, um Ihren Entwicklungsprozess zu optimieren. Wenn Sie Ihre Anwendung in den folgenden Schritten in GKE bereitstellen, erstellen Cloud Code und Skaffold automatisch Ihr Container-Image, übertragen es per Push in eine Container Registry und stellen Ihre Anwendung dann in GKE bereit. Dies geschieht im Hintergrund und die Details werden vom Entwicklerfluss abstrahiert.
In Kubernetes bereitstellen
- Wählen Sie im Bereich unten im Cloud Shell-Editor Cloud Code  aus.

- Wählen Sie im Feld, das oben angezeigt wird, Auf Kubernetes ausführen aus. Wenn Sie dazu aufgefordert werden, wählen Sie „Ja“ aus, um den aktuellen Kubernetes-Kontext zu verwenden.

Mit diesem Befehl wird der Quellcode erstellt und dann werden die Tests ausgeführt. Das Erstellen und Testen dauert einige Minuten. Diese Tests umfassen Unittests und einen Validierungsschritt, mit dem die für die Bereitstellungsumgebung festgelegten Regeln geprüft werden. Dieser Validierungsschritt ist bereits konfiguriert und sorgt dafür, dass Sie vor Bereitstellungsproblemen gewarnt werden, auch wenn Sie noch in Ihrer Entwicklungsumgebung arbeiten.
- Wenn Sie den Befehl zum ersten Mal ausführen, wird oben auf dem Bildschirm eine Aufforderung angezeigt, in der Sie gefragt werden, ob Sie den aktuellen Kubernetes-Kontext verwenden möchten. Wählen Sie „Ja“ aus, um den aktuellen Kontext zu akzeptieren und zu verwenden.
- Als Nächstes werden Sie gefragt, welche Container Registry Sie verwenden möchten. Drücken Sie die Eingabetaste, um den angegebenen Standardwert zu übernehmen.
- Wählen Sie im unteren Bereich den Tab „Ausgabe“ aus, um den Fortschritt und Benachrichtigungen zu sehen.

- Wählen Sie im Drop-down-Menü rechts „Kubernetes: Run/Debug – Detailed“ (Kubernetes: Ausführen/Debuggen – Detailliert) aus, um zusätzliche Details und Logs zu sehen, die live aus den Containern gestreamt werden.

Wenn der Build und die Tests abgeschlossen sind, wird auf dem Tab „Ausgabe“ Attached debugger to container "python-app-8476f4bbc-h6dsl" successfully. angezeigt und die URL „http://localhost:8080“ wird aufgeführt.
- Bewegen Sie den Mauszeiger im Cloud Code-Terminal auf die erste URL in der Ausgabe (http://localhost:8080) und wählen Sie dann in der angezeigten Kurzinfo die Option „Webvorschau öffnen“ aus.
- Ein neuer Browsertab wird geöffnet und die Meldung
Hello, World!wird angezeigt.
Hot Reload
- Öffnen Sie die Datei
app.py. - Ändere den Begrüßungstext in
Hello from Python.
Im Output-Fenster, Kubernetes: Run/Debug-Ansicht, synchronisiert der Watcher die aktualisierten Dateien mit dem Container in Kubernetes.
Update initiated Build started for artifact python-app Build completed for artifact python-app Deploy started Deploy completed Status check started Resource pod/python-app-6f646ffcbb-tn7qd status updated to In Progress Resource deployment/python-app status updated to In Progress Resource deployment/python-app status completed successfully Status check succeeded ...
- Wenn Sie zur Ansicht
Kubernetes: Run/Debug - Detailedwechseln, werden Sie feststellen, dass Dateiänderungen erkannt und die App dann neu erstellt und bereitgestellt wird.
files modified: [app.py]
Syncing 1 files for gcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Copying files:map[app.py:[/app/app.py]]togcr.io/veer-pylab-01/python-app:3c04f58-dirty@sha256:a42ca7250851c2f2570ff05209f108c5491d13d2b453bb9608c7b4af511109bd
Watching for changes...
[python-app] * Detected change in '/app/app.py', reloading
[python-app] * Restarting with stat
[python-app] * Debugger is active!
[python-app] * Debugger PIN: 744-729-662
- Aktualisieren Sie Ihren Browser, um die aktualisierten Ergebnisse zu sehen.
Debugging
- Rufen Sie die Debug-Ansicht auf und beenden Sie den aktuellen Thread
. - Klicken Sie im unteren Menü auf
Cloud Codeund wählen SieDebug on Kubernetesaus, um die Anwendung imdebug-Modus auszuführen.
- Im
Kubernetes Run/Debug - Detailed-Bereich desOutput-Fensters sehen Sie, dass Skaffold diese Anwendung im Debugmodus bereitstellt.
- Wenn das Skript zum ersten Mal ausgeführt wird, werden Sie aufgefordert, den Speicherort der Quelle im Container anzugeben. Dieser Wert bezieht sich auf die Verzeichnisse im Dockerfile.
Eingabetaste drücken, um den Standardwert zu übernehmen

Es dauert einige Minuten, bis die Anwendung erstellt und bereitgestellt wird.
- Wenn der Vorgang abgeschlossen ist. Sie sehen, dass ein Debugger angehängt ist.
Port forwarding pod/python-app-8bd64cf8b-cskfl in namespace default, remote port 5678 -> http://127.0.0.1:5678
- Die untere Statusleiste ändert ihre Farbe von Blau zu Orange, was darauf hinweist, dass sie sich im Debug-Modus befindet.
- In der Ansicht
Kubernetes Run/Debugsehen Sie, dass ein debugfähiger Container gestartet wurde.
**************URLs***************** Forwarded URL from service python-app: http://localhost:8080 Debuggable container started pod/python-app-8bd64cf8b-cskfl:python-app (default) Update succeeded ***********************************
Haltepunkte verwenden
- Öffnen Sie die Datei
app.py. - Suchen Sie die Aussage
return message. - Fügen Sie der Zeile einen Haltepunkt hinzu, indem Sie auf den leeren Bereich links neben der Zeilennummer klicken. Eine rote Markierung zeigt an, dass der Haltepunkt festgelegt ist.
- Laden Sie den Browser neu. Der Debugger hält den Prozess am Haltepunkt an und ermöglicht es Ihnen, die Variablen und den Status der Anwendung zu untersuchen, die remote in GKE ausgeführt wird.
- Klicken Sie auf den Abschnitt „VARIABLEN“.
- Klicken Sie auf „Locals“. Dort finden Sie die Variable
"message". - Doppelklicken Sie auf den Variablennamen „message“ und ändern Sie den Wert im Pop-up-Fenster in einen anderen Wert, z. B.
"Greetings from Python". - Klicken Sie in der Debugging-Steuerung auf die Schaltfläche „Weiter“
. - Sehen Sie sich die Antwort in Ihrem Browser an. Dort wird jetzt der aktualisierte Wert angezeigt, den Sie gerade eingegeben haben.
- Beenden Sie den Debug-Modus, indem Sie auf die Stopptaste
drücken, und entfernen Sie den Haltepunkt, indem Sie noch einmal darauf klicken.
5. Einfachen CRUD-REST-Dienst entwickeln
Ihre Anwendung ist jetzt vollständig für die containerisierte Entwicklung konfiguriert und Sie haben den grundlegenden Entwicklungs-Workflow mit Cloud Code durchlaufen. In den folgenden Abschnitten wenden Sie das Gelernte an, indem Sie REST-Dienstendpunkte hinzufügen, die eine Verbindung zu einer verwalteten Datenbank in Google Cloud herstellen.
Rest-Dienst programmieren
Mit dem folgenden Code wird ein einfacher REST-Dienst erstellt, der Spanner als Datenbank für die Anwendung verwendet. Erstellen Sie die Anwendung, indem Sie den folgenden Code in Ihre Anwendung kopieren.
- Erstellen Sie die Hauptanwendung, indem Sie
app.pydurch den folgenden Inhalt ersetzen.
import os
from flask import Flask, request, jsonify
from google.cloud import spanner
app = Flask(__name__)
instance_id = "music-catalog"
database_id = "musicians"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"
@app.route('/singer', methods=['POST'])
def create():
try:
request_json = request.get_json()
singer_id = request_json['singer_id']
first_name = request_json['first_name']
last_name = request_json['last_name']
def insert_singers(transaction):
row_ct = transaction.execute_update(
f"INSERT Singers (SingerId, FirstName, LastName) VALUES" \
f"({singer_id}, '{first_name}', '{last_name}')"
)
print("{} record(s) inserted.".format(row_ct))
database.run_in_transaction(insert_singers)
return {"Success": True}, 200
except Exception as e:
return e
@app.route('/singer', methods=['GET'])
def get_singer():
try:
singer_id = request.args.get('singer_id')
def get_singer():
first_name = ''
last_name = ''
with database.snapshot() as snapshot:
results = snapshot.execute_sql(
f"SELECT SingerId, FirstName, LastName FROM Singers " \
f"where SingerId = {singer_id}",
)
for row in results:
first_name = row[1]
last_name = row[2]
return (first_name,last_name )
first_name, last_name = get_singer()
return {"first_name": first_name, "last_name": last_name }, 200
except Exception as e:
return e
@app.route('/singer', methods=['PUT'])
def update_singer_first_name():
try:
singer_id = request.args.get('singer_id')
request_json = request.get_json()
first_name = request_json['first_name']
def update_singer(transaction):
row_ct = transaction.execute_update(
f"UPDATE Singers SET FirstName = '{first_name}' WHERE SingerId = {singer_id}"
)
print("{} record(s) updated.".format(row_ct))
database.run_in_transaction(update_singer)
return {"Success": True}, 200
except Exception as e:
return e
@app.route('/singer', methods=['DELETE'])
def delete_singer():
try:
singer_id = request.args.get('singer')
def delete_singer(transaction):
row_ct = transaction.execute_update(
f"DELETE FROM Singers WHERE SingerId = {singer_id}"
)
print("{} record(s) deleted.".format(row_ct))
database.run_in_transaction(delete_singer)
return {"Success": True}, 200
except Exception as e:
return e
port = int(os.environ.get('PORT', 8080))
if __name__ == '__main__':
app.run(threaded=True, host='0.0.0.0', port=port)
Datenbankkonfigurationen hinzufügen
Wenn Sie eine sichere Verbindung zu Cloud Spanner herstellen möchten, richten Sie die Anwendung für die Verwendung von Workload Identities ein. So kann Ihre Anwendung als eigenes Dienstkonto fungieren und beim Zugriff auf die Datenbank individuelle Berechtigungen haben.
deployment.yamlaktualisieren. Fügen Sie am Ende der Datei den folgenden Code ein (achten Sie darauf, dass die Tabulatoren im folgenden Beispiel erhalten bleiben).
serviceAccountName: python-ksa
nodeSelector:
iam.gke.io/gke-metadata-server-enabled: "true"
Anwendung bereitstellen und validieren
- Wählen Sie im Bereich unten im Cloud Shell-Editor
Cloud Codeund dann oben auf dem BildschirmDebug on Kubernetesaus. - Wenn der Build und die Tests abgeschlossen sind, wird auf dem Tab „Ausgabe“
Resource deployment/python-app status completed successfullyangezeigt und eine URL wird aufgeführt: „Weitergeleitete URL vom Dienst python-app: http://localhost:8080“. - Fügen Sie einige Einträge hinzu.
Führen Sie im Cloud Shell-Terminal den folgenden Befehl aus.
curl -X POST http://localhost:8080/singer -H 'Content-Type: application/json' -d '{"first_name":"Cat","last_name":"Meow", "singer_id": 6}'
- Testen Sie den GET-Vorgang, indem Sie den folgenden Befehl im Terminal ausführen.
curl -X GET http://localhost:8080/singer?singer_id=6
- Testen Sie das Löschen: Versuchen Sie nun, einen Eintrag zu löschen, indem Sie den folgenden Befehl ausführen. Ändern Sie bei Bedarf den Wert von „item-id“.
curl -X DELETE http://localhost:8080/singer?singer_id=6
This throws an error message
500 Internal Server Error
Problem identifizieren und beheben
- Fehlerbehebungsmodus aktivieren und das Problem finden Hier einige Tipps:
- Wir wissen, dass mit dem DELETE-Befehl etwas nicht stimmt, da er nicht das gewünschte Ergebnis zurückgibt. Sie würden den Haltepunkt also in
app.pyin der Methodedelete_singerfestlegen. - Führen Sie das Programm schrittweise aus und beobachten Sie die Variablen in jedem Schritt, um die Werte der lokalen Variablen im linken Fenster zu sehen.
- Wenn Sie bestimmte Werte wie
singer_idundrequest.argsbeobachten möchten, fügen Sie diese Variablen dem Fenster „Überwachen“ hinzu.
- Beachten Sie, dass der
singer_idzugewiesene WertNoneist. Ändern Sie den Code, um das Problem zu beheben.
Das korrigierte Code-Snippet sieht so aus:
@app.route('/delete-singer', methods=['DELETE', 'GET'])
def delete_singer():
try:
singer_id = request.args.get('singer_id')
- Wenn die Anwendung neu gestartet wurde, versuchen Sie noch einmal, die Datei zu löschen.
- Beenden Sie die Debugging-Sitzung, indem Sie in der Debug-Symbolleiste auf das rote Quadrat
klicken.
6. Bereinigen
Glückwunsch! In diesem Lab haben Sie eine neue Python-Anwendung von Grund auf erstellt und so konfiguriert, dass sie effektiv mit Containern zusammenarbeitet. Anschließend haben Sie Ihre Anwendung in einem Remote-GKE-Cluster bereitgestellt und dort Fehler behoben. Dabei haben Sie denselben Entwickler-Workflow verwendet, der auch bei herkömmlichen Anwendungsstacks zum Einsatz kommt.
So bereinigen Sie die Umgebung nach Abschluss des Labs:
- Im Lab verwendete Dateien löschen
cd ~ && rm -rf container-developer-workshop
- Projekt löschen, um alle zugehörigen Infrastrukturen und Ressourcen zu entfernen