En esta página se explica cómo solucionar problemas con las cuentas de servicio de Google Kubernetes Engine (GKE).
Asignar el rol necesario para GKE a las cuentas de servicio de los nodos
Las cuentas de servicio de IAM que usan tus nodos de GKE deben tener todos los permisos incluidos en el rol de IAM Cuenta de servicio de nodo predeterminada de Kubernetes Engine (roles/container.defaultNodeServiceAccount
). Si a una cuenta de servicio de nodo de GKE le faltan uno o varios de estos permisos, GKE no podrá realizar tareas del sistema como las siguientes:
- Envía registros de aplicaciones y sistemas de nodos a Cloud Logging.
- Envía métricas del sistema y de las aplicaciones de los nodos a Cloud Monitoring.
- Gestionar el perfil de rendimiento de la herramienta de adaptación dinámica horizontal de pods.
Es posible que las cuentas de servicio de los nodos no tengan determinados permisos necesarios por motivos como los siguientes:
- La organización aplica la
restricción de la política de organización
iam.automaticIamGrantsForDefaultServiceAccounts
, que impide que Google Cloud conceda automáticamente roles de gestión de identidades y accesos a las cuentas de servicio de gestión de identidades y accesos predeterminadas. - El rol de IAM que asignas a las cuentas de servicio de nodos personalizados no incluye todos los permisos necesarios que sí incluye el rol
roles/container.defaultNodeServiceAccount
.
Si a la cuenta de servicio de tu nodo le faltan los permisos que requiere GKE, es posible que veas errores y avisos como los siguientes:
- En la Google Cloud consola, en la página Clústeres de Kubernetes, aparece un mensaje de error Conceder permisos críticos en la columna Notificaciones de un clúster específico.
En la Google Cloud consola, en la página de detalles de un clúster específico, aparece el siguiente mensaje de error:
Grant roles/container.defaultNodeServiceAccount role to Node service account to allow for non-degraded operations.
En los registros de actividad del administrador de Cloud Audit Logs de Google Cloud APIs como
monitoring.googleapis.com
, se muestran los siguientes valores si faltan los permisos correspondientes para acceder a esas APIs en la cuenta de servicio del nodo:- Gravedad:
ERROR
- Mensaje:
Permission denied (or the resource may not exist)
- Gravedad:
Faltan registros de nodos específicos en Cloud Logging y los registros de pods del agente de registro de esos nodos muestran errores
401
. Para obtener estos registros de pods, ejecuta el siguiente comando:[[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"
Si el resultado es
true
, significa que la carga de trabajo del sistema está experimentando401
errores, lo que indica que faltan permisos.
Para resolver este problema, concede el rol Cuenta de servicio de nodo predeterminada de Kubernetes Engine (roles/container.defaultNodeServiceAccount
) en el proyecto a la cuenta de servicio que está provocando los errores. Selecciona una de las opciones siguientes:
consola
Para encontrar el nombre de la cuenta de servicio que usan tus nodos, haz lo siguiente:
Ve a la página Clústeres de Kubernetes:
En la lista de clústeres, haga clic en el nombre del clúster que quiera inspeccionar.
Busca el nombre de la cuenta de servicio del nodo. Necesitarás este nombre más adelante.
- En el caso de los clústeres en modo Autopilot, ve a la sección Seguridad y busca el campo Cuenta de servicio.
- En el caso de los clústeres en modo estándar, haga lo siguiente:
- Haz clic en la pestaña Nodos.
- En la tabla Grupos de nodos, haz clic en el nombre de un grupo de nodos. Se abrirá la página Detalles del grupo de nodos.
- En la sección Seguridad, busca el campo Cuenta de servicio.
Si el valor del campo Cuenta de servicio es
default
, tus nodos usarán la cuenta de servicio predeterminada de Compute Engine. Si el valor de este campo no esdefault
, tus nodos usan una cuenta de servicio personalizada.
Para conceder el rol Kubernetes Engine Default Node Service Account
a la cuenta de servicio, sigue estos pasos:
Ve a la página Bienvenida:
En el campo Número de proyecto, haz clic en
Copiar en el portapapeles.Ve a la página Gestión de identidades y accesos:
Haz clic en
Conceder acceso.En el campo Nuevos principales, especifica el nombre de tu cuenta de servicio de nodo. Si tus nodos usan la cuenta de servicio predeterminada de Compute Engine, especifica el siguiente valor:
PROJECT_NUMBER-compute@developer.gserviceaccount.com
Sustituye
PROJECT_NUMBER
por el número de proyecto que has copiado.En el menú Seleccionar un rol, elige el rol Cuenta de servicio de nodo predeterminada de Kubernetes Engine.
Haz clic en Guardar.
Para verificar que se ha concedido el rol, haz lo siguiente:
- En la página IAM, haga clic en la pestaña Ver por roles.
- Expande la sección Cuenta de servicio de nodo predeterminada de Kubernetes Engine. Se muestra una lista de las entidades que tienen este rol.
- Busca tu cuenta de servicio de nodo en la lista de principales.
gcloud
Busca el nombre de la cuenta de servicio que usan tus nodos:
- En los clústeres del modo Autopilot, ejecuta el siguiente comando:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
- En los clústeres en modo Estándar, ejecuta el siguiente comando:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="table(nodePools.name,nodePools.config.serviceAccount)"
Si el resultado es
default
, tus nodos usan la cuenta de servicio predeterminada de Compute Engine. Si el resultado no esdefault
, tus nodos usan una cuenta de servicio personalizada.Busca tu Google Cloud número de proyecto:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Sustituye
PROJECT_ID
por el ID del proyecto.El resultado debería ser similar al siguiente:
12345678901
Asigna el rol
roles/container.defaultNodeServiceAccount
a la cuenta de servicio:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="SERVICE_ACCOUNT_NAME" \ --role="roles/container.defaultNodeServiceAccount"
Sustituye
SERVICE_ACCOUNT_NAME
por el nombre de la cuenta de servicio, que has encontrado en el paso anterior. Si tus nodos usan la cuenta de servicio predeterminada de Compute Engine, especifica el siguiente valor:serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com
Sustituye
PROJECT_NUMBER
por el número de proyecto del paso anterior.Comprueba que el rol se haya concedido correctamente:
gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \ --format='value(bindings.members)'
El resultado es el nombre de tu cuenta de servicio.
Identificar clústeres que tengan cuentas de servicio de nodo a las que les falten permisos
Usa las recomendaciones de GKE del NODE_SA_MISSING_PERMISSIONS
subtipo de recomendación para
identificar los clústeres de Autopilot y Estándar que tienen cuentas de servicio de nodos con permisos que faltan. Recommender identifica solo los clústeres que se crearon el 1 de enero del 2024 o después de esa fecha. Para buscar y corregir los permisos que faltan con Recommender, sigue estos pasos:
Busca recomendaciones activas en tu proyecto para el subtipo de recomendador
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"
Haz los cambios siguientes:
LOCATION
: la ubicación en la que se buscarán las recomendaciones.PROJECT_ID
: tu ID de proyecto Google Cloud .
El resultado es similar al siguiente, que indica que un clúster tiene una cuenta de servicio de nodo a la que le faltan permisos:
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
La recomendación puede tardar hasta 24 horas en aparecer. Para obtener instrucciones detalladas, consulta el artículo Ver estadísticas y recomendaciones.
Por cada clúster que aparezca en el resultado del paso anterior, busca las cuentas de servicio de nodo asociadas y asigna el rol necesario a esas cuentas. Para obtener más información, consulta las instrucciones de la sección Conceder a las cuentas de servicio de nodo el rol necesario para GKE.
Después de asignar el rol necesario a las cuentas de servicio de nodo identificadas, la recomendación puede permanecer hasta 24 horas, a menos que la rechaces manualmente.
Identificar todas las cuentas de servicio de nodos a las que les faltan permisos
Puedes ejecutar una secuencia de comandos que busque en los grupos de nodos de los clústeres Estándar y Autopilot de tu proyecto las cuentas de servicio de nodos que no tengan los permisos necesarios para GKE. Esta secuencia de comandos usa la CLI de gcloud y la utilidad jq
. Para ver la secuencia de comandos, despliega la siguiente sección:
Ver la secuencia de comandos
#!/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
Esta secuencia de comandos se aplica a todos los clústeres de GKE de tu proyecto.
Una vez que hayas identificado los nombres de las cuentas de servicio que no tienen los permisos necesarios, concédeles el rol obligatorio. Para obtener más información, consulta las instrucciones de la sección Conceder a las cuentas de servicio de los nodos el rol necesario para GKE.
Restaurar la cuenta de servicio predeterminada en tu proyecto de Google Cloud
La cuenta de servicio predeterminada de GKE, container-engine-robot
, puede desvincularse de un proyecto por error. El rol de agente de servicio de Kubernetes Engine (roles/container.serviceAgent
) es un rol de gestión de identidades y accesos (IAM) que concede a la cuenta de servicio los permisos para gestionar recursos de clústeres. Si eliminas esta vinculación de rol de la cuenta de servicio, la cuenta de servicio predeterminada se desvinculará del proyecto, lo que puede impedir que despliegues aplicaciones y realices otras operaciones de clúster.
Para comprobar si la cuenta de servicio se ha eliminado de tu proyecto, puedes usar la Google Cloud consola o la CLI de Google Cloud.
Consola
En la Google Cloud consola, ve a la página IAM y administración.
gcloud
Ejecuta el siguiente comando:
gcloud projects get-iam-policy PROJECT_ID
Sustituye
PROJECT_ID
por el ID del proyecto.
Si el panel de control o el comando no muestran container-engine-robot
entre tus cuentas de servicio, significa que el rol no está vinculado.
Para restaurar la vinculación del rol de agente de servicio de Kubernetes Engine (roles/container.serviceAgent
), ejecuta los siguientes comandos:
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
Confirma que se ha restaurado la vinculación de roles:
gcloud projects get-iam-policy PROJECT_ID
Si ves el nombre de la cuenta de servicio junto con el rol container.serviceAgent
, significa que se ha restaurado la vinculación del rol. Por ejemplo:
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Habilitar la cuenta de servicio predeterminada de Compute Engine
La cuenta de servicio que se usa en el grupo de nodos suele ser la cuenta de servicio predeterminada de Compute Engine. Si se desactiva esta cuenta de servicio predeterminada, es posible que los nodos no se registren en el clúster.
Para comprobar si la cuenta de servicio está desactivada en tu proyecto, puedes usar la Google Cloud consola o la CLI de gcloud.
Consola
En la Google Cloud consola, ve a la página IAM y administración.
gcloud
- Ejecuta el siguiente comando:
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
Si la cuenta de servicio está desactivada, ejecuta los siguientes comandos para habilitarla:
Busca tu Google Cloud número de proyecto:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Sustituye
PROJECT_ID
por el ID del proyecto.El resultado debería ser similar al siguiente:
12345678901
Habilita la cuenta de servicio:
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com
Sustituye
PROJECT_NUMBER
por el número de tu proyecto de la salida del paso anterior.
Para obtener más información, consulta Solucionar problemas de registro de nodos.
Error 400/403: Faltan permisos de edición en la cuenta
Si se elimina tu cuenta de servicio, es posible que veas un error de falta de permisos de edición. Para saber cómo solucionar este error, consulta Error 400 o 403: no tienes permisos de edición en la cuenta.
Siguientes pasos
Si no encuentras una solución a tu problema en la documentación, consulta la sección Obtener asistencia para obtener más ayuda, incluidos consejos sobre los siguientes temas:
- Abrir un caso de asistencia poniéndose en contacto con el equipo de Atención al Cliente de Cloud.
- Obtener asistencia de la comunidad haciendo preguntas en Stack Overflow
y usando la etiqueta
google-kubernetes-engine
para buscar problemas similares. También puedes unirte al#kubernetes-engine
canal de Slack para obtener más ayuda de la comunidad. - Abrir errores o solicitudes de funciones mediante el seguimiento de problemas público.