Container-Image-Digests in Kubernetes-Manifesten verwenden

Last reviewed 2021-01-08 UTC

In dieser Anleitung wird Entwicklern und Anbietern, die Container in Kubernetes bereitstellen, gezeigt, wie Container-Image-Digests zur Identifizierung von Container-Images verwendet werden können. Ein Container-Image-Digest identifiziert ein Container-Image eindeutig und unveränderlich.

Das Bereitstellen von Container-Images mithilfe des Image-Digest bietet im Vergleich zur Verwendung von Image-Tags mehrere Vorteile. Bevor Sie mit dieser Anleitung fortfahren, finden Sie weitere Informationen zu Image-Digests im zugehörigen Dokument zur Verwendung von Container-Image-Digests.

Das Argument image für Container in einer Kubernetes Pod-Spezifikation akzeptiert Images mit Digests. Dieses Argument wird überall dort angewendet, wo Sie eine Pod-Spezifikation verwenden, z. B. im Abschnitt template der Deployment-, StatefulSet-, DaemonSet-, ReplicaSet- und Jobressourcen.

Zur Bereitstellung eines Images mithilfe des Digest verwenden Sie den Image-Namen, gefolgt von @sha256: und dem Digest-Wert. Das folgende Beispiel zeigt eine Deployment-Ressource, die ein Image mit einem Digest verwendet:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
spec:
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
        ports:
        - containerPort: 8080

Ein Nachteil der Verwendung von Image-Digests ist, dass Sie den Digest-Wert erst kennen, wenn Sie das Image in einer Registry veröffentlicht haben. Wenn Sie neue Images erstellen, ändert sich der Digest-Wert und Sie müssen bei jeder Bereitstellung die Möglichkeit haben, Ihre Kubernetes-Manifeste zu aktualisieren.

In dieser Anleitung wird beschrieben, wie Sie Tools wieSkaffold, kpt, digester, kustomize, gke-deploy, ko und Bazel nutzen, um Image-Digests in Ihren Manifesten zu verwenden.

Empfehlungen

In diesem Dokument werden verschiedene Möglichkeiten zur Verwendung von Image-Digests in Kubernetes-Deployments vorgestellt. Die in diesem Dokument beschriebenen Tools ergänzen sich. Sie können beispielsweise die Ausgabe einer kpt-Funktion mit kustomize verwenden, um Varianten für verschiedene Umgebungen zu erstellen. Skaffold kann mit HBase Images erstellen und diese mit kpt oder Kustomize in Ihren Kubernetes-Clustern bereitstellen.

Die Tools ergänzen sich, weil sie strukturierte Änderungen auf der Grundlage des Kubernetes-Ressourcenmodells (KRM) vornehmen. Durch dieses Modell sind die Tools plugbar und Sie können Ihre Nutzung der Tools zum Erstellen von Prozessen und Pipelines verbessern, mit denen Sie Ihre Anwendungen und Dienste bereitstellen.

Wir empfehlen Ihnen für den Einstieg die Vorgehensweise, die am besten mit Ihren vorhandenen Tools und Prozessen funktioniert:

  • Wenn Sie das Digest-Tool als mutierenden Zulassungs-Webhook in Ihren Kubernetes-Clustern verwenden, können Sie allen Ihren Bereitstellungen Digests mit minimaler Auswirkung auf Ihre aktuellen Prozesse zum Erstellen und Bereitstellen von Container-Images hinzufügen. Der Digest-Webhook vereinfacht auch die Akzeptanz der Binärautorisierung, da nur ein Label zu einem Namespace hinzugefügt werden muss.

  • kpt ist eine gute Möglichkeit, wenn Sie ein flexibles Tool benötigen, um Kubernetes-Manifeste zu bearbeiten. Das Digest-Tool kann als clientseitige KRM-Funktion in einer kpt-Pipeline verwendet werden.

  • Skaffold kann zum Hinzufügen von Digests zu Image-Referenzen verwendet werden. Sie aktivieren diese Funktion mit einer kleinen Konfigurationsänderung. Die Verwendung von Skaffold bietet zusätzliche Vorteile, z. B. die Abstraktion, wie verschiedene Tools und Container-Images erstellen und bereitstellen.

  • Wenn Sie kustomize bereits für die Verwaltung von Kubernetes-Manifesten in verschiedenen Umgebungen verwenden, empfehlen wir Ihnen, die Image-Transformer zur Bereitstellung von Images nach Digest zu verwenden.

  • ko ist eine gute Möglichkeit, um Images für Go-Anwendungen zu erstellen und zu veröffentlichen. Es wird von Open-Source-Projekten wie Knative und Tekton und sigstore.verwendet.

  • Wenn Sie zum Erstellen von Anwendungen bereits Bazel verwenden, empfehlen wir Ihnen, den rules_docker-Regelsatz zum Erstellen von Images und den Regelsatz rules_k8s zum Ergänzen von Image-Digests in Ihren Kubernetes-Manifesten hinzufügen.

Wenn Sie keines der in diesem Dokument beschriebenen Tools verwenden, empfehlen wir, mit Skaffold und dem Digest-Webhook zu beginnen. Skaffold ist ein gängiges Tool, das von Entwicklern und Release-Teams verwendet wird und sich in die anderen Tools in dieser Anleitung integrieren lässt. Diese Integrationsoptionen können Sie nutzen, wenn sich Ihre Anforderungen ändern. Der Digest-Kubernetes-Webhook ergänzt Skaffold durch die Aktivierung von Digest-basierten Bereitstellungen für eine gesamte Organisation.

Ziele

  • Verwenden Sie Skaffold, um ein Image zu erstellen und per Push zu übertragen sowie den Image-Namen und den Digest in ein Kubernetes-Manifest einzufügen.
  • Mit kpt-Settern können Sie ein Image-Tag in einem Kubernetes-Manifest durch einen Image-Digest ersetzen.
  • Verwenden Sie die clientseitige Digest-Funktion und den mutierenden Zulassungs-Webhook, um Digests zu Images in Kubernetes-Pods und Pod-Vorlagen hinzuzufügen.
  • Verwenden Sie kustomize, um ein Kubernetes-Manifest mit einem Image-Digest zu generieren.
  • Verwenden Sie gke-deploy, um ein Image-Tag in einen Digest in einem Kubernetes-Manifest aufzulösen.
  • Verwenden Sie ko, um ein Image zu erstellen und per Push zu übertragen und den Image-Namen und das Digest in ein Kubernetes-Manifest einzufügen.
  • Mit Bazel können Sie ein Image erstellen und per Push übertragen und den Image-Namen und das Digest in ein Kubernetes-Manifest einfügen.

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweis

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  3. Container Registry API aktivieren.

    Aktivieren Sie die API

  4. Aktivieren Sie Cloud Shell in der Google Cloud Console.

    Cloud Shell aktivieren

Skaffold verwenden

Skaffold ist ein Befehlszeilentool für die kontinuierliche Entwicklung und Bereitstellung von Anwendungen auf Kubernetes-Clustern.

Verwenden Sie Skaffold, um ein Image zu erstellen, das Image per Push an Container Registry zu übertragen und den Platzhalterwert image in einer Kubernetes-Manifestvorlage durch den Namen, das Tag und den Digest des übertragenen Images zu ersetzen:

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/skaffold
    cd ~/container-image-digests-tutorial/skaffold
    
  2. Klonen Sie das Git-Repository für Skaffold:

    git clone https://github.com/GoogleContainerTools/skaffold.git
    
  3. Rufen Sie das Verzeichnis des Beispiels getting-started auf:

    cd skaffold/examples/getting-started
    
  4. Sehen Sie sich das Git-Tag an, das Ihrer Version von Skaffold entspricht:

    git checkout $(skaffold version)
    
  5. Sehen Sie sich die Konfigurationsdatei skaffold.yaml an:

    cat skaffold.yaml
    

    Die Datei sieht in etwa so aus:

    apiVersion: skaffold/v2beta26
    kind: Config
    build:
      artifacts:
      - image: skaffold-example
    deploy:
      kubectl:
        manifests:
          - k8s-*
    

    Der Abschnitt build.artifacts enthält den Image-Kontext, in diesem Fall einen Platzhalternamen. Skaffold sucht in den Eingabemanifestdateien nach diesem Platzhalter. In diesem Abschnitt legen Sie auch die Kontextverzeichnisse fest, die von Skaffold zum Erstellen von Images verwendet werden. Standardmäßig verwendet Skaffold das aktuelle Verzeichnis als Build-Kontext.

    Im Abschnitt deploy wird Skaffold angewiesen, Eingabemanifestdateien im aktuellen Verzeichnis zu lesen, deren Namen mit dem Muster k8s-* übereinstimmen, und gerenderte Manifeste mit kubectl apply bereitzustellen.

    Eine Übersicht über alle verfügbaren Optionen finden Sie in der Referenzdokumentation zu skaffold.yaml.

  6. Sehen Sie sich die Kubernetes-Manifestvorlage an:

    cat k8s-pod.yaml
    

    Dies ist die Datei:

    apiVersion: v1
    kind: Pod
    metadata:
      name: getting-started
    spec:
      containers:
      - name: getting-started
        image: skaffold-example
    

    Der Platzhalterwert skaffold-example im Feld image entspricht dem Wert des Felds image in der Datei skaffold.yaml. Skaffold ersetzt diesen Platzhalterwert durch den vollständigen Image-Namen und den Digest in der gerenderten Ausgabe.

  7. Erstellen Sie das Image und übertragen Sie es in die Container Registry:

    skaffold build \
        --default-repo=gcr.io/$(gcloud config get-value core/project) \
        --file-output=artifacts.json \
        --interactive=false \
        --push=true \
        --update-check=false
    

    Dieser Befehl verwendet die folgenden Flags:

    • Das Flag --file-output gibt die Datei an, in der Skaffold Informationen zum erstellten Image speichert, einschließlich des Digest-Werts.
    • Das Flag --push weist Skaffold an, das erstellte Image in die durch das Flag --default-repo angegebene Container-Image-Registry zu übertragen.
    • Die Flags --interactive und --update-check sind beide auf false gesetzt. Setzen Sie diese Flags in nicht interaktiven Umgebungen wie Build-Pipelines auf false, behalten Sie sie aber als Standardwerte (true für beide Flags) für die lokale Entwicklung bei.

    Wenn Sie für die Bereitstellung in GKE Google Cloud Deploy verwenden, verwenden Sie die Datei aus dem --file-output-Flag als Wert für das --build-artifacts-Flag, wenn Sie ein Release erstellen.

  8. Rendern Sie das erweiterte Kubernetes-Manifest mit dem Namen, dem Tag und dem Digest des Container-Images aus dem vorherigen Schritt:

    skaffold render \
        --build-artifacts=artifacts.json \
        --digest-source=none \
        --interactive=false \
        --offline=true \
        --output=rendered.yaml \
        --update-check=false
    

    Dieser Befehl verwendet die folgenden Flags:

    • Das Flag --build-artifacts verweist auf die Ausgabedatei aus dem Befehl skaffold build im vorherigen Schritt.
    • Das Flag --digest-source=none bedeutet, dass Skaffold den Digest-Wert aus der im Flag --build-artifacts angegebenen Datei verwendet, anstatt den Digest aus der Container Registry aufzulösen.
    • Das Argument --offline=true bedeutet, dass Sie den Befehl ausführen können, ohne Zugriff auf einen Kubernetes-Cluster zu benötigen.
    • Das Flag --output gibt die Ausgabedatei für das gerenderte Manifest an.
  9. Rufen Sie das gerenderte Manifest auf:

    cat rendered.yaml
    

    Die Ausgabe sollte so aussehen:

    apiVersion: v1
    kind: Pod
    metadata:
      name: getting-started
    spec:
      containers:
      - image: gcr.io/YOUR_PROJECT_ID/skaffold-example:TAG@sha256:DIGEST
        name: getting-started
    

    In dieser Ausgabe sehen Sie die folgenden Werte:

    • YOUR_PROJECT_ID: Ihre Cloud-Projekt-ID
    • TAG: das Tag, das dem Image vom Skaffold zugewiesen wurde.
    • DIGEST: der Wert des Image-Digests

kpt-Setter verwenden

kpt ist ein Befehlszeilentool zum Verwalten, Bearbeiten, Anpassen und Anwenden von Kubernetes-Ressourcenmanifesten

Sie können die KRM-Funktionen create-setters und apply-setters aus dem kpt Functions-Katalog verwenden, um beim Erstellen neuer Images Image-Digests in Ihren Kubernetes-Manifesten zu aktualisieren.

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/kpt
    cd ~/container-image-digests-tutorial/kpt
    
  2. Laden Sie kpt herunter:

    mkdir -p ${HOME}/bin
    curl -L https://github.com/GoogleContainerTools/kpt/releases/download/v1.0.0-beta.1/kpt_linux_amd64 --output ${HOME}/bin/kpt
    chmod +x ${HOME}/bin/kpt
    export PATH=${HOME}/bin:${PATH}
    
  3. Erstellen Sie ein kpt-Paket im aktuellen Verzeichnis:

    kpt pkg init --description "Container image digest tutorial"
    
  4. Erstellen Sie mit dem Tag 1.10 ein Kubernetes-Deployment-Manifest, das auf das Image gcr.io/google-containers/echoserver verweist:

    cat << EOF > pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10
        ports:
        - containerPort: 8080
    EOF
    
  5. Verwenden Sie kpt, um einen Setter namens echoimage für das Manifestfeld zu erstellen, wobei der vorhandene Wert gcr.io/google-containers/echoserver:1.10 ist:

    kpt fn eval . \
        --image gcr.io/kpt-fn/create-setters:v0.1@sha256:0220cc87f29ff9abfa3a3b5643aa50f18d355d5e9dc9e1f518119633ddc4895c \
        -- "echoimage=gcr.io/google-containers/echoserver:1.10"
    
  6. Rufen Sie die Anzeige des Manifests auf:

    cat pod.yaml
    

    Dies ist die Datei:

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10 # kpt-set: ${echoimage}
        ports:
        - containerPort: 8080
    
  7. Rufen Sie den Digest-Wert des Container-Images ab:

    DIGEST=$(gcloud container images describe \
        gcr.io/google-containers/echoserver:1.10 \
        --format='value(image_summary.digest)')
    
  8. Legen Sie den neuen Feldwert fest:

    kpt fn eval . \
        --image gcr.io/kpt-fn/apply-setters:v0.2@sha256:4d4295727183396f0c3c6a75d2560254c2f9041a39e95dc1e5beffeb49cc1a12 \
        -- "echoimage=gcr.io/google-containers/echoserver:1.10@$DIGEST"
    

    Wenn Sie diesen Befehl ausführen, führt kpt eine direkte Ersetzung des Feldwerts image im Manifest durch.

  9. Rufen Sie das aktualisierte Manifest auf:

    cat pod.yaml
    

    Dies ist die Datei:

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 # kpt-set: ${echoimage}
        ports:
        - containerPort: 8080
    

Digest verwenden

Digester fügt Digests zu Container- und init-Container-Images in Kubernetes-Pod- und Pod-Vorlagenspezifikationen hinzu. Digester ersetzt Container-Image-Referenzen, die Tags verwenden:

spec:
  containers:
  - image: gcr.io/google-containers/echoserver:1.10

Mit Verweisen, die den Image-Digest verwenden:

spec:
  containers:
  - image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

Digester kann entweder als mutierender Zulassungs-Webhook in einem Kubernetes-Cluster oder als clientseitige KRM-Funktion mit den kpt- oder kustomize-Befehlszeilentools ausgeführt werden.

Digest-KRM-Funktion verwenden

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/digester-fn
    cd ~/container-image-digests-tutorial/digester-fn
    
  2. Laden Sie die Digest-Binärdatei herunter:

    DIGESTER_VERSION=v0.1.7
    mkdir -p ${HOME}/bin
    curl -L "https://github.com/google/k8s-digester/releases/download/${DIGESTER_VERSION}/digester_$(uname -s)_$(uname -m)" --output ${HOME}/bin/digester
    chmod +x ${HOME}/bin/digester
    export PATH=${HOME}/bin:${PATH}
    
  3. Erstellen Sie mit dem Tag 1.10 ein Kubernetes-Deployment-Manifest, das auf das Image gcr.io/google-containers/echoserver verweist:

    cat << EOF > pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10
        ports:
        - containerPort: 8080
    EOF
    
  4. Führen Sie die Digester-KRM-Funktion mit kpt mit den Manifesten im aktuellen Verzeichnis (.) aus:

    kpt fn eval . --exec digester
    

    Wenn Sie diesen Befehl ausführen, führt kpt eine direkte Aktualisierung der Manifeste im aktuellen Verzeichnis durch. Wenn Sie möchten, dass kpt das aktualisierte Manifest in der Konsole anzeigt und die Manifestdatei unverändert lässt, fügen Sie das Flag --output unwrap hinzu.

  5. Rufen Sie das aktualisierte Manifest auf:

    cat pod.yaml
    

    Dies ist die Datei:

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
          ports:
            - containerPort: 8080
    

Digest-Zulassungs-Webhook verwenden

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/digester-webhook
    cd ~/container-image-digests-tutorial/digester-webhook
    
  2. Laden Sie Art herunter:

    KIND_VERSION=v0.11.1
    mkdir -p ${HOME}/bin
    curl -L "https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64" --output ${HOME}/bin/kind
    chmod +x ${HOME}/bin/kind
    export PATH=${HOME}/bin:${PATH}
    

    Art ist ein Befehlszeilentool zum Ausführen lokaler Kubernetes-Cluster mit Docker.

  3. Erstellen Sie einen lokalen Kubernetes-Cluster:

    kind create cluster
    
  4. Laden Sie das Digest-Webhook-kpt-Paket herunter und speichern Sie es in einem Verzeichnis mit dem Namen manifests:

    DIGESTER_VERSION=v0.1.7
    kpt pkg get https://github.com/google/k8s-digester.git/manifests@${DIGESTER_VERSION} manifests
    
  5. Stellen Sie den Digest-Webhook bereit:

    kpt live init manifests
    kpt live apply manifests --reconcile-timeout=3m --output=table
    
  6. Erstellen Sie einen Kubernetes-Namespace namens digester-demo im Typcluster:

    kubectl create namespace digester-demo
    
  7. Fügen Sie dem Namespace digester-demo das Label digest-resolution: enabled hinzu:

    kubectl label namespace digester-demo digest-resolution=enabled
    

    Der Digest-Webhook fügt Digests zu Pods in Namespaces mit diesem Label hinzu.

  8. Erstellen Sie mit dem Tag 1.10 ein Kubernetes-Deployment-Manifest, das auf das Image gcr.io/google-containers/echoserver verweist:

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-deployment
    spec:
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
        spec:
          containers:
          - name: echoserver
            image: gcr.io/google-containers/echoserver:1.10
            ports:
            - containerPort: 8080
    EOF
    
  9. Wenden Sie das Manifest im Namespace digester-demo an:

    kubectl apply --filename deployment.yaml --namespace digester-demo \
        --output jsonpath='{.spec.template.spec.containers[].image}{"\n"}'
    

    Das Flag --output weist kubectl an, den Image-Namen an die Konsole auszugeben, gefolgt von einem Zeilenumbruch. Die Ausgabe sieht so aus:

    gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
    

    Diese Ausgabe zeigt, dass der Digest-Webhook den Image-Digest der Pod-Vorlagenspezifikation in der Deployment-Ressource hinzugefügt hat.

  10. Löschen Sie den Typcluster, um Ressourcen in der Cloud Shell-Sitzung freizugeben:

    kind delete cluster
    

kustomize-Image-Transformer verwenden

kustomize ist ein Befehlszeilentool, mit dem Sie Kubernetes-Manifeste mithilfe von Overlays, Patches und Transformern anpassen können.

Sie können den kustomize-Image-Transformer nutzen, um den Image-Namen, das Tag und den Digest in Ihrem vorhandenen Manifest zu aktualisieren.

Das folgende kustomization.yaml-Snippet zeigt, wie Sie den Image-Transformer konfigurieren, um den Wert digest des Transformers für Images zu verwenden, bei denen der Wert der Pod-Spezifikation image dem Wert name des Transformers entspricht:

images:
- name: gcr.io/google-containers/echoserver
  digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

So verwenden Sie einen kustomize-Image-Transformer mit einem Image-Digest:

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/kustomize
    cd ~/container-image-digests-tutorial/kustomize
    
  2. kustomization.yaml-Datei erstellen:

    kustomize init
    
  3. Erstellen Sie ein Kubernetes-Manifest mit einer Pod-Spezifikation, die auf das Image gcr.io/google-containers/echoserver mithilfe des Tags 1.10 verweist:

    cat << EOF > pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver:1.10
        ports:
        - containerPort: 8080
    EOF
    
  4. Fügen Sie das Manifest als Ressource zur Datei kustomization.yaml hinzu:

    kustomize edit add resource pod.yaml
    
  5. Aktualisieren Sie den Image-Digest mit einem Image-Transformer:

    kustomize edit set image \
        gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
    
  6. Sehen Sie sich den Image-Transformer in der Datei kustomization.yaml an:

    cat kustomization.yaml
    

    Dies ist die Datei:

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
    - pod.yaml
    images:
    - digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
      name: gcr.io/google-containers/echoserver
    
  7. Sehen Sie sich das resultierende Manifest an:

    kustomize build .
    

    Die Ausgabe sieht so aus:

    apiVersion: v1
    kind: Pod
    metadata:
      name: echo
    spec:
      containers:
      - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
        name: echoserver
        ports:
        - containerPort: 8080
    
  8. Sie können kubectl apply mit dem Flag --kustomize verwenden, um das resultierende Manifest auf einen Kubernetes-Cluster anzuwenden:

    kubectl apply --kustomize .
    

    Wenn Sie die Ausgabe später anwenden möchten, können Sie die Ausgabe des Befehls kustomize build an eine Datei weiterleiten. Kustomize hat weitere Funktionen, die in diesem Dokument nicht behandelt werden. Weitere Informationen finden Sie in der kustomize-Dokumentation. Kustomize ist auch als Community Builder-Image von Cloud Build verfügbar.

gke-deploy verwenden

gke-deploy ist ein Befehlszeilentool, das Sie mit Google Kubernetes Engine (GKE) verwenden können. gke-deploy umschließt das kubectl-Befehlszeilentool und kann die Ressourcen ändern, die Sie gemäß den von Google empfohlenen Praktiken erstellen.

Wenn Sie die gke-deploy-Unterbefehle prepare oder run verwenden, löst gke-deploy die Image-Tags in Digests auf und speichert die erweiterten Manifeste mit den Image-Digests standardmäßig in der Datei output/expanded/aggregated-resources.yaml.

Sie können gke-deploy run verwenden, um das Image-Tag für einen Digest zu ersetzen und das erweiterte Manifest auf Ihren GKE-Cluster anzuwenden. Dieser Befehl ist zwar praktisch, hat aber auch einen Nachteil: Das Image-Tag wird bei der Bereitstellung ersetzt. Das mit dem Tag verknüpfte Image kann sich zwischen dem Zeitpunkt, an dem Sie sich für ein Deployment entschieden haben, und dem eigentlichen Deployment-Zeitpunkt geändert haben, wodurch ein unerwartetes Image bereitgestellt wird. Bei Produktions-Deployments empfehlen wir separate Schritte zum Generieren und Anwenden von Manifesten.

So ersetzen Sie ein Image-Tag in einem Kubernetes-Deployment-Manifest durch das Image-Digest:

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/gke-deploy
    cd ~/container-image-digests-tutorial/gke-deploy
    
  2. Installieren Sie gke-deploy:

    go install github.com/GoogleCloudPlatform/cloud-builders/gke-deploy@latest
    
  3. Erstellen Sie mit dem Tag 1.10 ein Kubernetes-Deployment-Manifest, das auf das Image gcr.io/google-containers/echoserver verweist:

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-deployment
    spec:
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
        spec:
          containers:
          - name: echoserver
            image: gcr.io/google-containers/echoserver:1.10
            ports:
            - containerPort: 8080
    EOF
    
  4. Generieren Sie auf Basis des Manifests deployment.yaml ein erweitertes Manifest:

    gke-deploy prepare \
        --filename deployment.yaml \
        --image gcr.io/google-containers/echoserver:1.10 \
        --version 1.10
    
  5. Rufen Sie das erweiterte Manifest auf:

    cat output/expanded/aggregated-resources.yaml
    

    Die Ausgabe sieht so aus:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/managed-by: gcp-cloud-build-deploy
        app.kubernetes.io/version: "1.10"
      name: echo-deployment
      namespace: default
    spec:
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
            app.kubernetes.io/managed-by: gcp-cloud-build-deploy
            app.kubernetes.io/version: "1.10"
        spec:
          containers:
          - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
            name: echoserver
            ports:
            - containerPort: 8080
    

    Im erweiterten Manifest wird das Image-Tag durch den Digest ersetzt.

    Das Argument --version, das Sie mit dem Befehl gke-deploy verwendet haben, legt den Wert des empfohlenen app.kubernetes.io/version-Labels im Deployment und die Metadaten der Pod-Vorlage der erweiterten Manifestdatei fest.

    Das gke-deploy-Tool ist auch als vordefiniertes Image für Cloud Build verfügbar. Informationen zur Verwendung von gke-deploy mit Cloud Build finden Sie in der Cloud Build-Dokumentation für gke-deploy.

ko verwenden

ko ist ein Befehlszeilentool zum Erstellen von Go-Container-Images und für das entsprechende Deployment in Kubernetes-Clustern. ko erstellt Images ohne den Docker-Daemon, damit Sie es in Umgebungen verwenden können, in denen Sie Docker nicht installieren können.

Mit dem ko-Unterbefehl publish werden Images erstellt und in einer Container Registry veröffentlicht oder in den lokalen Docker-Daemon geladen.

Der ko-Unterbefehl resolve führt Folgendes aus:

  • Ermittelt die Images, die erstellt werden sollen. Dazu werden in den image-Feldern der Kubernetes-Manifeste, die Sie mit dem Argument --filename angeben, Platzhalter gesucht.
  • Erstellt und veröffentlicht Images.
  • Ersetzt die Platzhalterwerte des Typs image durch die Namen und Digests der erstellten Images.
  • Gibt die erweiterten Manifeste aus.

Die ko-Unterbefehle apply, create und run führen dieselben Schritte wieresolve und anschließend kubectl apply, create oderrun mit den erweiterten Manifesten aus.

So erstellen Sie ein Image aus dem Go-Quellcode und fügen den Digest des Images einem Kubernetes-Deployment-Manifest hinzu:

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/ko
    cd ~/container-image-digests-tutorial/ko
    
  2. Laden Sie ko herunter und fügen Sie es Ihrem PATH hinzu:

    mkdir -p ${HOME}/bin
    curl -L https://github.com/google/ko/releases/download/v0.9.3/ko_0.9.3_$(uname -s)_$(uname -m).tar.gz | tar -zxC ${HOME}/bin ko
    export PATH=${HOME}/bin:${PATH}
    
  3. Erstellen Sie eine Go-Anwendung mit dem Modulnamen example.com/hello-world in einem neuen Verzeichnis namens app:

    mkdir -p app/cmd/ko-example
    
    cd app
    
    go mod init example.com/hello-world
    
    cat << EOF > cmd/ko-example/main.go
    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("hello world")
    }
    EOF
    
  4. Legen Sie das Image-Repository fest, mit dem ko Images veröffentlicht:

    export KO_DOCKER_REPO=gcr.io/$(gcloud config get-value core/project)
    

    In diesem Beispiel wird Container Registry verwendet. Sie können aber auch eine andere Registry verwenden.

  5. Führen Sie einen der folgenden Schritte aus, um ein Image für Ihre Anwendung zu erstellen und zu veröffentlichen:

    • Erstellen und veröffentlichen Sie ein Image für Ihre Anwendung. Geben Sie dazu den Pfad zu Ihrem Go-Hauptpaket an:

      ko publish --base-import-paths ./cmd/ko-example
      

      Das optionale Argument --base-import-paths bedeutet, dass ko den Kurznamen des Hauptpaketverzeichnisses als Image-Namen verwendet.

      ko gibt den Image-Namen und den Digest in stdout im folgenden Format aus:

      gcr.io/YOUR_PROJECT_ID/ko-example@sha256:DIGEST_VALUE
      

      In dieser Ausgabe gilt:

      • YOUR_PROJECT_ID: Ihre Cloud-Projekt-ID
      • DIGEST_VALUE: Wert des Image-Digests
    • Verwenden Sie ko, um einen Manifest-Platzhalter durch den Namen und Digest des Images zu ersetzen, das erstellt und veröffentlicht wird:

      1. Erstellen Sie ein Kubernetes-Pod-Manifest. Im Manifest wird der Platzhalter ko://IMPORT_PATH_OF_YOUR_MAIN_PACKAGE als Wert für das Feld image verwendet:

        cat << EOF > ko-pod.yaml
        apiVersion: v1
        kind: Pod
        metadata:
          name: ko-example
        spec:
          containers:
          - name: hello-world
            image: ko://example.com/hello-world/cmd/ko-example
        EOF
        
      2. Verwenden Sie ko resolve, um ein Image für Ihre Anwendung zu erstellen und zu veröffentlichen. Ersetzen Sie dann den Manifestplatzhalter durch den Image-Namen und den Digest:

        ko resolve --base-import-paths --filename ko-pod.yaml
        

        ko gibt das Manifest mit dem Image-Namen und dem Digest an stdout aus:

        apiVersion: v1
        kind: Pod
        metadata:
          name: ko-example
        spec:
          containers:
          - name: hello-world
            image: gcr.io/YOUR_PROJECT_ID/ko-example@sha256:DIGEST
        

        In dieser Ausgabe gilt:

        • YOUR_PROJECT_ID: Ihre Cloud-Projekt-ID
        • DIGEST: der Wert des Image-Digests

Bazel verwenden

Bazel ist ein Open-Source-Build-Tool in mehreren Sprachen, das auf dem internen Blaze-Build-System von Google basiert.

rules_docker ist ein Bazel-Regelsatz zum Erstellen und Übertragen von Container-Images. Die Regeln erstellen reproduzierbare Images, ohne den Docker-Daemon zu verwenden. Das Caching von Bazel kann das Erstellen und Übertragen von Images an Registries beschleunigen.

rules_k8s ist ein Bazel-Regelsatz für die Arbeit mit Kubernetes-Manifesten und -Clustern.

So erstellen Sie ein Image und übertragen es mit einem Push-Vorgang, um ein Kubernetes-Manifest durch den Image-Digest zu ergänzen:

  1. Erstellen Sie in Cloud Shell ein Verzeichnis und rufen Sie es auf, um die in diesem Bereich erstellten Dateien zu speichern:

    mkdir -p ~/container-image-digests-tutorial/bazel
    cd ~/container-image-digests-tutorial/bazel
    
  2. Git-Repository rules_k8s klonen

    git clone https://github.com/bazelbuild/rules_k8s.git
    
  3. Rufen Sie das Git-Repository-Verzeichnis auf:

    cd rules_k8s
    
  4. Prüfen Sie ein Git-Tag:

    git checkout v0.6
    
  5. Ersetzen Sie in der Datei WORKSPACE den Namen des Basis-Image-Repositorys, das Bazel zum Hochladen von Images mit einem Repository verwendet, in dem Sie Berechtigungen zum Übertragen von Images haben:

    sed -i~ "s/image_chroot.*/image_chroot = \"gcr.io\/$(gcloud config get-value core\/project)\",/" WORKSPACE
    

    In diesem Beispiel wird Container Registry verwendet. Sie können aber auch eine andere Registry verwenden.

  6. Installieren Sie die Bazel-Version für die Verwendung mit dem Build:

    sudo apt-get install -y bazel-$(cat .bazelversion)
    
  7. Korrigieren Sie das Feld apiVersion in der beispielhaften Manifestvorlage für das Kubernetes-Deployments:

    sed -i~ 's/v1beta1/v1/' examples/hellohttp/deployment.yaml
    
  8. Sehen Sie sich die Manifestvorlage für das Kubernetes-Deployment an:

    cat examples/hellohttp/deployment.yaml
    

    Dies ist die Datei:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-http-staging
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: hello-http-staging
        spec:
          containers:
          - name: hello-http
            image: hello-http-image:latest
            imagePullPolicy: Always
            ports:
            - containerPort: 8080
    
  9. Erstellen Sie das Java-Image für das Beispiel hellohttp, übertragen Sie es per Push an Container Registry und ersetzen Sie den Wert image in der Deployment-Manifestvorlage von Kubernetes durch den Namen und Digest des übertragenen Images. Leiten Sie die Ausgabe stdout weiter, um das erweiterte Manifest in einer neuen Datei mit dem Namen deployment.yaml.out zu erfassen:

    bazel --output_user_root=/tmp/bazel \
        run //examples/hellohttp/java:staging > deployment.yaml.out
    

    Die Ausführung dieses Befehls dauert einige Minuten, da er die Regelsätze, Compiler und Abhängigkeiten herunterlädt.

    Das Argument --output_user_root weist Bazel an, ein temporäres Verzeichnis außerhalb des Basisverzeichnisses für den laufwerksbasierten Cache zu verwenden. Dieses temporäre Verzeichnis ist in Cloud Shell erforderlich, damit Ihr Basisverzeichnis nicht überfüllt wird.

  10. Rufen Sie das erweiterte Manifest auf:

    cat deployment.yaml.out
    

    Die Datei sieht in etwa so aus:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-http-staging
    spec:
      replicas: 1
      template:
        metadata:
          labels:
            app: hello-http-staging
        spec:
          containers:
          - image: gcr.io/YOUR_PROJECT_ID/hello-http-image@sha256:b9d0a4643e9f11efe7cd300dd219ad691077ddfaccc118144cd83b7c472a8e86
            imagePullPolicy: Always
            name: hello-http
            ports:
            - containerPort: 8080
    
  11. Sehen Sie sich das von Bazel per Push übertragene Image an:

    gcloud container images describe \
        gcr.io/$(gcloud config get-value core/project)/hello-http-image
    

Bereinigen

Am einfachsten können Sie weitere Kosten vermeiden, wenn Sie das Cloud-Projekt löschen, das Sie für die Anleitung erstellt haben. Alternativ haben Sie die Möglichkeit, die einzelnen Ressourcen zu löschen.

Projekt löschen

  1. Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Ressourcen löschen

Wenn Sie das in dieser Anleitung verwendete Cloud-Projekt beibehalten möchten, löschen Sie die einzelnen Ressourcen:

  1. Löschen Sie die Images in Container Registry:

    for IMG in hello-http-image ko-example skaffold-example ; do \
        gcloud container images list-tags \
            gcr.io/$(gcloud config get-value core/project)/$IMG \
            --format 'value(digest)' | xargs -I {} gcloud container images \
            delete --force-delete-tags --quiet \
            gcr.io/$(gcloud config get-value core/project)/$IMG@sha256:{}
    done
    
  2. Löschen Sie die Dateien, die Sie in dieser Anleitung erstellt haben:

    cd
    rm -rf ~/container-image-digests-tutorial
    

Nächste Schritte