Nesta página, mostramos como resolver problemas com contas de serviço do Google Kubernetes Engine (GKE).
Conceda o papel necessário para o GKE às contas de serviço do nó
Para clusters do GKE que usam a versão 1.33 ou anterior do Kubernetes, as contas de serviço do IAM usadas pelos nós do GKE precisam ter todas as permissões incluídas no papel do IAM Conta de serviço de nó padrão do Kubernetes Engine (roles/container.defaultNodeServiceAccount
). Se uma conta de serviço do nó do GKE não tiver uma ou mais dessas permissões, o GKE não poderá realizar tarefas do sistema como:
- Envie registros do sistema e de aplicativos dos nós para o Cloud Logging.
- Enviar métricas de sistema e aplicativo dos nós para o Cloud Monitoring.
- Operar o perfil de desempenho do escalonador automático horizontal de pods.
As contas de serviço do nó podem não ter determinadas permissões necessárias por motivos como:
- A organização aplica a
restrição de política da organização
iam.automaticIamGrantsForDefaultServiceAccounts
, que impede que o Google Cloud conceda automaticamente papéis do IAM a contas de serviço padrão do IAM. - O papel do IAM concedido às contas de serviço de nós personalizados não inclui todas as permissões necessárias incluídas no papel
roles/container.defaultNodeServiceAccount
.
Se a conta de serviço do nó não tiver as permissões exigidas pelo GKE, você poderá encontrar erros e avisos como estes:
- No console Google Cloud , na página Clusters do Kubernetes, uma mensagem de erro Conceder permissões críticas aparece na coluna Notificações de um cluster específico.
No console Google Cloud , na página de detalhes de um cluster específico, aparece a seguinte mensagem de erro:
Grant roles/container.defaultNodeServiceAccount role to Node service account to allow for non-degraded operations.
Nos registros de auditoria do Cloud, os registros de atividade do administrador para APIs Google Cloud , como
monitoring.googleapis.com
, têm os seguintes valores se as permissões correspondentes para acessar essas APIs estiverem faltando na conta de serviço do nó:- Gravidade:
ERROR
- Mensagem:
Permission denied (or the resource may not exist)
- Gravidade:
Os registros de nós específicos estão ausentes do Cloud Logging, e os registros de pod do agente de geração de registros nesses nós mostram erros
401
. Para receber esses registros do pod, execute o seguinte comando:[[ $(kubectl logs -l k8s-app=fluentbit-gke -n kube-system -c fluentbit-gke | grep -cw "Received 401") -gt 0 ]] && echo "true" || echo "false"
Se a saída for
true
, a carga de trabalho do sistema estará apresentando erros de401
, o que indica falta de permissões.
Para resolver esse problema, conceda o papel de conta de serviço de nó padrão do Kubernetes Engine
(roles/container.defaultNodeServiceAccount
) no projeto à conta de serviço
que está causando os erros. Selecione uma das seguintes opções:
Console
Para encontrar o nome da conta de serviço usada pelos nós, faça o seguinte:
Acesse a página Clusters do Kubernetes:
Na lista de clusters, clique no nome do cluster que você quer inspecionar.
Encontre o nome da conta de serviço do nó. Você vai precisar desse nome mais tarde.
- Para clusters no modo Autopilot, na seção Segurança, encontre o campo Conta de serviço.
- Para clusters no modo padrão, faça o seguinte:
- Clique na guia Nós.
- Na tabela Pools de nós, clique no nome de um pool de nós. A página Detalhes do pool de nós é aberta.
- Na seção Segurança, encontre o campo Conta de serviço.
Se o valor no campo Conta de serviço for
default
, os nós usarão a conta de serviço padrão do Compute Engine. Se o valor nesse campo não fordefault
, seus nós usarão uma conta de serviço personalizada.
Para conceder o papel Kubernetes Engine Default Node Service Account
à
conta de serviço, faça o seguinte:
Acesse a página Boas-vindas:
No campo Número do projeto, clique em
Copiar para a área de transferência.Acesse a página do IAM:
Clique em
CONCEDER ACESSO.No campo Novos principais, especifique o nome da conta de serviço do nó. Se os nós usarem a conta de serviço padrão do Compute Engine, especifique o seguinte valor:
PROJECT_NUMBER-compute@developer.gserviceaccount.com
Substitua
PROJECT_NUMBER
pelo número do projeto que você copiou.No menu Selecionar um papel, escolha o papel Conta de serviço do nó padrão do Kubernetes Engine.
Clique em Salvar.
Para verificar se a função foi concedida, faça o seguinte:
- Na página IAM, clique na guia Visualizar por papéis.
- Expanda a seção Conta de serviço do nó padrão do Kubernetes Engine. Uma lista de principais que têm essa função é exibida.
- Encontre a conta de serviço do nó na lista de principais.
gcloud
Encontre o nome da conta de serviço usada pelos seus nós:
- Para clusters no modo Autopilot, execute o seguinte comando:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
- Para clusters no modo padrão, execute o seguinte comando:
gcloud container clusters describe CLUSTER_NAME \ --location=LOCATION \ --format="table(nodePools.name,nodePools.config.serviceAccount)"
Se a saída for
default
, os nós usarão a conta de serviço padrão do Compute Engine. Se a saída não fordefault
, seus nós usarão uma conta de serviço personalizada.Encontre o número do seu projeto Google Cloud :
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Substitua
PROJECT_ID
pela ID do seu projeto.O resultado será assim:
12345678901
Conceda o papel
roles/container.defaultNodeServiceAccount
à conta de serviço:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="SERVICE_ACCOUNT_NAME" \ --role="roles/container.defaultNodeServiceAccount"
Substitua
SERVICE_ACCOUNT_NAME
pelo nome da conta de serviço, que você encontrou na etapa anterior. Se os nós usarem a conta de serviço padrão do Compute Engine, especifique o valor a seguir:serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com
Substitua
PROJECT_NUMBER
pelo número do projeto da etapa anterior.Verifique se a função foi concedida:
gcloud projects get-iam-policy PROJECT_ID \ --flatten="bindings[].members" --filter=bindings.role:roles/container.defaultNodeServiceAccount \ --format='value(bindings.members)'
A saída é o nome da sua conta de serviço.
Identificar clusters com contas de serviço de nós sem permissões
Use as recomendações do GKE do NODE_SA_MISSING_PERMISSIONS
subtipo de recomendador para
identificar clusters do Autopilot e do Standard que têm contas
de serviço de nós com permissões ausentes. O Recommender identifica apenas clusters criados a partir de 1º de janeiro de 2024. Para encontrar e corrigir as permissões ausentes usando o Recomendador, faça o seguinte:
Encontre recomendações ativas no seu projeto para o 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"
Substitua:
LOCATION
: o local em que as recomendações serão encontradas.PROJECT_ID
: o ID do projeto Google Cloud .
A saída é semelhante à seguinte, que indica que um cluster tem uma conta de serviço de nó com permissões ausentes:
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
A recomendação pode levar até 24 horas para aparecer. Para instruções detalhadas, consulte ver insights e recomendações.
Para cada cluster na saída da etapa anterior, encontre as contas de serviço de nó associadas e conceda a função necessária a elas. Para detalhes, consulte as instruções na seção Conceder às contas de serviço do nó o papel necessário para o GKE.
Depois de conceder o papel necessário às contas de serviço do nó identificadas, a recomendação pode persistir por até 24 horas, a menos que você a dispense manualmente.
Identificar todas as contas de serviço de nó com permissões ausentes
É possível executar um script que pesquisa pools de nós nos clusters Standard e Autopilot do projeto para encontrar contas de serviço de nós que não têm as permissões necessárias para o GKE. Esse script usa a CLI gcloud e o utilitário
jq
. Para ver o script, expanda a seção a seguir:
Ver o script
#!/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
Esse script se aplica a todos os clusters do GKE no seu projeto.
Depois de identificar os nomes das contas de serviço com permissões ausentes, conceda a elas o papel necessário. Para mais detalhes, consulte as instruções na seção Conceder às contas de serviço do nó o papel necessário para o GKE.
Restaurar a conta de serviço padrão para seu projeto Google Cloud
A conta de serviço padrão do GKE, container-engine-robot
, pode
ser acidentalmente desassociada de um projeto. O papel de agente de serviço do Kubernetes Engine (roles/container.serviceAgent
) é um papel de Identity and Access Management (IAM) que concede à conta de serviço as permissões para gerenciar recursos de cluster. Se você remover essa vinculação de papel da conta de serviço, a conta de serviço padrão ficará desvinculada do projeto, o que poderá impedir a implantação de aplicativos e a execução de outras operações de cluster.
Para verificar se a conta de serviço foi removida do seu projeto, use o console Google Cloud ou a Google Cloud CLI.
Console
No Google Cloud console, acesse a página IAM e administrador.
gcloud
Execute este comando:
gcloud projects get-iam-policy PROJECT_ID
Substitua
PROJECT_ID
pela ID do projeto.
Se o painel ou o comando não mostrar container-engine-robot
entre suas contas de serviço, o papel está desvinculado.
Para restaurar a vinculação de papel de agente de serviço do Kubernetes Engine (roles/container.serviceAgent
), execute os seguintes 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
Confirme se a vinculação de função foi restaurada:
gcloud projects get-iam-policy PROJECT_ID
Se o nome da conta de serviço estiver com a função container.serviceAgent
, a vinculação de papel foi restaurada. Por exemplo:
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Ativar a conta de serviço padrão do Compute Engine
A conta de serviço usada para o pool de nós geralmente é a conta de serviço padrão do Compute Engine. Se essa conta de serviço padrão for desativada, os nós poderão não ser registrados no cluster.
Para saber se a conta de serviço está desativada no seu projeto, use o console doGoogle Cloud ou a CLI gcloud.
Console
No Google Cloud console, acesse a página IAM e administrador.
gcloud
- Execute este comando:
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
Se a conta de serviço estiver desativada, execute os seguintes comandos para ativá-la:
Encontre o número do seu projeto Google Cloud :
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Substitua
PROJECT_ID
pela ID do seu projeto.O resultado será assim:
12345678901
Ative a conta de serviço:
gcloud iam service-accounts enable PROJECT_NUMBER-compute@developer.gserviceaccount.com
Substitua
PROJECT_NUMBER
pelo número do projeto na saída da etapa anterior.
Para mais informações, consulte Resolver problemas no registro de nós.
Erro 400/403: permissões de edição ausentes na conta
Se a conta de serviço for excluída, talvez apareça um erro de permissões de edição ausentes. Para saber como resolver esse erro, consulte Erro 400/403: permissões de edição ausentes na conta.
A seguir
Se você não encontrar uma solução para seu problema na documentação, consulte Receber suporte para mais ajuda, incluindo conselhos sobre os seguintes tópicos:
- Abrir um caso de suporte entrando em contato com o Cloud Customer Care.
- Receber suporte da comunidade fazendo perguntas no StackOverflow e usando a tag
google-kubernetes-engine
para pesquisar problemas semelhantes. Você também pode participar do canal do Slack#kubernetes-engine
para receber mais suporte da comunidade. - Abrir bugs ou solicitações de recursos usando o Issue Tracker público.