Fehlerbehebung bei Dienstkonten in GKE

Auf dieser Seite erfahren Sie, wie Sie Probleme mit Dienstkonten in der Google Kubernetes Engine (GKE) beheben.

Erforderliche Rolle für GKE Knotendienstkonten zuweisen

Für GKE-Cluster mit Kubernetes-Version 1.33 oder niedriger müssen die IAM-Dienstkonten, die von Ihren GKE-Knoten verwendet werden, alle Berechtigungen haben, die in der IAM-Rolle Kubernetes Engine-Standardknoten-Dienstkonto (roles/container.defaultNodeServiceAccount) enthalten sind. Wenn einem GKE-Knotendienstkonto eine oder mehrere dieser Berechtigungen fehlen, kann GKE keine Systemaufgaben wie die folgenden ausführen:

Knoten-Dienstkonten haben möglicherweise aus folgenden Gründen nicht die erforderlichen Berechtigungen:

Wenn Ihrem Knoten-Dienstkonto die von GKE benötigten Berechtigungen fehlen, werden möglicherweise Fehler und Hinweise wie die folgenden angezeigt:

  • In der Google Cloud Console wird auf der Seite Kubernetes-Cluster in der Spalte Benachrichtigungen für einen bestimmten Cluster die Fehlermeldung Kritische Berechtigungen erteilen angezeigt.
  • In der Google Cloud Console wird auf der Seite mit den Clusterdetails für einen bestimmten Cluster die folgende Fehlermeldung angezeigt:

    Grant roles/container.defaultNodeServiceAccount role to Node service account to allow for non-degraded operations.
    
  • In Cloud-Audit-Logs haben Administratoraktivitätslogs für Google Cloud APIs wiemonitoring.googleapis.com die folgenden Werte, wenn dem Knotendienstkonto die entsprechenden Berechtigungen für den Zugriff auf diese APIs fehlen:

    • Schweregrad: ERROR
    • Nachricht: Permission denied (or the resource may not exist)
  • Logs für bestimmte Knoten fehlen in Cloud Logging und die Pod-Logs für den Logging-Agent auf diesen Knoten enthalten 401-Fehler. Führen Sie den folgenden Befehl aus, um diese Pod-Logs abzurufen:

    [[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"
    

    Wenn die Ausgabe true ist, treten bei der Systemarbeitslast 401-Fehler auf, die auf fehlende Berechtigungen hinweisen.

Weisen Sie zur Behebung dieses Problems dem Dienstkonto, das die Fehler verursacht, die Rolle „Kubernetes Engine Default Node Service Account“ (roles/container.defaultNodeServiceAccount) für das Projekt zu. Wählen Sie eine der folgenden Optionen aus:

Console

So finden Sie den Namen des Dienstkontos, das von Ihren Knoten verwendet wird:

  1. Zur Seite Kubernetes-Cluster

    Zur Seite "Kubernetes-Cluster"

  2. Klicken Sie in der Clusterliste auf den Namen des Clusters, den Sie prüfen möchten.

  3. Suchen Sie nach dem Namen des Knotendienstkontos. Sie benötigen diesen Namen später.

    • Suchen Sie bei Clustern im Autopilot-Modus im Abschnitt Sicherheit nach dem Feld Dienstkonto.
    • Führen Sie für Cluster im Standardmodus die folgenden Schritte aus:
    1. Klicken Sie auf den Tab Knoten.
    2. Klicken Sie in der Tabelle Knotenpools auf einen Knotenpoolnamen. Die Seite Knotenpooldetails wird geöffnet.
    3. Suchen Sie im Abschnitt Sicherheit nach dem Feld Dienstkonto.

    Wenn der Wert im Feld Dienstkonto default ist, verwenden Ihre Knoten das Compute Engine-Standarddienstkonto. Wenn der Wert in diesem Feld nicht default ist, verwenden Ihre Knoten ein benutzerdefiniertes Dienstkonto.

So weisen Sie dem Dienstkonto die Rolle Kubernetes Engine Default Node Service Account zu:

  1. Rufen Sie die Seite Willkommen auf:

    Zur Begrüßungsseite

  2. Klicken Sie im Feld Projektnummer auf  In die Zwischenablage kopieren.

  3. Rufen Sie die IAM-Seite auf.

    IAM aufrufen

  4. Klicken Sie auf Zugriffsrechte erteilen.

  5. Geben Sie im Feld Neue Hauptkonten den Namen Ihres Knotendienstkontos an. Wenn Ihre Knoten das Compute Engine-Standarddienstkonto verwenden, geben Sie den folgenden Wert an:

    PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    Ersetzen Sie PROJECT_NUMBER durch die kopierte Projektnummer.

  6. Wählen Sie im Menü Rolle auswählen die Rolle Kubernetes Engine Default Node Service Account aus.

  7. Klicken Sie auf Speichern.

So prüfen Sie, ob die Rolle gewährt wurde:

  1. Klicken Sie auf der Seite IAM auf den Tab Nach Rollen ansehen.
  2. Maximieren Sie den Bereich Kubernetes Engine Default Node Service Account. Eine Liste der Hauptkonten mit dieser Rolle wird angezeigt.
  3. Suchen Sie Ihr Knotendienstkonto in der Liste der Hauptkonten.

gcloud

  1. So finden Sie den Namen des Dienstkontos, das von Ihren Knoten verwendet wird:

    • Führen Sie für Cluster im Autopilot-Modus den folgenden Befehl aus:
    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
    
    • Führen Sie für Cluster im Standardmodus den folgenden Befehl aus:
    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --format="table(nodePools.name,nodePools.config.serviceAccount)"
    

    Wenn die Ausgabe default ist, verwenden Ihre Knoten das Compute Engine-Standarddienstkonto. Wenn die Ausgabe nicht default ist, verwenden Ihre Knoten ein benutzerdefiniertes Dienstkonto.

  2. So finden Sie Ihre Google Cloud Projektnummer:

    gcloud projects describe PROJECT_ID \
        --format="value(projectNumber)"
    

    Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID.

    Die Ausgabe sieht etwa so aus:

    12345678901
    
  3. Weisen Sie dem Dienstkonto die Rolle roles/container.defaultNodeServiceAccount zu:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member="SERVICE_ACCOUNT_NAME" \
        --role="roles/container.defaultNodeServiceAccount"
    

    Ersetzen Sie SERVICE_ACCOUNT_NAME durch den Namen des Dienstkontos, den Sie im vorherigen Schritt ermittelt haben. Wenn Ihre Knoten das Compute Engine-Standarddienstkonto verwenden, geben Sie den folgenden Wert an:

    serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    Ersetzen Sie PROJECT_NUMBER durch die Projektnummer aus dem vorherigen Schritt.

  4. Prüfen Sie, ob die Rolle erfolgreich gewährt wurde:

    gcloud projects get-iam-policy PROJECT_ID \
        --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \
        --format='value(bindings.members)'
    

    Die Ausgabe ist der Name Ihres Dienstkontos.

Cluster mit Knotendienstkonten mit fehlenden Berechtigungen identifizieren

Verwenden Sie GKE-Empfehlungen des NODE_SA_MISSING_PERMISSIONS Empfehlungssubtyps, um Autopilot- und Standardcluster mit Knoten-Servicekonten mit fehlenden Berechtigungen zu identifizieren. Der Recommender identifiziert nur Cluster, die am oder nach dem 1. Januar 2024 erstellt wurden. So finden und beheben Sie fehlende Berechtigungen mit Recommender:

  1. So finden Sie aktive Empfehlungen in Ihrem Projekt für den Recommender-Untertyp NODE_SA_MISSING_PERMISSIONS:

    gcloud recommender recommendations list \
        --recommender=google.container.DiagnosisRecommender \
        --location LOCATION \
        --project PROJECT_ID \
        --format yaml \
        --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
    

    Ersetzen Sie Folgendes:

    • LOCATION: Der Standort, an dem Empfehlungen zu finden sind.
    • PROJECT_ID: Projekt-ID in Google Cloud .

    Die Ausgabe sieht etwa so aus. Sie weist darauf hin, dass für ein Cluster ein Knotendienstkonto mit fehlenden Berechtigungen vorhanden ist:

    associatedInsights:
    # lines omitted for clarity
    recommenderSubtype: NODE_SA_MISSING_PERMISSIONS
    stateInfo:
      state: ACTIVE
    targetResources:
    - //container.googleapis.com/projects/12345678901/locations/us-central1/clusters/cluster-1
    

    Es kann bis zu 24 Stunden dauern, bis die Empfehlung angezeigt wird. Eine detaillierte Anleitung finden Sie unter Insights und Empfehlungen ansehen.

  2. Suchen Sie für jeden Cluster in der Ausgabe des vorherigen Schritts die zugehörigen Knoten-Dienstkonten und weisen Sie diesen Dienstkonten die erforderliche Rolle zu. Weitere Informationen finden Sie im Abschnitt Erforderliche Rolle für GKE für Knoten-Dienstkonten zuweisen.

    Nachdem Sie den identifizierten Knotendienstkonten die erforderliche Rolle zugewiesen haben, wird die Empfehlung möglicherweise bis zu 24 Stunden lang angezeigt, sofern Sie sie nicht manuell schließen.

Alle Knotendienstkonten mit fehlenden Berechtigungen identifizieren

Sie können ein Skript ausführen, das in den Standard- und Autopilot-Clustern Ihres Projekts nach Knotendienstkonten sucht, die nicht die erforderlichen Berechtigungen für GKE haben. In diesem Skript werden die gcloud CLI und das jq-Dienstprogramm verwendet. Wenn Sie das Skript aufrufen möchten, maximieren Sie den folgenden Abschnitt:

Skript ansehen

#!/bin/bash

# Set your project ID
project_id=PROJECT_ID
project_number=$(gcloud projects describe "$project_id" --format="value(projectNumber)")
declare -a all_service_accounts
declare -a sa_missing_permissions

# Function to check if a service account has a specific permission
# $1: project_id
# $2: service_account
# $3: permission
service_account_has_permission() {
  local project_id="$1"
  local service_account="$2"
  local permission="$3"

  local roles=$(gcloud projects get-iam-policy "$project_id" \
          --flatten="bindings[].members" \
          --format="table[no-heading](bindings.role)" \
          --filter="bindings.members:\"$service_account\"")

  for role in $roles; do
    if role_has_permission "$role" "$permission"; then
      echo "Yes" # Has permission
      return
    fi
  done

  echo "No" # Does not have permission
}

# Function to check if a role has the specific permission
# $1: role
# $2: permission
role_has_permission() {
  local role="$1"
  local permission="$2"
  gcloud iam roles describe "$role" --format="json" | \
  jq -r ".includedPermissions" | \
  grep -q "$permission"
}

# Function to add $1 into the service account array all_service_accounts
# $1: service account
add_service_account() {
  local service_account="$1"
  all_service_accounts+=( ${service_account} )
}

# Function to add service accounts into the global array all_service_accounts for a Standard GKE cluster
# $1: project_id
# $2: location
# $3: cluster_name
add_service_accounts_for_standard() {
  local project_id="$1"
  local cluster_location="$2"
  local cluster_name="$3"

  while read nodepool; do
    nodepool_name=$(echo "$nodepool" | awk '{print $1}')
    if [[ "$nodepool_name" == "" ]]; then
      # skip the empty line which is from running `gcloud container node-pools list` in GCP console
      continue
    fi
    while read nodepool_details; do
      service_account=$(echo "$nodepool_details" | awk '{print $1}')

      if [[ "$service_account" == "default" ]]; then
        service_account="${project_number}-compute@developer.gserviceaccount.com"
      fi
      if [[ -n "$service_account" ]]; then
        printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" $service_account $project_id  $cluster_name $cluster_location $nodepool_name
        add_service_account "${service_account}"
      else
        echo "cannot find service account for node pool $project_id\t$cluster_name\t$cluster_location\t$nodepool_details"
      fi
    done <<< "$(gcloud container node-pools describe "$nodepool_name" --cluster "$cluster_name" --zone "$cluster_location" --project "$project_id" --format="table[no-heading](config.serviceAccount)")"
  done <<< "$(gcloud container node-pools list --cluster "$cluster_name" --zone "$cluster_location" --project "$project_id" --format="table[no-heading](name)")"

}

# Function to add service accounts into the global array all_service_accounts for an Autopilot GKE cluster
# Autopilot cluster only has one node service account.
# $1: project_id
# $2: location
# $3: cluster_name
add_service_account_for_autopilot(){
  local project_id="$1"
  local cluster_location="$2"
  local cluster_name="$3"

  while read service_account; do
      if [[ "$service_account" == "default" ]]; then
        service_account="${project_number}-compute@developer.gserviceaccount.com"
      fi
      if [[ -n "$service_account" ]]; then
        printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" $service_account $project_id  $cluster_name $cluster_location $nodepool_name
        add_service_account "${service_account}"
      else
        echo "cannot find service account" for cluster  "$project_id\t$cluster_name\t$cluster_location\t"
      fi
  done <<< "$(gcloud container clusters describe "$cluster_name" --location "$cluster_location" --project "$project_id" --format="table[no-heading](autoscaling.autoprovisioningNodePoolDefaults.serviceAccount)")"
}


# Function to check whether the cluster is an Autopilot cluster or not
# $1: project_id
# $2: location
# $3: cluster_name
is_autopilot_cluster() {
  local project_id="$1"
  local cluster_location="$2"
  local cluster_name="$3"
  autopilot=$(gcloud container clusters describe "$cluster_name" --location "$cluster_location" --format="table[no-heading](autopilot.enabled)")
  echo "$autopilot"
}


echo "--- 1. List all service accounts in all GKE node pools"
printf "%-60s| %-40s| %-40s| %-10s| %-20s\n" "service_account" "project_id" "cluster_name" "cluster_location" "nodepool_name"
while read cluster; do
  cluster_name=$(echo "$cluster" | awk '{print $1}')
  cluster_location=$(echo "$cluster" | awk '{print $2}')
  # how to find a cluster is a Standard cluster or an Autopilot cluster
  autopilot=$(is_autopilot_cluster "$project_id" "$cluster_location" "$cluster_name")
  if [[ "$autopilot" == "True" ]]; then
    add_service_account_for_autopilot "$project_id" "$cluster_location"  "$cluster_name"
  else
    add_service_accounts_for_standard "$project_id" "$cluster_location"  "$cluster_name"
  fi
done <<< "$(gcloud container clusters list --project "$project_id" --format="value(name,location)")"

echo "--- 2. Check if service accounts have permissions"
unique_service_accounts=($(echo "${all_service_accounts[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))

echo "Service accounts: ${unique_service_accounts[@]}"
printf "%-60s| %-40s| %-40s| %-20s\n" "service_account" "has_logging_permission" "has_monitoring_permission" "has_performance_hpa_metric_write_permission"
for sa in "${unique_service_accounts[@]}"; do
  logging_permission=$(service_account_has_permission "$project_id" "$sa" "logging.logEntries.create")
  time_series_create_permission=$(service_account_has_permission "$project_id" "$sa" "monitoring.timeSeries.create")
  metric_descriptors_create_permission=$(service_account_has_permission "$project_id" "$sa" "monitoring.metricDescriptors.create")
  if [[ "$time_series_create_permission" == "No" || "$metric_descriptors_create_permission" == "No" ]]; then
    monitoring_permission="No"
  else
    monitoring_permission="Yes"
  fi
  performance_hpa_metric_write_permission=$(service_account_has_permission "$project_id" "$sa" "autoscaling.sites.writeMetrics")
  printf "%-60s| %-40s| %-40s| %-20s\n" $sa $logging_permission $monitoring_permission $performance_hpa_metric_write_permission

  if [[ "$logging_permission" == "No" || "$monitoring_permission" == "No" || "$performance_hpa_metric_write_permission" == "No" ]]; then
    sa_missing_permissions+=( ${sa} )
  fi
done

echo "--- 3. List all service accounts that don't have the above permissions"
if [[ "${#sa_missing_permissions[@]}" -gt 0 ]]; then
  printf "Grant roles/container.defaultNodeServiceAccount to the following service accounts: %s\n" "${sa_missing_permissions[@]}"
else
  echo "All service accounts have the above permissions"
fi

Dieses Script gilt für alle GKE-Cluster in Ihrem Projekt.

Nachdem Sie die Namen der Dienstkonten mit fehlenden Berechtigungen ermittelt haben, weisen Sie ihnen die erforderliche Rolle zu. Weitere Informationen finden Sie im Abschnitt Knoten-Dienstkonten die erforderliche Rolle für GKE zuweisen.

Standarddienstkonto für Ihr Google Cloud -Projekt wiederherstellen

Die Verknüpfung des GKE-Standarddienstkontos container-engine-robot mit einem Projekt kann versehentlich aufgehoben werden. Die Rolle Kubernetes Engine-Dienst-Agent (roles/container.serviceAgent) 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.

Mit der Google Cloud Console oder der Google Cloud CLI können Sie prüfen, ob das Dienstkonto aus Ihrem Projekt entfernt wurde.

Console

gcloud

  • Führen Sie dazu diesen Befehl aus:

    gcloud projects get-iam-policy PROJECT_ID
    

    Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID.

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

Führen Sie die folgenden Befehle aus, um die Bindung der Rolle „Kubernetes Engine-Dienst-Agent“ (roles/container.serviceAgent) wiederherzustellen:

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

Prüfen Sie, ob die Rollenbindung wiederhergestellt wurde:

gcloud projects get-iam-policy PROJECT_ID

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

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

Compute Engine-Standarddienstkonto aktivieren

Das für den Knotenpool verwendete Dienstkonto ist in der Regel das Compute Engine-Standarddienstkonto. Wenn dieses Standarddienstkonto deaktiviert ist, können Ihre Knoten möglicherweise nicht beim Cluster registriert werden.

Mit derGoogle Cloud -Console oder der gcloud CLI können Sie prüfen, ob das Dienstkonto in Ihrem Projekt deaktiviert ist.

Console

gcloud

  • Führen Sie dazu diesen Befehl aus:
gcloud iam service-accounts list  --filter="NAME~'compute' AND disabled=true"

Wenn das Dienstkonto deaktiviert ist, führen Sie die folgenden Befehle aus, um es zu aktivieren:

  1. So finden Sie Ihre Google Cloud Projektnummer:

    gcloud projects describe PROJECT_ID \
        --format="value(projectNumber)"
    

    Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID.

    Die Ausgabe sieht etwa so aus:

    12345678901
    
  2. Aktivieren Sie das Dienstkonto:

    gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com
    

    Ersetzen Sie PROJECT_NUMBER durch die Projektnummer aus der Ausgabe des vorherigen Schritts.

Weitere Informationen finden Sie unter Fehlerbehebung bei der Knotenregistrierung.

Fehler 400/403: Dem Konto fehlen Bearbeitungsberechtigungen

Wenn Ihr Dienstkonto gelöscht wird, wird möglicherweise der Fehler „Fehlende Bearbeitungsberechtigungen“ angezeigt. Informationen zum Beheben dieses Fehlers finden Sie unter Fehler 400/403: Dem Konto fehlen Bearbeitungsberechtigungen.

Nächste Schritte

  • Wenn Sie in der Dokumentation keine Lösung für Ihr Problem finden, lesen Sie den Abschnitt Support erhalten. Dort finden Sie weitere Hilfe, z. B. zu den folgenden Themen: