Falsch konfigurierte oder fehlende Berechtigungen für Google Kubernetes Engine-Dienstkonten (GKE) können zu verschiedenen Problemen führen, z. B. dazu, dass Knoten nicht registriert werden können oder Arbeitslasten nicht auf Dienste zugreifen können. Google Cloud
In diesem Dokument erfahren Sie, wie Sie Probleme beheben können, die durch falsch konfigurierte, deaktivierte oder gelöschte Dienstkonten verursacht werden.
Diese Informationen sind wichtig für Plattformadministratoren und ‑operatoren sowie für Sicherheitsingenieure, die IAM-Berechtigungen auf Projektebene für GKE-Knoten und GKE-Kernkomponenten konfigurieren und verwalten. Weitere Informationen zu den gängigen Rollen und Beispielaufgaben, auf die wir in Google Cloud Inhalten verweisen, finden Sie unter Häufig verwendete GKE-Nutzerrollen und -aufgaben.
Erforderliche Rolle für GKE für 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 Default Node Service Account“
(roles/container.defaultNodeServiceAccount) enthalten sind. Wenn einem GKE-Knotendienstkonto eine oder mehrere dieser Berechtigungen fehlen, kann GKE keine Systemaufgaben wie die folgenden ausführen:
- System- und Anwendungslogs von Knoten an Cloud Logging senden.
- System- und Anwendungsmesswerte von Knoten an Cloud Monitoring senden.
- Das Leistungsprofil des horizontalen Pod-Autoscalers verwenden.
Knotendienstkonten haben möglicherweise bestimmte erforderliche Berechtigungen aus folgenden Gründen nicht:
- Die Organisation erzwingt die
iam.automaticIamGrantsForDefaultServiceAccountsEinschränkung für die Organisationsrichtlinie, die verhindert, Google Cloud dass IAM-Rollen automatisch Standard-IAM-Dienstkonten zugewiesen werden. - Die IAM-Rolle, die Sie benutzerdefinierten Knotendienstkonten zuweisen, enthält nicht alle erforderlichen Berechtigungen, die in der Rolle
roles/container.defaultNodeServiceAccountenthalten sind.
Wenn Ihrem Knotendienstkonto 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 Grant critical permissions (Wichtige Berechtigungen erteilen) angezeigt.
In der Google Cloud Console wird auf der Detailseite des Clusters 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 wie
monitoring.googleapis.comdie 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)(Berechtigung verweigert (oder die Ressource ist möglicherweise nicht vorhanden))
- Schweregrad:
Logs für bestimmte Knoten fehlen in Cloud Logging und in den Pod-Logs für den Logging-Agent auf diesen Knoten werden
401-Fehler angezeigt. 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
trueist, treten bei der Systemarbeitslast401-Fehler auf, die auf fehlende Berechtigungen hinweisen.
Um dieses Problem zu beheben, weisen Sie dem Dienstkonto, das die Fehler verursacht, die Rolle „Kubernetes Engine Default Node Service Account“ (roles/container.defaultNodeServiceAccount) im Projekt zu. Wählen Sie eine der folgenden Optionen aus:
Console
So finden Sie den Namen des Dienstkontos, das von Ihren Knoten verwendet wird:
Rufen Sie die Seite Kubernetes-Cluster auf:
Klicken Sie in der Clusterliste auf den Namen des Clusters, den Sie untersuchen möchten.
Suchen Sie den Namen des Knotendienstkontos. Sie benötigen diesen Namen später.
- Suchen Sie bei Clustern im Autopilot-Modus im Bereich Sicherheit nach dem Feld Dienstkonto.
- Führen Sie für Cluster im Standardmodus die folgenden Schritte aus:
- Klicken Sie auf den Tab Knoten.
- Klicken Sie in der Tabelle Knotenpools auf einen Knotenpoolnamen. Die Seite Knotenpooldetails wird geöffnet.
- Suchen Sie im Bereich Sicherheit nach dem Feld Dienstkonto.
Wenn der Wert im Feld Dienstkonto
defaultist, verwenden Ihre Knoten das Compute Engine-Standarddienstkonto. Wenn der Wert in diesem Feld nichtdefaultist, verwenden Ihre Knoten ein benutzerdefiniertes Dienstkonto.
So weisen Sie dem Dienstkonto die Rolle Kubernetes Engine Default Node Service Account zu:
Rufen Sie die Seite Willkommen auf:
Klicken Sie im Feld Projektnummer auf In die Zwischenablage kopieren.
Rufen Sie die Seite IAM auf:
Klicken Sie auf Zugriffsrechte erteilen.
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.comErsetzen Sie
PROJECT_NUMBERdurch die kopierte Projektnummer.Wählen Sie im Menü Rolle auswählen die Rolle Kubernetes Engine Default Node Service Account aus.
Klicken Sie auf Speichern.
So prüfen Sie, ob die Rolle zugewiesen wurde:
- Klicken Sie auf der Seite IAM auf den Tab Nach Rollen ansehen.
- Maximieren Sie den Bereich Kubernetes Engine Default Node Service Account. Eine Liste der Hauptkonten mit dieser Rolle wird angezeigt.
- Suchen Sie Ihr Knotendienstkonto in der Liste der Hauptkonten.
gcloud
Suchen 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
defaultist, verwenden Ihre Knoten das Compute Engine-Standarddienstkonto. Wenn die Ausgabe nichtdefaultist, verwenden Ihre Knoten ein benutzerdefiniertes Dienstkonto.Suchen Sie Ihre Google Cloud Projektnummer:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"Ersetzen Sie
PROJECT_IDdurch Ihre Projekt-ID.Die Ausgabe sieht etwa so aus:
12345678901Weisen Sie dem Dienstkonto die Rolle
roles/container.defaultNodeServiceAccountzu:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="SERVICE_ACCOUNT_NAME" \ --role="roles/container.defaultNodeServiceAccount"Ersetzen Sie
SERVICE_ACCOUNT_NAMEdurch 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.comErsetzen Sie
PROJECT_NUMBERdurch die Projektnummer aus dem vorherigen Schritt.Prüfen Sie, ob die Rolle erfolgreich zugewiesen 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
Recommender-Subtyps, um
Autopilot- und Standardcluster mit Knotendienstkonten mit fehlenden Berechtigungen zu
identifizieren. Recommender identifiziert nur Cluster, die am oder nach dem 1. Januar 2024 erstellt wurden. So finden und beheben Sie die fehlenden Berechtigungen mit Recommender:
Suchen Sie nach aktiven Empfehlungen in Ihrem Projekt für den Empfehlungssubtyp
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 gesucht werden sollen.PROJECT_ID: Ihre Google Cloud Projekt-ID.
Die Ausgabe sieht etwa so aus und zeigt, dass ein Cluster ein Knotendienstkonto mit fehlenden Berechtigungen hat:
associatedInsights: # lines omitted for clarity recommenderSubtype: NODE_SA_MISSING_PERMISSIONS stateInfo: state: ACTIVE targetResources: - //container.googleapis.com/projects/12345678901/locations/us-central1/clusters/cluster-1Es kann bis zu 24 Stunden dauern, bis die Empfehlung angezeigt wird. Eine detaillierte Anleitung finden Sie unter Insights und Empfehlungen anzeigen.
Suchen Sie für jeden Cluster in der Ausgabe des vorherigen Schritts die zugehörigen Knotendienstkonten und weisen Sie diesen Dienstkonten die erforderliche Rolle zu. Weitere Informationen finden Sie in der Anleitung im Abschnitt Knotendienstkonten die erforderliche Rolle für GKE zuweisen.
Nachdem Sie den identifizierten Knotendienstkonten die erforderliche Rolle zugewiesen haben, bleibt die Empfehlung möglicherweise bis zu 24 Stunden bestehen, es sei denn, Sie lehnen sie manuell ab.
Alle Knotendienstkonten mit fehlenden Berechtigungen identifizieren
Sie können ein Script ausführen, das in den Knotenpools der Standard-
und Autopilot-Clustern Ihres Projekts nach Knotendienstkonten sucht, die nicht die erforderlichen
Berechtigungen für GKE haben. Dieses Script verwendet die gcloud CLI und das
jq Dienstprogramm. Maximieren Sie den folgenden Abschnitt, um das Script aufzurufen:
Script 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"
fiDieses 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 in der Anleitung im Abschnitt Knotendienstkonten 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 Console oder der Google Cloud CLI können Sie prüfen, ob das Dienstkonto aus Ihrem Projekt entfernt wurde. Google Cloud
Console
Wechseln Sie in der Google Cloud Console zur Seite IAM & Verwaltung.
gcloud
Führen Sie dazu diesen Befehl aus:
gcloud projects get-iam-policy PROJECT_IDErsetzen Sie
PROJECT_IDdurch 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 der Console oder der gcloud CLI können Sie prüfen, ob das Dienstkonto in Ihrem Projekt deaktiviert ist.Google Cloud
Console
Wechseln Sie in der Google Cloud Console zur Seite IAM & Verwaltung.
gcloud
- Führen Sie 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:
Suchen Sie Ihre Google Cloud Projektnummer:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"Ersetzen Sie
PROJECT_IDdurch Ihre Projekt-ID.Die Ausgabe sieht etwa so aus:
12345678901Aktivieren Sie das Dienstkonto:
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.comErsetzen Sie
PROJECT_NUMBERdurch Ihre 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 Hilfeartikel Support erhalten. Dort finden Sie unter anderem Informationen zu folgenden Themen:
- Supportanfrage erstellen, indem Sie sich an Cloud Customer Care wenden.
- Support von der Community erhalten, indem Sie
Fragen auf Stack Overflow stellen
und mit dem
google-kubernetes-engineTag nach ähnlichen Problemen suchen. Sie können auch dem#kubernetes-engineSlack-Kanal beitreten, um weitere Unterstützung von der Community zu erhalten. - Probleme melden oder Featureanfragen stellen, indem Sie die öffentliche Problemverfolgung verwenden.