Esta página ajuda a resolver os erros 400, 401, 403 e 404 que pode encontrar quando usa o Google Kubernetes Engine (GKE).
Problema: erros de autenticação e autorização
Quando se liga a clusters do GKE, pode receber um erro de autenticação e autorização com o código de estado HTTP 401 (Unauthorized)
. Este problema pode ocorrer quando tenta executar um comando kubectl
no cluster do GKE a partir de um ambiente local.
A causa deste problema pode ser uma das seguintes:
- O plugin de autenticação
gke-gcloud-auth-plugin
não está instalado nem configurado corretamente. - Não tem as autorizações necessárias para se ligar ao servidor da API do cluster e executar comandos
kubectl
.
Para diagnosticar a causa, conclua os passos nas secções seguintes:
Ligue-se ao cluster através de curl
Para diagnosticar a causa do erro de autenticação e autorização, ligue-se ao cluster através de curl
. A utilização de curl
ignora a ferramenta de linha de comandos kubectl
e o plug-in gke-gcloud-auth-plugin
.
Defina variáveis de ambiente:
APISERVER=https://$(gcloud container clusters describe CLUSTER_NAME \ --location=COMPUTE_LOCATION --format "value(endpoint)") TOKEN=$(gcloud auth print-access-token)
Verifique se o token de acesso é válido:
curl https://oauth2.googleapis.com/tokeninfo?access_token=$TOKEN
Quando tem um token de acesso válido, este comando envia um pedido para o servidor OAuth 2.0 da Google, e o servidor responde com informações sobre o token.
Tente estabelecer ligação ao ponto final da API principal no servidor da API:
# Get cluster CA certificate gcloud container clusters describe CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --format "value(masterAuth.clusterCaCertificate)" | \ base64 -d > /tmp/ca.crt # Make API call with authentication and CA certificate curl -s -X GET "${APISERVER}/api/v1/namespaces" \ --header "Authorization: Bearer $TOKEN" \ --cacert /tmp/ca.crt
Se o comando
curl
for bem-sucedido, é apresentada uma lista de espaços de nomes. Proceda à verificação para saber se o plug-in é a causa através dos passos na secção Configure o plug-in no kubeconfig.Se o comando
curl
falhar com um resultado semelhante ao seguinte, não tem as autorizações corretas para aceder ao cluster:{ "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 }
Para resolver este problema, consulte o seu administrador para obter as autorizações corretas para aceder ao cluster.
Configure a utilização do plug-in no kubeconfig
Se estiver a receber erros de autenticação e autorização ao estabelecer ligação aos seus clusters, mas conseguiu estabelecer ligação ao cluster através do
curl
, certifique-se de que consegue aceder ao cluster sem precisar do plug-in gke-gcloud-auth-plugin
.
Para resolver este problema, configure o seu ambiente local para ignorar o ficheiro binário gke-gcloud-auth-plugin
ao autenticar no cluster. Nos clientes do Kubernetes que executam a versão 1.25 e posteriores, o binário gke-gcloud-auth-plugin
é obrigatório, pelo que tem de usar uma versão 1.24 ou anterior para a ferramenta de linha de comandos kubectl
.
Siga estes passos para aceder ao cluster sem precisar do plug-in:
Instale a ferramenta de linha de comandos
kubectl
com a versão 1.24 ou anterior através decurl
. O exemplo seguinte instala a ferramenta com a versão 1.24:curl -LO https://dl.k8s.io/release/v1.24.0/bin/linux/amd64/kubectl
Abra o ficheiro de script de arranque da shell num editor de texto. Por exemplo, abra
.bashrc
para a shell Bash:vi ~/.bashrc
Se estiver a usar o macOS, use
~/.bash_profile
em vez de.bashrc
nestas instruções.Adicione a seguinte linha ao ficheiro de script de arranque e guarde-o:
export USE_GKE_GCLOUD_AUTH_PLUGIN=False
Execute o script de arranque:
source ~/.bashrc
Obtenha credenciais para o seu cluster, que configuram o ficheiro
.kube/config
:gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION
Substitua o seguinte:
CLUSTER_NAME
: o nome do cluster.COMPUTE_LOCATION
: a localização do Compute Engine.
Executar um comando
kubectl
. Por exemplo:kubectl cluster-info
Se receber um erro 401 ou um erro de autorização semelhante depois de executar estes comandos, certifique-se de que tem as autorizações corretas e, em seguida, volte a executar o passo que devolveu o erro.
Erro 400: o node pool requer recriação
O seguinte erro pode ocorrer quando tenta realizar uma ação que recria o plano de controlo e os nós:
ERROR: (gcloud.container.clusters.update) ResponseError: code=400, message=Node pool "test-pool-1" requires recreation.
Por exemplo, este erro pode ocorrer quando conclui uma rotação de credenciais em curso.
No back-end, os conjuntos de nós são marcados para recriação, mas a operação de recriação real pode demorar algum tempo a começar. Por este motivo, a operação falha porque o GKE ainda não recriou um ou mais conjuntos de nós no seu cluster.
Para resolver este problema, escolha uma das seguintes soluções:
- Aguarde que a recriação ocorra. Isto pode demorar horas, dias ou semanas, dependendo de fatores como as janelas de manutenção e as exclusões existentes.
Inicie manualmente uma recriação dos conjuntos de nós afetados iniciando uma atualização de versão para a mesma versão do plano de controlo.
Para iniciar uma recriação, execute o seguinte comando:
gcloud container clusters upgrade CLUSTER_NAME \ --node-pool=POOL_NAME
Após a conclusão da atualização, tente novamente a operação.
Erro 401: não autorizado
Identifique clusters com contas de serviço de nós que não têm autorizações críticas
Para identificar clusters com contas de serviço de nós em que faltam autorizações críticas, use as recomendações do GKE do NODE_SA_MISSING_PERMISSIONS
subtipo de recomendador:
- Use a Google Cloud consola. Aceda à página Clusters do Kubernetes e verifique se existe a recomendação Conceder autorizações críticas na coluna Notificações para clusters específicos.
Use a CLI gcloud ou a API Recommender, especificando o subtipo do recomendador
NODE_SA_MISSING_PERMISSIONS
.Para consultar recomendações, execute o seguinte comando:
gcloud recommender recommendations list \ --recommender=google.container.DiagnosisRecommender \ --location LOCATION \ --project PROJECT_ID \ --format yaml \ --filter="recommenderSubtype:NODE_SA_MISSING_PERMISSIONS"
Tenha em atenção que a recomendação pode demorar até 24 horas a ser apresentada. Para ver instruções detalhadas, saiba como ver estatísticas e recomendações.
Para implementar esta recomendação, conceda a função roles/container.defaultNodeServiceAccount
à conta de serviço do nó.
Pode executar um script que procure pools de nós nos clusters padrão e do Autopilot do seu projeto para quaisquer contas de serviço de nós que não tenham as autorizações necessárias para o GKE. Este script usa a CLI gcloud e o utilitário jq
. Para ver o script, expanda a secção seguinte:
Veja o guião
#!/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
Identifique contas de serviço de nós com autorizações críticas em falta num cluster
O GKE usa contas de serviço da IAM anexadas aos seus nós para
executar tarefas do sistema, como registo e monitorização. No mínimo, estas contas de serviço de nós
têm de ter a função
Conta de serviço de nós predefinida do Kubernetes Engine
(roles/container.defaultNodeServiceAccount
) no seu projeto. Por predefinição,
o GKE usa a
conta de serviço predefinida do Compute Engine,
que é criada automaticamente no seu projeto, como a conta de serviço do nó.
Se a sua organização aplicar a restrição da política da organização iam.automaticIamGrantsForDefaultServiceAccounts
, a conta de serviço do Compute Engine predefinida no seu projeto pode não receber automaticamente as autorizações necessárias para o GKE.
-
Encontre o nome da conta de serviço que os seus nós usam:
Consola
- Aceda à página Clusters do Kubernetes:
- Na lista de clusters, clique no nome do cluster que quer inspecionar.
- Consoante o modo de funcionamento do cluster, faça uma das seguintes ações:
- Para clusters do modo de piloto automático, na secção Segurança, encontre o campo Conta de serviço.
- Para clusters do modo padrão, faça o seguinte:
- Clique no separador Nós.
- Na tabela Conjuntos de nós, clique no nome de um conjunto de nós. É apresentada a página Detalhes do conjunto de nós.
- Na secção Segurança, encontre o campo Conta de serviço.
Se o valor no campo Conta de serviço for
default
, os seus nós usam a conta de serviço predefinida do Compute Engine. Se o valor neste campo não fordefault
, os seus nós usam uma conta de serviço personalizada. Para conceder a função necessária a uma conta de serviço personalizada, consulte o artigo Use contas de serviço da IAM com o menor número de privilégios.gcloud
Para clusters no modo Autopilot, execute o seguinte comando:
gcloud container clusters describe
CLUSTER_NAME
\ --location=LOCATION
\ --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccountPara 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 o resultado for
default
, os seus nós usam a conta de serviço predefinida do Compute Engine. Se o resultado não fordefault
, os seus nós usam uma conta de serviço personalizada. Para conceder a função necessária a uma conta de serviço personalizada, consulte o artigo Use contas de serviço da IAM com o menor número de privilégios. -
Para conceder a função
roles/container.defaultNodeServiceAccount
à conta de serviço predefinida do Compute Engine, conclua os passos seguintes:consola
- Aceda à página Boas-vindas:
- No campo Número do projeto, clique em Copiar para a área de transferência.
- Aceda à página IAM:
- Clique em Conceder acesso.
- No campo Novos responsáveis, especifique o seguinte valor:
SubstituaPROJECT_NUMBER-compute@developer.gserviceaccount.com
PROJECT_NUMBER
pelo número do projeto que copiou. - No menu Selecionar uma função, selecione a função Conta de serviço do nó predefinido do Kubernetes Engine.
- Clique em Guardar.
gcloud
- Encontre o seu Google Cloud número do projeto:
gcloud projects describe PROJECT_ID \ --format="value(projectNumber)"
Substitua
PROJECT_ID
pelo ID do seu projeto.O resultado é semelhante ao seguinte:
12345678901
- Conceda a função
roles/container.defaultNodeServiceAccount
à conta de serviço predefinida do Compute Engine:gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role="roles/container.defaultNodeServiceAccount"
Substitua
PROJECT_NUMBER
pelo número do projeto do passo anterior.
Erro 403: autorizações insuficientes
O seguinte erro ocorre quando tenta estabelecer ligação a um cluster do GKE usando o gcloud container clusters get-credentials
, mas a conta não tem autorização para aceder ao servidor da API Kubernetes:
ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Required "container.clusters.get" permission(s) for "projects/<your-project>/locations/<region>/clusters/<your-cluster>".
Para resolver este problema, conclua os seguintes passos:
Identifique a conta que tem o problema de acesso:
gcloud auth list
Conceda o acesso necessário à conta através das instruções em Autenticação no servidor da API Kubernetes.
Erro 403: limite de novas tentativas esgotado
O seguinte erro pode ocorrer quando tenta criar um cluster do GKE:
Error: googleapi: Error 403: Retry budget exhausted: Google Compute Engine:
Required permission 'PERMISSION_NAME' for 'RESOURCE_NAME'.
Nesta mensagem de erro, aplicam-se as seguintes variáveis:
PERMISSION_NAME
: o nome de uma autorização, comocompute.regions.get
.RESOURCE_NAME
: o caminho para o recurso ao qual estava a tentar aceder, como uma região do Compute Engine. Google Cloud
Este erro ocorre se a conta de serviço do IAM associada ao cluster não tiver as autorizações mínimas necessárias para criar o cluster.
Para resolver este problema, faça o seguinte:
- Crie ou modifique uma conta de serviço do IAM para ter todas as autorizações necessárias para executar um cluster do GKE. Para obter instruções, consulte o artigo Use contas de serviço IAM com o menor número de privilégios.
- Especifique a conta de serviço do IAM atualizada no comando de criação do cluster com a flag
--service-account
. Para ver instruções, consulte o artigo Crie um cluster do Autopilot.
Em alternativa, omita a flag --service-account
para permitir que o GKE use a conta de serviço predefinida do Compute Engine no projeto, que tem as autorizações necessárias por predefinição.
Erro 404: recurso não encontrado
Se receber um erro 404, recurso não encontrado, ao chamar comandos gcloud container
, resolva o problema autenticando novamente na CLI Google Cloud:
gcloud auth login
Erro 400/403: autorizações de edição em falta na conta
Um erro de autorizações de edição em falta na conta (erro 400 ou 403) indica que um dos seguintes foi eliminado ou editado manualmente:
- A sua conta de serviço predefinida do Compute Engine.
- O agente do serviço das APIs Google.
- A conta de serviço associada ao GKE.
Quando ativa a API Compute Engine ou GKE, Google Cloud são criadas as seguintes contas de serviço e agentes:
- Conta de serviço predefinida do Compute Engine no seu projeto. Por predefinição, o GKE anexa esta conta de serviço aos nós para tarefas do sistema, como o registo e a monitorização.
- Agente do serviço de APIs Google num projeto gerido pela Google, com autorizações de edição no seu projeto.
- Agente de serviço do Google Kubernetes Engine num projeto gerido pela Google, com a função de agente de serviço do Kubernetes Engine no seu projeto.
A criação do cluster e toda a gestão falham se, em qualquer altura, alguém editar essas autorizações, remover as associações de funções no projeto, remover a conta de serviço por completo ou desativar a API.
Valide as autorizações do agente de serviço do GKE
Para verificar se a conta de serviço do Google Kubernetes Engine tem a função Agente de serviço do Kubernetes Engine atribuída no projeto, conclua os seguintes passos:
Determine o nome da sua conta de serviço do Google Kubernetes Engine. Todas as contas de serviço têm o seguinte formato:
service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
Substitua
PROJECT_NUMBER
pelo seu número do projeto.Verifique se a sua conta de serviço do Google Kubernetes Engine não tem a função de agente de serviço do Kubernetes Engine atribuída no projeto:
gcloud projects get-iam-policy PROJECT_ID
Substitua
PROJECT_ID
pelo ID do seu projeto.
Para corrigir o problema, se alguém tiver removido a função Agente de serviço do Kubernetes Engine da sua conta de serviço do Google Kubernetes Engine, adicione-a novamente. Caso contrário, use as seguintes instruções para reativar a API Kubernetes Engine, que restaura as contas de serviço e as autorizações:
Consola
Aceda à página APIs e serviços na Google Cloud consola.
Selecione o seu projeto.
Clique em Ativar APIs e serviços.
Pesquise Kubernetes e, em seguida, selecione a API nos resultados da pesquisa.
Clique em Ativar. Se ativou a API anteriormente, tem de a desativar e, em seguida, ativá-la novamente. A ativação da API e dos serviços relacionados pode demorar alguns minutos.
gcloud
Execute os seguintes comandos na CLI gcloud:
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
O que se segue?
Se não conseguir encontrar uma solução para o seu problema na documentação, consulte a secção Obtenha apoio técnico para receber mais ajuda, incluindo aconselhamento sobre os seguintes tópicos:
- Abrindo um registo de apoio ao cliente através do contacto com o Cloud Customer Care.
- Receber apoio técnico da comunidade fazendo perguntas no StackOverflow e usando a etiqueta
google-kubernetes-engine
para pesquisar problemas semelhantes. Também pode juntar-se ao#kubernetes-engine
canal do Slack para receber mais apoio técnico da comunidade. - Abrir erros ou pedidos de funcionalidades através do rastreador de problemas público.