Fehlerbehebung

Hier finden Sie Informationen zur Fehlerbehebung, die bei Problemen mit Google Kubernetes Engine (GKE) hilfreich sein können.

Kubernetes-Ressourcen debuggen

Wenn bei Ihrem Cluster ein Problem auftritt, lesen Sie den Abschnitt Fehlerbehebung bei Clustern in der Kubernetes-Dokumentation.

Falls bei Ihrer Anwendung, den zugehörigen Pods oder dem Controllerobjekt ein Problem auftritt, lesen Sie die Fehlerbehebung für Anwendungen.

Befehl kubectl wurde nicht gefunden

  1. Installieren Sie die Binärdatei kubectl mit dem folgenden Befehl:

    sudo gcloud components update kubectl
    
  2. Antworten Sie mit "yes" (Ja), wenn das Installationsprogramm Sie dazu auffordert, Ihre Umgebungsvariable $PATH zu ändern. Durch die Änderung dieser Variablen können Sie kubectl-Befehle verwenden, ohne den vollständigen Dateipfad eingeben zu müssen.

    Alternativ können Sie in ~/.bashrc (oder ~/.bash_profile unter macOS oder am jeweiligen Speicherort für Umgebungsvariablen in der verwendeten Shell) die folgende Zeile hinzufügen:

    export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
    
  3. Führen Sie den folgenden Befehl aus, um die aktualisierte Datei .bashrc oder .bash_profile zu laden:

    source ~/.bashrc
    

kubectl-Befehle geben den Fehler "Verbindung verweigert" aus

Legen Sie den Clusterkontext mit folgendem Befehl fest:

gcloud container clusters get-credentials cluster-name

Wenn Sie nicht sicher sind, welchen Wert Sie für cluster-name eingeben sollen, können Sie den folgenden Befehl verwenden, um die vorhandenen Cluster aufzulisten:

gcloud container clusters list

kubectl-Befehle geben den Fehler "Es konnte keine API-Version festgelegt werden" aus

Achten Sie darauf, dass kubectl über die Anmeldedaten für die Authentifizierung verfügt:

gcloud auth application-default login

Die Befehle kubectl logs, attach, exec und port-forward reagieren nicht mehr

Diese Befehle sind davon abhängig, dass die Cluster-Steuerungsebene (Master) mit den Knoten im Cluster kommunizieren kann. Da sich die Steuerungsebene jedoch nicht im gleichen Compute Engine-Netzwerk befindet wie die Knoten des Clusters, sind wir für eine sichere Kommunikation auf SSH-Tunnel angewiesen.

GKE speichert eine Datei mit dem öffentlichen SSH-Schlüssel in den Metadaten Ihres Compute Engine-Projekts. Alle Compute Engine-VMs, die von Google bereitgestellte Images verwenden, prüfen regelmäßig die allgemeinen Metadaten ihres Projekts und die Instanzmetadaten auf SSH-Schlüssel, um diese der Liste mit autorisierten Nutzern der VM hinzuzufügen. GKE fügt dem Compute Engine-Netzwerk außerdem eine Firewallregel hinzu, mit der der SSH-Zugriff von der IP-Adresse der Steuerungsebene auf jeden Knoten im Cluster möglich ist.

Wenn einer der oben aufgeführten kubectl-Befehle nicht funktioniert, kann der API-Server wahrscheinlich keine SSH-Tunnel zu den Knoten öffnen. Prüfen Sie folgenden möglichen Ursachen:

  1. Der Cluster hat keine Knoten.

    Wenn Sie die Anzahl der Knoten in Ihrem Cluster bis auf null reduziert haben, funktionieren SSH-Tunnel nicht.

    Passen Sie die Größe Ihres Clusters an, um das Problem zu beheben. Es muss mindestens ein Knoten vorhanden sein.

  2. Die Pods im Cluster hängen im Abbruchstatus fest und verhindern, dass nicht mehr existierende Knoten aus dem Cluster entfernt werden.

    Dieses Problem sollte nur in Kubernetes-Version 1.1 auftreten, könnte aber auch durch wiederholte Anpassungen der Clustergröße verursacht werden.

    Löschen Sie Pods, die länger als einige Minuten im Abbruchstatus sind, um das Problem zu beheben. Die alten Knoten werden dann aus der Steuerungsebene entfernt und durch die neuen Knoten ersetzt.

  3. Die Firewallregeln Ihres Netzwerks lassen keinen SSH-Zugriff auf die Steuerungsebene zu.

    Alle Compute Engine-Netzwerke werden mit einer Firewallregel mit dem Namen default-allow-ssh erstellt, die den SSH-Zugriff über alle IP-Adressen ermöglicht (erfordert selbstverständlich einen gültigen privaten Schlüssel). Von GKE wird darüber hinaus für jeden öffentlichen Cluster eine SSH-Regel der Form gke-cluster-name-random-characters-ssh eingefügt, mit der der SSH-Zugriff speziell von der Steuerungsebene des Clusters auf dessen Knoten möglich ist. Wenn keine dieser Regeln vorhanden ist, kann die Steuerungsebene keine SSH-Tunnel öffnen.

    Fügen Sie zum Beheben des Problems noch einmal eine Firewallregel hinzu, die den Zugriff auf VMs mit dem Tag ermöglicht, das sich auf allen Clusterknoten von der IP-Adresse der Steuerungsebene befindet.

  4. Der allgemeine Metadateneintrag Ihres Projekts für "ssh-keys" ist voll.

    Wenn der Metadateneintrag "ssh-keys" des Projekts nahe der maximalen Größe liegt, kann GKE keinen eigenen SSH-Schlüssel hinzufügen, um SSH-Tunnel zu öffnen. Sie können die Metadaten Ihres Projekts mit dem folgenden Befehl aufrufen:

    gcloud compute project-info describe [--project=PROJECT]
    

    Prüfen Sie dann die Länge der Liste "ssh-keys".

    Löschen Sie zum Beheben dieses Problems einige SSH-Schlüssel, die nicht mehr benötigt werden.

  5. Sie haben auf den VMs im Cluster für ein Metadatenfeld den Schlüssel „ssh-keys“ festgelegt.

    Der Knoten-Agent auf VMs bevorzugt pro Instanz zugewiesene SSH-Schlüssel gegenüber projektweiten SSH-Schlüsseln. Wenn Sie also speziell auf den Clusterknoten SSH-Schlüssel eingerichtet haben, dann wird der SSH-Schlüssel der Steuerungsebene in den Projektmetadaten von den Knoten nicht beachtet. Führen Sie zum Prüfen gcloud compute instances describe <VM-name> aus und suchen Sie in den Metadaten nach dem Feld „ssh-keys“.

    Löschen Sie zum Beheben des Problems die pro Instanz zugewiesenen SSH-Schlüssel aus den Instanzmetadaten.

Es sollte beachtet werden, dass diese Funktionen nicht für ein korrektes Funktionieren des Clusters erforderlich sind. Wenn Sie es vorziehen, Ihr Clusternetzwerk für alle externen Zugriffe zu sperren, können Sie Funktionen wie diese nicht mehr verwenden.

Knotenversion ist nicht mit Version der Steuerungsebene kompatibel.

Sehen Sie nach, welche Version von Kubernetes auf der Steuerungsebene Ihres Clusters ausgeführt wird, und prüfen Sie dann, welche Kubernetes-Version die Knotenpools des Clusters ausführt. Wenn einer der Knotenpools eines Clusters mehr als zwei Nebenversionen älter als die Steuerungsebene ist, kann dies zu Problemen mit Ihrem Cluster führen.

Das GKE-Team führt regelmäßig Upgrades der Cluster-Steuerungsebene in Ihrem Namen durch. Steuerebenen werden auf neuere stabile Versionen von Kubernetes aktualisiert. Für die Knoten eines Clusters ist standardmäßig das automatische Upgrade aktiviert. Wir empfehlen, dies nicht zu deaktivieren.

Wenn die automatischen Upgrades für die Knoten eines Clusters deaktiviert sind und Sie die Knotenpoolversion nicht manuell auf eine Version aktualisieren, die mit der Steuerungsebene kompatibel ist, wird Ihre Steuerungsebene nicht mehr mit Ihren Knoten kompatibel sein, da die Steuerungsebene im Laufe der Zeit automatisch aktualisiert wird. Inkompatibilität zwischen der Steuerungsebene des Clusters und den Knoten kann zu unerwarteten Problemen führen.

Die Supportrichtlinie für Kubernetes-Versionen und Versionsinkompatibilität sorgt dafür, dass Steuerungsebenen mit Knoten kompatibel sind, die bis zu zwei Nebenversionen älter sind als die Steuerungsebene. Die Steuerungsebenen von Kubernetes 1.19 sind beispielsweise mit Kubernetes 1.19-, 1.18- und 1.17-Knoten kompatibel. Aktualisieren Sie die Knotenpoolversion auf eine Version, die mit der Steuerungsebene kompatibel ist, um dieses Problem zu beheben.

Wenn Sie befürchten, dass der Upgradeprozess zu Arbeitslasten führt, die auf den betroffenen Knoten ausgeführt werden, folgen Sie den Schritten im Abschnitt "Arbeitslasten migrieren" der Anleitung Arbeitslasten zu anderen Maschinentypen migrieren. Mit diesen Schritten können Sie ordnungsgemäß migrieren, indem Sie einen neuen Knotenpool erstellen und dann den alten Knotenpool sperren und leeren.

Messwerte aus Ihrem Cluster werden nicht in Cloud Monitoring angezeigt

Achten Sie darauf, dass Sie die Cloud Monitoring API und die Cloud Logging API in Ihrem Projekt aktiviert haben und Sie das Projekt in Cloud Monitoring aufrufen können.

Wenn das Problem weiterhin besteht, prüfen Sie folgende mögliche Ursachen:

  1. Vergewissern Sie sich, dass Sie das Monitoring für Ihren Cluster aktiviert haben.

    Monitoring ist standardmäßig für Cluster aktiviert, die über die Google Cloud Console und das gcloud-Befehlszeilentool erstellt wurden. Zur Prüfung können Sie den folgenden Befehl ausführen oder in der Cloud Console auf die Clusterdetails klicken:

    gcloud container clusters describe cluster-name
    

    Die Ausgabe dieses Befehls sollte angeben, dass "monitoringService" "monitoring.googleapis.com" lautet, und Cloud Monitoring sollte in der Cloud Console aktiviert sein.

    Aktiveren Sie das Monitoring gegebenenfalls mithilfe des folgenden Befehls:

    gcloud container clusters update cluster-name --monitoring-service=monitoring.googleapis.com
    
  2. Wie lange ist es her, dass Ihr Cluster erstellt oder das Monitoring aktiviert wurde?

    Es kann bis zu einer Stunde dauern, bis die Messwerte eines neuen Clusters in Cloud Monitoring angezeigt werden.

  3. Wird in Ihrem Cluster im Namespace "kube-system" ein heapster oder gke-metrics-agent (der OpenTelemetry Collector) ausgeführt?

    Unter Umständen kann der Pod keine Arbeitslasten planen, weil die Ressourcen im Cluster zur Neige gehen. Prüfen Sie, ob Heapster oder OpenTelemetry ausgeführt wird. Rufen Sie dazu kubectl get pods --namespace=kube-system auf und suchen Sie nach Pods mit heapster oder gke-metrics-agent im Namen.

  4. Kann Ihre Cluster-Steuerungsebene mit den Knoten kommunizieren?

    Dies ist entscheidend für die Funktion von Cloud Monitoring. Mit dem folgenden Befehl können Sie prüfen, ob dies der Fall ist:

    kubectl logs pod-name
    

    Wenn dieser Befehl einen Fehler zurückgibt, wird das Problem möglicherweise von den SSH-Tunnels verursacht. Weitere Informationen finden Sie in diesem Abschnitt.

Wenn ein Problem mit dem Cloud Logging-Agent besteht, lesen Sie die Dokumentation zur Fehlerbehebung.

Weitere Informationen finden Sie in der Dokumentation zu Logging.

Fehler 404: Ressource "nicht gefunden" nach Aufrufen von gcloud container-Befehlen

Führen Sie eine erneute Authentifizierung beim gcloud-Befehlszeilentool durch:

gcloud auth login

Fehler 400/403: Dem Konto fehlen Bearbeitungsberechtigungen

Ihr Compute Engine-Standarddienstkonto oder das GKE zugeordnete Dienstkonto wurde manuell gelöscht oder bearbeitet.

Wenn Sie die Compute Engine API oder die Kubernetes Engine API aktivieren, wird ein Dienstkonto mit Bearbeitungsberechtigungen für Ihr Projekt erstellt. Falls Sie die Berechtigungen bearbeiten, die Rolle "Kubernetes Engine-Dienst-Agent" entfernen, das Konto vollständig entfernen oder die API deaktivieren, schlagen das Erstellen des Clusters und sämtliche Verwaltungsfunktionen fehl.

Der Name Ihres Google Kubernetes Engine-Dienstkontos lautet folgendermaßen, wobei project-number Ihre Projektnummer ist:

service-project-number@container-engine-robot.iam.gserviceaccount.com

Falls Sie die Rolle Kubernetes Engine-Dienst-Agent aus Ihrem Google Kubernetes Engine-Dienstkonto entfernt haben, fügen Sie sie wieder hinzu, um das Problem zu beheben. Andernfalls müssen Sie die Kubernetes Engine API wieder aktivieren, damit die Dienstkonten und Berechtigungen korrekt wiederhergestellt werden. Dies ist mit dem gcloud-Tool oder in der Cloud Console möglich.

Console

  1. Rufen Sie in der Cloud Console die Seite APIs & Dienste auf.

    Seite "APIs & Dienste"

  2. Wählen Sie Ihr Projekt aus.

  3. Klicken Sie auf APIs und Dienste aktivieren.

  4. Suchen Sie "Kubernetes" und wählen Sie anschließend in den Suchergebnissen die API aus.

  5. Klicken Sie auf Aktivieren. Wenn Sie die API bereits aktiviert hatten, deaktivieren Sie sie und aktivieren Sie sie dann noch einmal. Es kann einige Minuten dauern, bis die API und zugehörige Dienste aktiviert werden.

gcloud

Führen Sie den folgenden Befehl im gcloud-Tool aus:

gcloud services enable container.googleapis.com

Automatische Firewallregeln für 1.8.x (und früher) auf 1.9.x und später replizieren

Wenn auf Ihrem Cluster Kubernetes Version 1.9.x ausgeführt wird, wurden die automatischen Firewallregeln so geändert, dass von Arbeitslasten in einem GKE-Cluster keine Kommunikation mit anderen Compute Engine-VMs mehr gestartet werden kann, die sich außerhalb des Clusters, aber im selben Netzwerk befinden.

Sie können das Verhalten der automatischen Firewallregeln eines Clusters mit 1.8.x (und früher) replizieren. Führen Sie dazu die folgenden Schritte aus:

  1. Suchen Sie das Netzwerk Ihres Clusters:

    gcloud container clusters describe cluster-name --format=get"(network)"
    
  2. Rufen Sie die IPv4-CIDR des Clusters ab, die für die Container verwendet wird:

    gcloud container clusters describe cluster-name --format=get"(clusterIpv4Cidr)"
    
  3. Erstellen Sie eine Firewallregel für das Netzwerk mit der CIDR als Quellbereich und lassen Sie alle Protokolle zu:

    gcloud compute firewall-rules create "cluster-name-to-all-vms-on-network" \
      --network="network" --source-ranges="cluster-ipv4-cidr" \
      --allow=tcp,udp,icmp,esp,ah,sctp
    

Standarddienstkonto für Ihr GCP-Projekt wiederherstellen

Die Verknüpfung des GKE-Standarddienstkontos container-engine-robot mit einem Projekt kann versehentlich aufgehoben werden. GKE-Dienst-Agent ist eine IAM-Rolle (Identity and Access Management), mit der dem Dienstkonto Berechtigungen zum Verwalten von Clusterressourcen erteilt werden. Wenn Sie diese Rollenbindung aus dem Dienstkonto entfernen, wird die Verknüpfung des Standarddienstkontos mit dem Projekt aufgehoben. Dies kann verhindern, dass Anwendungen bereitgestellt und andere Clustervorgänge ausgeführt werden können.

Mit dem gcloud-Tool oder der Cloud Console können Sie prüfen, ob das Dienstkonto aus Ihrem Projekt entfernt wurde.

gcloud

Führen Sie diesen Befehl aus:

gcloud projects get-iam-policy project-id

Ersetzen Sie project-id durch Ihre Projekt-ID.

Console

Rufen Sie in der Cloud Console die Seite IAM & Verwaltung auf.

Wenn im Befehl oder im Dashboard unter Ihren Dienstkonten container-engine-robot nicht angezeigt wird, wurde die Verknüpfung mit dem Dienstkonto aufgehoben.

Wenn Sie die Rollenbindung des GKE-Dienst-Agents entfernt haben, führen Sie die folgenden Befehle aus, um die Rollenbindung wiederherzustellen:

PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format "value(projectNumber)")
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member "serviceAccount:service-${PROJECT_NUMBER}@container-engine-robot.iam.gserviceaccount.com" \
  --role roles/container.serviceAgent

Mit dem folgenden Befehl bestätigen Sie, dass die Rollenbindung erteilt wurde:

gcloud projects get-iam-policy $PROJECT_ID

Wenn der Name des Dienstkontos zusammen mit der Rolle container.serviceAgent angezeigt wird, wurde die Rollenbindung erteilt. Beispiel:

- members:
  - serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
  role: roles/container.serviceAgent

Cloud KMS-Schlüssel ist deaktiviert

Das GKE-Standarddienstkonto kann keinen deaktivierten Cloud KMS-Schlüssel für die Secrets-Verschlüsselung auf Anwendungsebene verwenden.

Informationen zum erneuten Aktivieren eines deaktivierten Schlüssels finden Sie unter Schlüsselversion aktivieren.

Pods bleiben nach der Aktivierung der Option „Node Allocatable“ im Status „Ausstehend“

Wenn Pods nach der Aktivierung von Nodes Allocatable im Status Ausstehend hängen bleiben, beachten Sie Folgendes:

Ab Version 1.7.6 reserviert GKE CPU und Arbeitsspeicher für Kubernetes-Overhead, darunter auch für Docker und das Betriebssystem. Unter Clusterarchitektur finden Sie Informationen dazu, wie viel von jedem Maschinentyp durch Pods belegt werden kann.

Wenn Pods nach einem Upgrade ausstehen, empfehlen wir Folgendes:

  1. Achten Sie darauf, dass die CPU- und Speicheranforderungen Ihrer Pods die maximale Auslastung nicht überschreiten. Da GKE CPU und Arbeitsspeicher für Overhead reserviert, können Pods diese Ressourcen nicht anfordern. Pods, die mehr CPU oder Arbeitsspeicher anfordern, als sie verwenden, verhindern, dass andere Pods diese Ressourcen anfordern. Der Cluster ist somit möglicherweise nicht optimal ausgelastet. Weitere Informationen finden Sie unter Pods mit Ressourcenanfragen planen.

  2. Ziehen Sie eine Anpassung der Clustergröße in Betracht. Eine Anleitung finden Sie unter Clustergröße anpassen.

  3. Führen Sie ein Downgrade des Clusters aus, um diese Änderung rückgängig zu machen. Eine Anleitung finden Sie unter Manuelles Upgrade eines Clusters oder Knotenpools.

Private Clusterknoten wurden erstellt, aber nicht dem Cluster hinzugefügt

Bei der Verwendung von benutzerdefiniertem Routing und Netzwerk-Appliances von Drittanbietern in der VPC, die Ihr privater Cluster verwendet, wird die Standardroute (0.0.0.0/0) an die Appliance weitergeleitet anstatt an das Standard-Internetgateway. Zusätzlich zur Verbindung der Steuerungsebene müssen Sie dafür sorgen, dass die folgenden Ziele erreichbar sind:

  • *.googleapis.com
  • *.gcr.io
  • gcr.io

Konfigurieren Sie den privaten Google-Zugriff für alle drei Domains. Diese Best Practice ermöglicht es Ihnen, die neuen Knoten zu starten und dem Cluster beizutreten, während der ausgehende Internettraffic eingeschränkt bleibt.

Probleme mit bereitgestellten Arbeitslasten beheben

Bei Problemen mit den Pods einer Arbeitslast wird von GKE ein Fehler zurückgegeben. Sie können den Status eines Pods mit dem kubectl-Befehlszeilentool oder der Cloud Console prüfen.

kubectl

Führen Sie den folgenden Befehl aus, um alle in Ihrem Cluster ausgeführten Pods anzusehen:

kubectl get pods

Ausgabe:

NAME       READY  STATUS             RESTARTS  AGE
pod-name   0/1    CrashLoopBackOff   23        8d

Führen Sie den folgenden Befehl aus, um weitere Details zu einem bestimmten Pod abzurufen:

kubectl describe pod pod-name

Ersetzen Sie pod-name durch den Namen des gewünschten Pods.

Console

Führen Sie folgende Schritte aus:

  1. Rufen Sie in der Cloud Console das GKE-Dashboard "Arbeitslasten" auf.

    GKE-Dashboard "Arbeitslasten" aufrufen

  2. Wählen Sie die gewünschte Arbeitslast aus. Auf dem Tab Übersicht wird der Status der Arbeitslast angezeigt.

  3. Klicken Sie im Abschnitt Verwaltete Pods auf die Fehlerstatusmeldung.

In den folgenden Abschnitten werden einige häufig von Arbeitslasten zurückgegebene Fehler erläutert und ihre Behebung erklärt.

CrashLoopBackOff

Der Fehler CrashLoopBackOff gibt an, dass ein Container nach dem Neustart wiederholt abstürzt. Ein Container kann aus verschiedenen Gründen abstürzen. Hier kann ein Blick in die Logs eines Pods helfen, die Ursache zu beheben.

Abgestürzte Container werden standardmäßig mit einer auf fünf Minuten begrenzten exponentiellen Verzögerung neu gestartet. Dieses Verhalten können Sie dadurch ändern, dass Sie in der Pod-Spezifikation des Deployments unter spec: restartPolicy das Feld restartPolicy definieren. Der Standardwert des Felds ist Always.

Mithilfe des kubectl-Befehlszeilentools oder der Cloud Console können Sie ermitteln, weshalb der Container des Pods abstürzt.

kubectl

Führen Sie den folgenden Befehl aus, um alle in Ihrem Cluster ausgeführten Pods anzusehen:

kubectl get pods

Suchen Sie nach dem Pod mit dem Fehler CrashLoopBackOff.

Führen Sie den folgenden Befehl aus, um die Logs des Pods abzurufen:

kubectl logs pod-name

Ersetzen Sie pod-name durch den Namen des problematischen Pods.

Wenn Sie das Flag -p übergeben, können Sie außerdem die Logs der vorherigen Instanz des Containers eines Pods abrufen, falls vorhanden.

Console

Führen Sie folgende Schritte aus:

  1. Rufen Sie in der Cloud Console das GKE-Dashboard "Arbeitslasten" auf.

    GKE-Dashboard "Arbeitslasten" aufrufen

  2. Wählen Sie die gewünschte Arbeitslast aus. Auf dem Tab Übersicht wird der Status der Arbeitslast angezeigt.

  3. Klicken Sie im Abschnitt Verwaltete Pods auf den problematischen Pod.

  4. Klicken Sie im Menü des Pods auf den Tab Logs.

Exit-Code des abgestürzten Containers prüfen

Sie finden den Exit-Code durch Ausführen der folgenden Aufgaben:

  1. Führen Sie diesen Befehl aus:

    kubectl describe pod pod-name
    

    Ersetzen Sie pod-name durch den Namen des Pods.

  2. Prüfen Sie den Wert im Feld containers: container-name: last state: exit code:

    • Lautet der Exit-Code 1, ist ein Absturz der Anwendung der Grund dafür, dass der Container abgestürzt ist.
    • Lautet der Exit-Code 0, stellen Sie fest, wie lange die Anwendung ausgeführt wurde.

    Container werden beendet, wenn der Hauptprozess der Anwendung beendet wird. Wird die Ausführung einer Anwendung sehr schnell beendet, ist es möglich, dass der Container weiter neu gestartet wird.

Verbindung zu einem ausgeführten Container herstellen

Stellen Sie eine Shell-Verbindung zum Pod her:

kubectl exec -it pod-name -- /bin/bash

Wenn sich in Ihrem Pod mehrere Container befinden, fügen Sie -c container-name hinzu.

Jetzt können Sie Bash-Befehle aus dem Container ausführen und so beispielsweise das Netzwerk testen oder prüfen, ob Sie Zugriff auf Dateien oder Datenbanken haben, die von der Anwendung verwendet werden.

ImagePullBackOff und ErrImagePull

Die Fehler ImagePullBackOff und ErrImagePull zeigen an, dass das von einem Container verwendete Image nicht aus der Image-Registry geladen werden kann.

Sie können dieses Problem mithilfe der Cloud Console oder des kubectl-Befehlszeilentools prüfen.

kubectl

Führen Sie den folgenden Befehl aus, um weitere Informationen zum Container-Image eines Pods zu erhalten:

kubectl describe pod pod-name

Console

Führen Sie folgende Schritte aus:

  1. Rufen Sie in der Cloud Console das GKE-Dashboard "Arbeitslasten" auf.

    GKE-Dashboard "Arbeitslasten" aufrufen

  2. Wählen Sie die gewünschte Arbeitslast aus. Auf dem Tab Übersicht wird der Status der Arbeitslast angezeigt.

  3. Klicken Sie im Abschnitt Verwaltete Pods auf den problematischen Pod.

  4. Klicken Sie im Menü des Pods auf den Tab Ereignisse.

Wenn das Image nicht gefunden wird

Wenn Ihr Image nicht gefunden wird, gehen Sie so vor:

  1. Prüfen Sie, ob der Name des Images korrekt ist.
  2. Prüfen Sie dann, ob das Tag des Images korrekt ist. Versuchen Sie es mit :latest oder keinem Tag, um das neueste Image per Pull abzurufen.
  3. Wenn das Image einen vollständigen Registry-Pfad hat, schauen Sie nach, ob es in der von Ihnen verwendeten Docker-Registry vorhanden ist. Falls Sie nur den Image-Namen angegeben haben, prüfen Sie die Docker Hub-Registry.
  4. Versuchen Sie, das Docker-Image manuell herunterzuladen:

    • Stellen Sie eine SSH-Verbindung zum Knoten her:

      So stellen Sie beispielsweise eine SSH-Verbindung zu example-instance in der Zone us-central1-a her:

      gcloud compute ssh example-instance --zone us-central1-a
      
    • Führen Sie docker pull image-name aus.

    Wenn dies funktioniert, müssen Sie möglicherweise ImagePullSecrets für einen Pod angeben. Pods können nur auf Image-Pull-Secrets in ihrem eigenen Namespace verweisen. Daher muss dieser Prozess pro Namespace einmal ausgeführt werden.

Wenn ein Fehler des Typs "Berechtigung verweigert" oder "Kein Pull-Zugriff" auftritt, überprüfen Sie, ob Sie angemeldet sind und/oder Zugriff auf das Image haben.

Bei Verwenden einer privaten Registry sind möglicherweise Schlüssel zum Lesen von Images erforderlich.

Wenn das Image in Container Registry gehostet wird, benötigt das mit Ihrem Knotenpool verknüpfte Dienstkonto Lesezugriff auf den Cloud Storage-Bucket, der das Image enthält. Weitere Informationen finden Sie in der Dokumentation zu Container Registry.

Pod nicht planbar

Der Fehler PodUnschedulable gibt an, dass Ihr Pod aufgrund unzureichender Ressourcen oder eines Konfigurationsfehlers nicht geplant werden kann.

Unzureichende Ressourcen

Möglicherweise stoßen Sie auf einen Fehler, der auf zu wenig CPU-Kapazität, Arbeitsspeicher oder andere Ressourcen hinweist. Beispiel: "Es sind keine Knoten verfügbar, die mit allen Prädikaten übereinstimmen: Unzureichende CPU (2)". Dies weist darauf hin, dass auf zwei Knoten nicht genügend CPU-Kapazität verfügbar ist, um die Anfragen eines Pods zu erfüllen.

Die Standard-CPU-Anfrage beträgt 100 MB oder 10 % einer CPU bzw. eines Kerns. Wenn Sie mehr oder weniger Ressourcen anfordern möchten, geben Sie den Wert in der Pod-Spezifikation unter spec: containers: resources: requests an.

MatchNodeSelector

Der Fehler MatchNodeSelector gibt an, dass keine Knoten vorhanden sind, die mit der Labelauswahl des Pods übereinstimmen.

Sehen Sie sich in der Pod-Spezifikation unter spec: nodeSelector die im Feld nodeSelector angegebenen Labels an, um das zu prüfen.

Führen Sie den folgenden Befehl aus, um sich die Labels von Knoten in Ihrem Cluster anzusehen:

kubectl get nodes --show-labels

Führen Sie den folgenden Befehl aus, um einem Knoten ein Label hinzuzufügen:

kubectl label nodes node-name label-key=label-value

Ersetzen Sie Folgendes:

  • node-name durch den gewünschten Knoten.
  • label-key durch den Schlüssel des Labels.
  • label-value durch den Wert des Labels.

Weitere Informationen finden Sie unter Pods zu Knoten zuweisen.

PodToleratesNodeTaints

Der Fehler PodToleratesNodeTaints gibt an, dass der Pod für keinen Knoten geplant werden kann, da aktuell kein Knoten die Knotenmarkierung des Pods toleriert.

Führen Sie den folgenden Befehl aus, um dies zu ermitteln:

kubectl describe nodes node-name

Prüfen Sie in der Ausgabe das Feld Taints. Darin sind Schlüssel/Wert-Paare und Planungseffekte aufgeführt.

Lautet der aufgeführte Effekt NoSchedule, können Pods auf diesem Knoten nur geplant werden, wenn sie eine übereinstimmende Toleranz haben.

Eine Möglichkeit zur Behebung dieses Problems ist, die Markierung zu entfernen. Führen Sie beispielsweise den folgenden Befehl aus, um eine NoSchedule-Markierung zu entfernen:

kubectl taint nodes node-name key:NoSchedule-

PodFitsHostPorts

Der Fehler PodFitsHostPorts gibt an, dass ein Port, den ein Knoten zu verwenden versucht, bereits in Gebrauch ist.

Prüfen Sie in der Pod-Spezifikation unter spec: containers: ports: hostPort den Wert hostPort, um dieses Problem zu beheben. Es kann sein, dass dieser Wert in einen anderen Port geändert werden muss.

Keine Mindestverfügbarkeit vorhanden

Wenn für einen Knoten genügend Ressourcen vorhanden sind, die Meldung Does not have minimum availability jedoch immer noch angezeigt wird, prüfen Sie den Status des Pods. Wenn er SchedulingDisabled oder Cordoned lautet, kann der Knoten keine neuen Pods planen. Sie können den Status eines Knotens in der Cloud Console oder dem kubectl-Befehlszeilentool prüfen.

kubectl

Führen Sie den folgenden Befehl aus, um die Status der Knoten abzurufen:

kubectl get nodes

Die Planung auf dem Knoten aktivieren Sie mit folgendem Befehl:

kubectl uncordon node-name

Console

Führen Sie folgende Schritte aus:

  1. Rufen Sie in der Cloud Console das GKE-Dashboard "Arbeitslasten" auf.

    GKE-Dashboard "Cluster" aufrufen

  2. Wählen Sie den gewünschten Cluster aus. Auf dem Tab Knoten werden die Knoten und ihr Status angezeigt.

Führen Sie die folgenden Schritte aus, um die Planung auf dem Knoten zu aktivieren:

  1. Klicken Sie in der Liste auf den gewünschten Knoten.

  2. Klicken Sie dann in den Knotendetails auf Entsperren.

Ungebundene PersistentVolumeClaims

Der Fehler Unbound PersistentVolumeClaims gibt an, dass der Pod auf einen nicht gebundenen PersistentVolumeClaim verweist. Dieser Fehler kann auftreten, wenn das PersistentVolume nicht bereitgestellt werden konnte. Sie können prüfen, ob die Bereitstellung fehlgeschlagen ist. Dazu rufen Sie die Ereignisse für den PersistentVolumeClaim ab und untersuchen sie auf Fehler.

Führen Sie den folgenden Befehl aus, um Ereignisse abzurufen:

kubectl describe pvc statefulset-name-pvc-name-0

Ersetzen Sie Folgendes:

  • statefulset-name durch den Namen des StatefulSet-Objekts.
  • pvc-name durch den Namen des PersistentVolumeClaim-Objekts.

Dies kann auch passieren, wenn während der manuellen Vorabbereitstellung eines PersistentVolume und der Bindung an einen PersistentVolumeClaim ein Konfigurationsfehler aufgetreten ist. Sie können versuchen, das Volume noch einmal vorab bereitzustellen.

Verbindungsprobleme

Damit Sie Fehler erfolgreich beheben können, sollten Sie wissen, wie die Netzwerk-Namespaces von Pods mit dem Stamm-Namespace auf dem Knoten verbunden sind (siehe Netzwerkübersicht). Gehen Sie bei der folgenden Erläuterung davon aus, dass der Cluster das native CNI von GKE und nicht das CNI von Calico verwendet (sofern nicht anders angegeben). Das heißt, es wurde keine Netzwerkrichtlinie angewendet.

Pods auf bestimmten Knoten sind nicht verfügbar

Wenn Pods auf bestimmten Knoten keine Netzwerkverbindung haben, prüfen Sie, ob die Linux-Bridge aktiv ist:

ip address show cbr0

Wenn die Linux-Bridge nicht aktiv ist, starten Sie sie:

sudo ip link set cbr0 up

Prüfen Sie, ob der Knoten Pod-MAC-Adressen in Erfahrung bringt, die zu cbr0 gehören:

arp -an

Pods auf bestimmten Knoten haben nur minimale Konnektivität

Wenn Pods auf bestimmten Knoten nur minimale Konnektivität haben, sollten Sie zuerst prüfen, ob Pakete verloren gegangen sind. Führen Sie dazu tcpdump im Toolbox-Container aus:

sudo toolbox bash

Installieren Sie tcpdump in der Toolbox, wenn nicht bereits geschehen:

apt install -y tcpdump

Führen Sie tcpdump für cbr0 aus:

tcpdump -ni cbr0 host hostname and port port-number and [tcp|udp|icmp]

Wenn es so aussieht, als würden große Pakete nach der Bridge verloren gehen (der TCP-Handshake wird beispielsweise abgeschlossen, es gehen aber keine SSL-Hellos ein), prüfen Sie, ob der MTU-Wert der Linux-Bridge korrekt auf den MTU-Wert des VPC-Netzwerks des Clusters festgelegt ist.

ip address show cbr0

Wenn Overlays verwendet werden (z. B. Weave oder Flannel), muss dieser MTU-Wert weiter reduziert werden, um Kapselungsoverhead für das Overlay aufzufangen.

Zeitweise fehlgeschlagene Verbindungen

Verbindungen zu und von den Pods werden von iptables weitergeleitet. Datenflüsse werden als Einträge in der Conntrack-Tabelle verfolgt. Wenn viele Arbeitslasten pro Knoten vorhanden sind, kann die Überfüllung der Conntrack-Tabelle zu einem Fehler führen. Solche Fehler können in der seriellen Konsole des Knotens protokolliert werden. Beispiel:

nf_conntrack: table full, dropping packet

Wenn sich zeitweise auftretende Probleme auf eine volle Conntrack-Tabelle zurückführen lassen, können Sie die Größe des Clusters erhöhen, um die Anzahl der Arbeitslasten und Datenflüsse pro Knoten zu reduzieren, oder nf_conntrack_max erhöhen:

new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
  && echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf

"bind: Address already in use" wird für einen Container gemeldet

Aus den Containerlogs geht hervor, dass ein Container in einem Pod nicht gestartet werden kann, da der Port, an den sich die Anwendung binden möchte, bereits reserviert ist. Der Container gerät in eine Absturzschleife. Zum Beispiel in Cloud Logging:

resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"

2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use

Wenn Docker abstürzt, wird manchmal ein veralteter Container weiterhin ausgeführt. Der Prozess läuft im Netzwerk-Namespace weiter, der dem Pod zugewiesen ist, und überwacht seinen Port. Da Docker und das kubelet nichts von dem veralteten Container wissen, versuchen sie, einen neuen Container mit einem neuen Prozess zu starten. Dieser Prozess kann sich jedoch nicht an den Port binden, da er dem Netzwerk-Namespace hinzugefügt wird, der bereits mit dem Pod verknüpft ist.

So diagnostizieren Sie dieses Problem:

  1. Sie benötigen die UUID des Pods im Feld .metadata.uuid:

    kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg
    
    name                      UUID
    ubuntu-6948dd5657-4gsgg   db9ed086-edba-11e8-bdd6-42010a800164
    
  2. Rufen Sie die Ausgabe der folgenden Befehle vom Knoten ab:

    docker ps -a
    ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
    
  3. Prüfen Sie die laufenden Prozesse von diesem Pod. Da die UUID der cgroup-Namespaces die UUID des Pods enthält, können Sie die Pod-UUID mit grep in ps ausgeben. Rufen Sie auch die Zeile davor mit grep ab, sodass Sie die docker-containerd-shim-Prozesse erhalten, die auch die Container-ID im Argument haben. Schneiden Sie den Rest der cgroup-Spalte ab, um die Ausgabe zu vereinfachen:

    # ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/
    1283089     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim 276e173b0846e24b704d4 12:
    1283107 1283089 Ss   sys_pause            4026532393         pause           /pause                                     12:
    1283150     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim ab4c7762f5abf40951770 12:
    1283169 1283150 Ss   do_wait              4026532393         sh              /bin/sh -c echo hello && sleep 6000000     12:
    1283185 1283169 S    hrtimer_nanosleep    4026532393           sleep           sleep 6000000                            12:
    1283244     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim 44e76e50e5ef4156fd5d3 12:
    1283263 1283244 Ss   sigsuspend           4026532393         nginx           nginx: master process nginx -g daemon off; 12:
    1283282 1283263 S    ep_poll              4026532393           nginx           nginx: worker process
    
  4. Dieser Liste können Sie die Container-IDs entnehmen, die auch in docker ps sichtbar sein sollten.

    In diesem Fall:

    • docker-containerd-shim 276e173b0846e24b704d4 für pause
    • docker-containerd-shim ab4c7762f5abf40951770 für sh mit sleep (sleep-ctr)
    • docker-containerd-shim 44e76e50e5ef4156fd5d3 für nginx (echoserver-ctr)
  5. Prüfen Sie diese in der Ausgabe von docker ps:

    # docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3'
    44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f   gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc                   "nginx -g 'daemon off;'"                                                                                                                                                                                                                                                                                                                                                                     14 hours ago        Up 14 hours                             k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0
    ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475   ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78                                                "/bin/sh -c 'echo hello && sleep 6000000'"                                                                                                                                                                                                                                                                                                                                                   14 hours ago        Up 14 hours                             k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0
    276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327   k8s.gcr.io/pause-amd64:3.1
    

    Normalerweise werden alle Container-IDs aus ps in docker ps angezeigt. Wenn Sie eine ID nicht sehen, ist der Container veraltet. Wahrscheinlich sehen Sie dann einen untergeordneten Prozess von docker-containerd-shim process, der den TCP-Port überwacht, der als bereits verwendet gemeldet wird.

    Damit Sie das prüfen können, führen Sie netstat im Netzwerk-Namespace des Containers aus. Rufen Sie die PID eines beliebigen Containerprozesses (jedoch NICHT docker-containerd-shim) für den Pod ab.

    Aus dem obigen Beispiel:

    • 1283107 – pause
    • 1283169 – sh
    • 1283185 – sleep
    • 1283263 – nginx-Master
    • 1283282 – nginx-Worker
    # nsenter -t 1283107 --net netstat -anp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
    unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
    unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
    
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
    unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
    unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
    

    Sie können auch netstat mit ip netns ausführen, müssen jedoch den Netzwerk-Namespace des Prozesses manuell verbinden, da Docker die Verbindung nicht herstellt:

    # ln -s /proc/1283169/ns/net /var/run/netns/1283169
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list
    1283169 (id: 2)
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
    unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
    unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
    gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
    

Abhilfe:

Zur vorläufigen Abhilfe können Sie veraltete Prozesse mit der oben beschriebenen Methode identifizieren und die Prozesse mit dem Befehl kill [PID] beenden.

Zur langfristigen Abhilfe müssen Sie feststellen, warum Docker abstürzt, und dieses Problem beheben. Mögliche Gründe:

  • Es sammeln sich Zombie-Prozesse an, sodass PID-Namespaces ausgehen
  • Programmfehler in Docker
  • Ressourcenknappheit/nicht genügend Arbeitsspeicher