Einführung in Container


Wenn Sie mit containerisierten Arbeitslasten nicht vertraut sind, ist diese Anleitung genau richtig für Sie. Sie lernen Container und Containerorchestrierung kennen, indem Sie eine einfache Anwendung vom Quellcode bis zu einem Container einrichten, der in GKE ausgeführt wird.

Für diese Anleitung sind keine Vorkenntnisse mit Containern oder Kubernetes erforderlich. Wenn Sie sich vor Beginn dieses Tutorials einen Überblick über die wichtigsten Kubernetes-Termini verschaffen möchten, lesen Sie den Artikel Einstieg in Kubernetes. Wenn Sie lieber in Comicform mehr über Kubernetes erfahren möchten, sehen Sie sich unseren Kubernetes-Comic an. Ausführlichere Ressourcen finden Sie im Abschnitt Nächste Schritte am Ende des Tutorials.

Wenn Sie bereits mit Containern und Kubernetes vertraut sind, können Sie dieses Tutorial überspringen und direkt mit GKE beginnen.

Lernziele

  1. Einfache „Hello World“-Anwendung für mehrere Services kennenlernen
  2. Führen Sie die Anwendung aus der Quelle aus.
  3. Anwendung containerisieren
  4. Kubernetes-Cluster erstellen
  5. Container im Cluster bereitstellen

Vorbereitung

Führen Sie folgende Schritte aus, um die Kubernetes Engine API zu aktivieren:
  1. Rufen Sie in der Google Cloud Console die Seite "Kubernetes Engine" auf.
  2. Erstellen Sie ein Projekt oder wählen Sie eines aus.
  3. Warten Sie, bis die API und die zugehörigen Dienste aktiviert worden sind. Dieser Vorgang kann einige Minuten dauern.
  4. Make sure that billing is enabled for your Google Cloud project.

Cloud Shell vorbereiten

In dieser Anleitung wird Cloud Shell verwendet, mit der eine virtuelle Maschine (VM) der g1-small Compute Engine bereitgestellt wird, auf der ein Debian-basiertes Linux-Betriebssystem ausgeführt wird.

Cloud Shell bietet folgende Vorteile:

  • Eine Python 3-Entwicklungsumgebung (einschließlich virtualenv) ist vollständig eingerichtet.
  • Die in dieser Anleitung verwendeten gcloud-, docker-, git- und kubectl-Befehlszeilentools sind bereits installiert.
  • Es stehen verschiedene integrierte Texteditoren zur Auswahl:

    • Cloud Shell-Editor: Klicken Sie oben im Cloud Shell-Fenster auf  Editor öffnen, um ihn zu öffnen.

    • Emacs, Vim oder Nano, auf die Sie in Cloud Shell über die Befehlszeile zugreifen.

In the Google Cloud console, activate Cloud Shell.

Activate Cloud Shell

At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

Beispielcode herunterladen

  1. Laden Sie den Quellcode helloserver herunter:

    git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
    
  2. Öffnen Sie das Verzeichnis mit dem Beispielcode:

    cd anthos-service-mesh-samples/docs/helloserver
    

Anwendung mit mehreren Diensten entdecken

Die Beispielanwendung ist in Python geschrieben. Sie besteht aus den folgenden Komponenten, die mit REST kommunizieren:

  • server: Ein einfacher Server mit einem GET-Endpunkt (/), der „Hallo Welt“ in das Terminalfenster ausgibt.
  • loadgen: Ein Skript, das Traffic an server mit einer konfigurierbaren Anzahl von Anfragen pro Sekunde (RPS) sendet.

Beispielanwendung

Anwendung aus der Quelle ausführen

Um sich mit der Beispielanwendung vertraut zu machen, führen Sie sie in Cloud Shell aus:

  1. Führen Sie im Verzeichnis sample-apps/helloserver den Befehl server aus:

    python3 server/server.py
    

    Beim Start zeigt server Folgendes an:

    INFO:root:Starting server...
    
  2. Öffnen Sie ein anderes Terminalfenster, damit Sie Anfragen an server senden können. Klicken Sie dazu in Cloud Shell auf Neuen Tab öffnen, um eine weitere Sitzung zu öffnen.

  3. Senden Sie im neuen Terminalfenster eine Anfrage an die server:

    curl http://localhost:8080
    

    Die Ausgabe von server sieht so aus:

    Hello World!
    
  4. Wechseln Sie auf demselben Tab in das Verzeichnis, das das loadgen-Script enthält:

    cd anthos-service-mesh-samples/docs/helloserver/loadgen
  5. Erstellen Sie die folgenden Umgebungsvariablen:

    export SERVER_ADDR=http://localhost:8080
    export REQUESTS_PER_SECOND=5
    
  6. Starten Sie virtualenv:

    virtualenv --python python3 env
    
  7. Aktivieren Sie die virtuelle Umgebung:

    source env/bin/activate
    
  8. Installieren Sie die Anforderungen für loadgen:

    pip3 install -r requirements.txt
    
  9. Führen Sie die loadgen-Anwendung aus, um Traffic für die server zu generieren:

    python3 loadgen.py
    

    Beim Start sieht die Ausgabe von loadgen in etwa so aus:

    Starting loadgen: 2024-10-11 09:49:51.798028
    5 request(s) complete to http://localhost:8080
    
  10. Öffnen Sie nun das Terminalfenster, in dem die server ausgeführt wird. Sie sollten in etwa folgende Meldungen sehen:

    127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 -
    INFO:root:GET request,
    Path: /
    Headers:
    Host: localhost:8080
    User-Agent: python-requests/2.32.3
    Accept-Encoding: gzip, deflate
    Accept: */*
    Connection: keep-alive
    

    Aus Netzwerksicht wird die gesamte Anwendung jetzt auf demselben Host ausgeführt. Sie können also localhost verwenden, um Anfragen an die server zu senden.

  11. Zum Beenden von loadgen und server drücken Sie in jedem Terminalfenster Ctrl-c.

  12. Deaktivieren Sie im Terminalfenster loadgen die virtuelle Umgebung:

    deactivate
    

Anwendung containerisieren

Um die Anwendung in GKE auszuführen, müssen Sie beide Komponenten der Beispielanwendung in Container verpacken. Ein Container ist ein Paket, das alle erforderlichen Elemente für die Ausführung Ihrer Anwendung in jeder Umgebung enthält. In dieser Anleitung wird Docker verwendet, um die Anwendung zu containerisieren.

Zum Containerisieren der Anwendung mit Docker benötigen Sie ein Dockerfile. Ein Dockerfile ist eine Textdatei, in der die Befehle definiert sind, die zum Erstellen des Quellcodes der Anwendung und der Abhängigkeiten in einem Container-Image erforderlich sind. Nachdem Sie das Image erstellt haben, laden Sie es in eine Container Registry wie Artifact Registry hoch.

Der Quellcode für diese Anleitung enthält ein Dockerfile für server und loadgen mit allen Befehlen, die zum Erstellen der Images erforderlich sind. Im Folgenden finden Sie das Dockerfile für den server:

FROM python:3.13-slim as base
FROM base as builder
RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        g++ \
    && rm -rf /var/lib/apt/lists/*

# Enable unbuffered logging
FROM base as final
ENV PYTHONUNBUFFERED=1

RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        wget

WORKDIR /helloserver

# Grab packages from builder
COPY --from=builder /usr/local/lib/python3.* /usr/local/lib/

# Add the application
COPY . .

EXPOSE 8080
ENTRYPOINT [ "python", "server.py" ]

In dieser Datei sehen Sie Folgendes:

  • Die Anweisung FROM python:3-slim as base weist Docker an, das neueste Python 3-Image als Basis-Image zu verwenden.
  • Mit der Anweisung COPY . . werden die Quelldateien aus dem aktuellen Arbeitsverzeichnis (in diesem Fall server.py) in das Dateisystem des Containers kopiert.
  • ENTRYPOINT definiert die Anweisung, die zum Ausführen des Containers verwendet wird. In diesem Beispiel ähnelt die Anweisung derjenigen, mit der Sie server.py aus dem Quellcode ausgeführt haben.
  • Die Anweisung EXPOSE gibt an, dass server den Port 8080 überwacht. Mit dieser Anleitung werden keine Ports freigegeben. Sie dient jedoch als Dokumentation, die Sie beim Ausführen des Containers zum Öffnen von Port 8080 benötigen.

Containerisierung der Anwendung vorbereiten

Bevor Sie die Anwendung containerisieren, müssen Sie die Tools und Dienste einrichten, die Sie verwenden möchten:

  1. Legen Sie das Standard-Google Cloud-Projekt für die Google Cloud CLI fest:

    gcloud config set project PROJECT_ID
  2. Legen Sie die Standardregion für die Google Cloud CLI fest:

    gcloud config set compute/region us-central1
    

Repository erstellen

So erstellen Sie ein neues Repository für Docker-Container-Images in Artifact Registry:

  1. Achten Sie darauf, dass der Artifact Registry-Dienst in Ihrem Google Cloud-Projekt aktiviert ist.

    gcloud services enable artifactregistry.googleapis.com
    
    
  2. Erstellen Sie das Artifact Registry-Repository:

    gcloud artifacts repositories create container-intro --repository-format=docker \
        --location=us-central1 \
        --description="My new Docker repository" 
    
  3. Richten Sie die Authentifizierung von Docker zu Artifact Registry mit der Google Cloud CLI ein:

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

server containerisieren

Jetzt ist es an der Zeit, Ihre Anwendung zu containerisieren. Containerisieren Sie zuerst „Hallo Welt“ server und übertragen Sie das Image in die Artifact Registry:

  1. Wechseln Sie zu dem Verzeichnis, in dem sich das Beispiel server befindet:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. Erstellen Sie das Image mit der Dockerfile:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
    
    • Ersetzen Sie PROJECT_ID durch die ID Ihres Google Cloud-Projekts.

    Das Flag -t steht für das Docker-Tag. Dies ist der Name des Images, das Sie bei der Bereitstellung des Containers verwenden.

  3. Übertragen Sie das Image per Push an Artifact Registry.

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

loadgen containerisieren

Containerisieren Sie als Nächstes den Load-Generator-Dienst auf die gleiche Weise:

  1. Wechseln Sie zu dem Verzeichnis, in dem sich das Beispiel loadgen befindet:

    cd ../loadgen
    
  2. Erstellen Sie das Image:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
    
  3. Übertragen Sie das Image per Push an Artifact Registry.

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

Images auflisten

Rufen Sie eine Liste der Images im Repository ab, um zu bestätigen, dass die Images übertragen wurden:

gcloud container images list --repository us-central1-docker.pkg.dev/PROJECT_ID/container-intro

Die Ausgabe sollte die Namen der von Ihnen gepushten Images enthalten, ähnlich wie hier:

NAME
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen

GKE-Cluster erstellen

Sie können die Container jetzt mit dem Befehl docker run auf der Cloud Shell-VM ausführen. Wenn Sie jedoch zuverlässige Produktionsarbeitslasten ausführen möchten, müssen Sie Container einheitlich verwalten. Beispielsweise müssen Sie dafür sorgen, dass die Container bei einem Fehler neu gestartet werden. Außerdem müssen Sie zusätzliche Instanzen eines Containers horizontal und vertikal installieren können, um Traffic-Spitzen zu bewältigen.

GKE kann Ihnen dabei helfen, diese Anforderungen zu erfüllen. GKE ist eine Plattform zur Containerorchestrierung, die VMs mit einem Cluster verbindet. Jede VM wird als Knoten bezeichnet. GKE-Cluster basieren auf dem Open-Source-Clusterverwaltungssystem Kubernetes. Kubernetes bietet die Mechanismen, die eine Interaktion mit Ihrem Cluster ermöglichen.

Wenn Sie die Container in GKE ausführen möchten, müssen Sie zuerst einen Cluster erstellen und sich dann mit ihm verbinden:

  1. Erstellen Sie den Cluster:

    gcloud container clusters create-auto container-intro
    

    Mit dem Befehl gcloud wird im Standard-Google Cloud-Projekt und in der Standardregion, die Sie zuvor festgelegt haben, ein Cluster erstellt.

    Der Befehl zum Erstellen des Clusters dauert einige Minuten. Wenn der Cluster bereit ist, sieht die Ausgabe in etwa so aus:

     NAME: container-intro
     LOCATION: us-central1
     MASTER_VERSION: 1.30.4-gke.1348000
     MASTER_IP: 34.44.14.166
     MACHINE_TYPE: e2-small
     NODE_VERSION: 1.30.4-gke.1348000
     NUM_NODES: 3
     STATUS: RUNNING
    
  2. Geben Sie Anmeldedaten für das kubectl-Befehlszeilentool an, damit Sie es zum Verwalten des Clusters verwenden können:

    gcloud container clusters get-credentials container-intro
    

Kubernetes-Manifeste prüfen

Als Sie die Anwendung aus dem Quellcode ausgeführt haben, haben Sie einen imperativen Befehl verwendet: python3 server.py

Imperativ bedeutet in Verbform: „Tun Sie dies.“

Im Gegensatz dazu verwendet Kubernetes ein deklaratives Modell. Das bedeutet, dass Sie Kubernetes nicht genau mitteilen müssen, was zu tun ist, sondern Kubernetes einen gewünschten Status zuweisen. Beispielsweise werden Pods bei Kubernetes nach Bedarf gestartet und beendet, sodass der tatsächliche Systemstatus dem gewünschten Zustand entspricht.

Sie geben den gewünschten Status in einer Datei an, die als Manifest bezeichnet wird. Manifeste werden in Sprachen wie YAML oder JSON geschrieben und enthalten die Spezifikation für ein oder mehrere Kubernetes-Objekte.

Das Beispiel enthält jeweils ein Manifest für server und loadgen. Jedes Manifest gibt den gewünschten Status für das Kubernetes-Deployment-Objekt (das den Betrieb Ihres Containers verwaltet, der zur Verwaltung als Kubernetes-Pod verpackt ist) und den Dienst (der eine IP-Adresse für den Pod bereitstellt) an. Ein Pod ist die kleinste bereitstellbare Computingeinheit, die Sie in Kubernetes erstellen und verwalten können. Er enthält einen oder mehrere Container.

Das folgende Diagramm zeigt die in GKE ausgeführte Anwendung:

Containerisierte Anwendung, die auf GKE ausgeführt wird

Weitere Informationen zu Pods, Bereitstellungen und Diensten finden Sie unter Einstieg in Kubernetes oder in den Ressourcen am Ende dieser Seite.

Server

Sehen wir uns zuerst das Manifest für das „Hello World“-server an:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloserver
  template:
    metadata:
      labels:
        app: helloserver
    spec:
      containers:
      - image: gcr.io/google-samples/istio/helloserver:v0.0.1
        imagePullPolicy: Always
        name: main
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

Dieses Manifest enthält die folgenden Felder:

  • kind gibt den Typ des Objekts an.
  • metadata.name gibt den Namen des Deployments an.
  • Das erste spec-Feld enthält eine Beschreibung des gewünschten Status.
  • spec.replicas gibt die Anzahl der gewünschten Pods an.
  • Im Abschnitt spec.template wird eine Pod-Vorlage definiert. In der Spezifikation für die Pods ist das Feld image enthalten. Dies ist der Name des Images, das aus Artifact Registry abgerufen werden soll. Im nächsten Schritt aktualisieren Sie dies auf das neue Bild, das Sie gerade erstellt haben.

Der hellosvc-Dienst ist so definiert:

apiVersion: v1
kind: Service
metadata:
  name: hellosvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: helloserver
  type: LoadBalancer
  • LoadBalancer: Clients senden Anfragen an die IP-Adresse eines Netzwerk-Load-Balancers, der eine stabile IP-Adresse hat und außerhalb des Clusters erreichbar ist.
  • targetPort: Beachten Sie, dass der Befehl EXPOSE 8080 im Dockerfile keine Ports tatsächlich verfügbar macht. Sie stellen Port 8080 bereit, damit Sie den server-Container außerhalb des Clusters erreichen können. In diesem Fall wird hellosvc.default.cluster.local:80 (Kurzname: hellosvc) dem Port 8080 der helloserver-Pod-IP zugeordnet.
  • port: Dies ist die Portnummer, die andere Dienste im Cluster beim Senden von Anfragen verwenden.

Load-Generator

Das Deployment-Objekt in loadgen.yaml entspricht in etwa server.yaml. Ein großer Unterschied besteht darin, dass die Pod-Spezifikation für das loadgen-Deployment ein Feld namens env enthält. In diesem Abschnitt werden die Umgebungsvariablen loadgen definiert, die Sie zuvor festgelegt haben, als Sie die Anwendung aus der Quelle ausgeführt haben.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: loadgenerator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: loadgenerator
  template:
    metadata:
      labels:
        app: loadgenerator
    spec:
      containers:
      - env:
        - name: SERVER_ADDR
          value: http://hellosvc:80/
        - name: REQUESTS_PER_SECOND
          value: '10'
        image: gcr.io/google-samples/istio/loadgen:v0.0.1
        imagePullPolicy: Always
        name: main
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 300m
            memory: 256Mi
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

Da loadgen keine eingehenden Anfragen akzeptiert, ist das Feld type auf ClusterIP gesetzt. Dieser Diensttyp bietet eine stabile IP-Adresse, die von Entitäten im Cluster verwendet werden kann. Die IP-Adresse wird jedoch externen Clients nicht angezeigt.

apiVersion: v1
kind: Service
metadata:
  name: loadgensvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: loadgenerator
  type: ClusterIP

Container in GKE bereitstellen

Um die Container bereitzustellen, wenden Sie die Manifeste mit dem gewünschten Status mithilfe von kubectl an.

server bereitstellen

  1. Wechseln Sie zu dem Verzeichnis, in dem sich das Beispiel server befindet:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. Öffnen Sie server.yaml im Cloud Shell-Editor oder in Ihrem bevorzugten Texteditor.

  3. Ersetzen Sie den Namen im Feld image durch den Namen des Docker-Images.

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

    Ersetzen Sie PROJECT_ID durch Ihre Google Cloud-Projekt-ID.

    • Wenn Sie den Cloud Shell-Editor verwenden, wird die Datei automatisch gespeichert. Klicken Sie auf Terminal öffnen, um zum Terminalfenster zurückzukehren.
    • Wenn Sie in Cloud Shell einen Texteditor verwenden, speichern und schließen Sie server.yaml.
  4. Stellen Sie das Manifest in Kubernetes bereit:

    kubectl apply -f server.yaml
    

    Die Ausgabe sieht in etwa so aus:

    deployment.apps/helloserver created
    service/hellosvc created
    

loadgen bereitstellen

  1. Wechseln Sie zu dem Verzeichnis, in dem sich loadgen befindet.

    cd ../loadgen
    
  2. Öffnen Sie loadgen.yaml wie zuvor in einem Texteditor.

  3. Ersetzen Sie den Namen im Feld image noch einmal durch den Namen Ihres Docker-Images.

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

    Ersetzen Sie PROJECT_ID durch Ihre Google Cloud-Projekt-ID.

    • Wenn Sie den Cloud Shell-Editor verwenden, wird die Datei automatisch gespeichert. Klicken Sie auf Terminal öffnen, um zum Terminalfenster zurückzukehren.
    • Wenn Sie in Cloud Shell einen Texteditor verwenden, speichern und schließen Sie loadgen.yaml.
  4. Stellen Sie das Manifest in Ihrem Cluster bereit:

    kubectl apply -f loadgen.yaml
    

    Bei Erfolg gibt der Befehl Folgendes zurück:

    deployment.apps/loadgenerator created
    service/loadgensvc created
    

Deployment prüfen

Prüfen Sie nach der Bereitstellung Ihrer Manifeste im Cluster, ob Ihre Container erfolgreich bereitgestellt wurden:

  1. Prüfen Sie den Status der Pods in Ihrem Cluster:

    kubectl get pods
    

    Der Befehl antwortet mit einem Status wie diesem:

    NAME                             READY   STATUS    RESTARTS   AGE
    helloserver-69b9576d96-mwtcj     1/1     Running   0          58s
    loadgenerator-774dbc46fb-gpbrz   1/1     Running   0          57s
    
  2. Rufen Sie die Anwendungslogs aus dem Pod loadgen ab. Ersetzen Sie POD_ID durch die Pod-ID des Load Balancers aus der vorherigen Ausgabe.

    kubectl logs POD_ID
    
  3. Rufen Sie die externen IP-Adressen von hellosvc ab:

    kubectl get service hellosvc
    

    Die Ausgabe sieht in etwa so aus:

    NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    hellosvc     LoadBalancer   10.81.15.158   192.0.2.1       80:31127/TCP   33m
    
  4. Senden Sie eine Anfrage an hellosvc. Ersetzen Sie EXTERNAL_IP durch die externe IP-Adresse Ihrer hellosvc.

    curl http://EXTERNAL_IP
    

    Sie sollten vom Server die Meldung „Hello World!“ sehen.

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

Wenn Sie nicht das gesamte Projekt löschen möchten:

  • Löschen Sie den GKE-Cluster. Durch das Löschen des Clusters werden alle Ressourcen des Clusters gelöscht, darunter Compute Engine-Instanzen, Laufwerke und Netzwerkressourcen.

     gcloud container clusters delete container-intro
    
  • Löschen Sie das Artifact Registry-Repository:

     gcloud artifacts repositories delete container-intro --location=us-central1
    

Nächste Schritte