Resolver problemas de autenticação do GKE

Nesta página, mostramos como resolver problemas relacionados a configurações de segurança nos clusters do Autopilot e do Standard do Google Kubernetes Engine (GKE).

RBAC e IAM

Contas do IAM autenticadas não realizam ações no cluster

O problema a seguir ocorre quando você tenta executar uma ação no cluster, mas o GKE não consegue encontrar uma política de RBAC que autorize a ação. O GKE tenta encontrar uma política do IAM que conceda a mesma permissão. Se isso falhar, você encontrará uma mensagem de erro semelhante a esta:

Error from server (Forbidden): roles.rbac.authorization.k8s.io is forbidden:
User "example-account@example-project.iam.gserviceaccount.com" cannot list resource "roles" in
API group "rbac.authorization.k8s.io" in the namespace "kube-system": requires
one of ["container.roles.list"] permission(s).

Para resolver esse problema, use uma política de RBAC a fim de conceder as permissões para a tentativa de ação. Por exemplo, para resolver o problema no exemplo anterior, conceda um papel que tenha a permissão list em objetos roles no namespace kube-system. Para instruções, consulte Autorizar ações em clusters usando o controle de acesso baseado em papéis.

Federação de identidade da carga de trabalho para o GKE

O pod não pode se autenticar em Google Cloud

Se não for possível autenticar o aplicativo no Google Cloud, verifique se as configurações a seguir estão corretas:

  1. Verifique se você ativou a API Service Account Credentials do IAM no projeto que contém o cluster do GKE.

    Ativar a API IAM Credentials

  2. Confirme se a federação de identidade da carga de trabalho do GKE está ativada no cluster. Para isso, verifique se ele tem um pool de identidades de cargas de trabalho definido:

    gcloud container clusters describe CLUSTER_NAME \
        --format="value(workloadIdentityConfig.workloadPool)"
    

    Substitua CLUSTER_NAME pelo nome do cluster do GKE.

    Se você ainda não tiver especificado uma zona ou região padrão para gcloud, talvez seja necessário especificar uma flag --region ou --zone ao executar este comando.

  3. Verifique se o servidor de metadados do GKE está configurado no pool de nós em que o aplicativo está em execução:

    gcloud container node-pools describe NODEPOOL_NAME \
        --cluster=CLUSTER_NAME \
        --format="value(config.workloadMetadataConfig.mode)"
    

    Substitua:

    • NODEPOOL_NAME pelo nome do pool de nós.
    • CLUSTER_NAME pelo nome do cluster do GKE.
  4. Se você tiver uma política de rede de cluster, permita que a saída seja permitida para 169.254.169.252/32 na porta 988. Para clusters que executam o GKE Dataplane V2, é necessário permitir a saída para 169.254.169.254/32 na porta 80.

    kubectl describe networkpolicy NETWORK_POLICY_NAME
    

    Substitua NETWORK_POLICY_NAME pelo nome da política de rede do GKE.

Se a configuração vincular contas de serviço do Kubernetes a contas de serviço do IAM, verifique o seguinte:

  1. Confira se a conta de serviço do Kubernetes está anotada corretamente:

    kubectl describe serviceaccount \
        --namespace NAMESPACE KSA_NAME
    

    Substitua:

    • NAMESPACE pelo namespace do cluster do GKE.
    • KSA pelo nome da conta de serviço do Kubernetes.

    A saída esperada contém uma anotação semelhante a esta:

    iam.gke.io/gcp-service-account: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
    
  2. Verifique se a conta de serviço do IAM está configurada corretamente:

    gcloud iam service-accounts get-iam-policy \
        GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
    

    A saída esperada contém uma vinculação semelhante a esta:

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]
      role: roles/iam.workloadIdentityUser
    

Erro: formato inválido do ID da conta

O erro a seguir ocorre quando você tenta uma operação que exige um endereço de e-mail de conta de serviço do IAM, como criar manualmente um URL assinado do Cloud Storage:

ERROR: Error: Invalid form of account ID test_account.svc.id.goog. Should be [Gaia ID |Email |Unique ID |] of the account
# Multiple lines are omitted here
command terminated with exit code 137

Esse erro ocorre quando você usa uma anotação para vincular contas de serviço do Kubernetes a contas de serviço do IAM em vez de usar um identificador principal do IAM para configurar a federação de identidade da carga de trabalho para o GKE.

Por padrão, o servidor de metadados do GKE retorna um valor de SERVICEACCOUNT_NAME.svc.id.goog como o identificador da conta de serviço para ServiceAccounts vinculadas. Esse identificador não usa a sintaxe do identificador principal do IAM.

Para resolver esse erro, adicione a anotação iam.gke.io/return-principal-id-as-email="true" à conta de serviço do Kubernetes do pod:

kubectl annotate serviceaccount KSA_NAME \
    --namespace=NAMESPACE \
    iam.gke.io/return-principal-id-as-email="true"

Substitua:

  • KSA_NAME: o nome da ServiceAccount do Kubernetes.
  • NAMESPACE: o namespace da ServiceAccount.

Acesso negado à conta de serviço do IAM

Pode ser que os pods não consigam acessar um recurso com a Federação de Identidade da Carga de Trabalho para GKE imediatamente depois de acrescentar vinculações de papel do IAM. É mais provável que a falha de acesso ocorra em pipelines de implantação ou em configurações declarativas Google Cloud em que recursos como políticas de permissão do IAM, vinculações de função e pods do Kubernetes são criados em conjunto. A seguinte mensagem de erro aparece nos registros do pod:

HTTP/403: generic::permission_denied: loading: GenerateAccessToken("SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com", ""): googleapi: Error 403: Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).

Este erro pode ser causado pela propagação de mudanças de acesso no IAM, o que significa que mudanças de acesso, tais como permissões de função, levam tempo para se propagar pelo sistema. Para permissões de função, a propagação geralmente leva cerca de dois minutos, mas pode levar sete minutos ou mais. Para mais informações, acesse Propagação de mudança de acesso.

Para resolver esse erro, adicione um atraso para que os pods tentem acessar os recursos do Google Cloud depois da criação.

Problemas de resolução de DNS

Nesta seção, descrevemos como identificar e resolver erros de conexão de pods com APIs do Google Cloud causados por problemas de resolução de DNS. Se as etapas desta seção não resolverem os erros de conexão, consulte a seção Erros de tempo limite na inicialização do pod.

Algumas bibliotecas de cliente Google Cloud são configuradas para se conectar aos servidores de metadados do GKE e do Compute Engine resolvendo o nome DNS metadata.google.internal. Para essas bibliotecas, a resolução de DNS íntegra no cluster é uma dependência essencial para que suas cargas de trabalho sejam autenticadas nos serviços doGoogle Cloud .

A forma como você detecta esse problema depende dos detalhes do aplicativo implantado, o que inclui a configuração da geração de registros. Procure mensagens de erro que informem para configurar GOOGLE_APPLICATION_CREDENTIALS, que suas solicitações para um serviçoGoogle Cloud foram rejeitadas porque não tinham credenciais ou que o servidor de metadados não foi encontrado.

Por exemplo, a seguinte mensagem de erro pode indicar um problema de resolução de DNS:

ComputeEngineCredentials cannot find the metadata server. This is likely because code is not running on Google Compute Engine

Se você encontrar problemas com a resolução de DNS de metadata.google.internal, algumas bibliotecas de cliente Google Cloud podem ser instruídas a ignorar a resolução de DNS definindo a variável de ambiente GCE_METADATA_HOST como 169.254.169.254:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  namespace: default
spec:
  containers:
  - image: debian
    name: main
    command: ["sleep", "infinity"]
    env:
    - name: GCE_METADATA_HOST
      value: "169.254.169.254"

Esse é o endereço IP fixado no código em que o serviço de metadados está sempre disponível nas plataformas de computação do Google Cloud .

As seguintes bibliotecas Google Cloud são compatíveis:

Erros de tempo limite na inicialização do pod

O servidor de metadados do GKE precisa de alguns segundos para começar a aceitar solicitações em um novo pod. As tentativas de autenticação usando a federação de identidade da carga de trabalho para o GKE nos primeiros segundos da vida de um pod podem falhar em aplicativos e bibliotecas de cliente do Google Cloud configuradas com um tempo limite curto.

Se você encontrar erros de tempo limite, tente o seguinte:

  • Atualize as bibliotecas de cliente Google Cloud usadas pelas suas cargas de trabalho.
  • Altere o código do aplicativo para aguardar alguns segundos e tente novamente.
  • Implante um initContainer que aguarde até que o servidor de metadados do GKE esteja pronto antes de executar o contêiner principal do pod.

    Por exemplo, o seguinte manifesto é para um pod com initContainer:

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-with-initcontainer
    spec:
      serviceAccountName: KSA_NAME
      initContainers:
      - image:  gcr.io/google.com/cloudsdktool/cloud-sdk:alpine
        name: workload-identity-initcontainer
        command:
        - '/bin/bash'
        - '-c'
        - |
          curl -sS -H 'Metadata-Flavor: Google' 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token' --retry 30 --retry-connrefused --retry-max-time 60 --connect-timeout 3 --fail --retry-all-errors > /dev/null && exit 0 || echo 'Retry limit exceeded. Failed to wait for metadata server to be available. Check if the gke-metadata-server Pod in the kube-system namespace is healthy.' >&2; exit 1
      containers:
      - image: gcr.io/your-project/your-image
        name: your-main-application-container
    

A federação de identidade da carga de trabalho para o GKE falha devido à indisponibilidade do plano de controle

O servidor de metadados não pode retornar a federação de identidade da carga de trabalho do GKE quando o plano de controle do cluster não está disponível. As chamadas para o servidor de metadados retornam o código de status 500.

Uma entrada de registro pode ser semelhante a esta na Análise de registros:

dial tcp 35.232.136.58:443: connect: connection refused

Esse comportamento leva à indisponibilidade da federação de identidade da carga de trabalho para o GKE.

O plano de controle pode estar indisponível em clusters zonais na manutenção do cluster, como rotação de IPs, upgrade de VMs do plano de controle ou redimensionamento de clusters ou pools de nós. Consulte Como escolher um plano de controle regional ou zonal para saber mais sobre a disponibilidade do plano de controle. Alternar para um cluster regional elimina esse problema.

A federação de identidade da carga de trabalho para autenticação do GKE falha em clusters usando o Istio

Talvez você veja erros semelhantes aos seguintes quando o aplicativo for iniciado e tentar se comunicar com um endpoint:

Connection refused (169.254.169.254:80)
Connection timeout

Esses erros podem ocorrer quando o aplicativo tenta fazer uma conexão de rede antes que o contêiner istio-proxy esteja pronto. Por padrão, o Istio e o Cloud Service Mesh permitem que as cargas de trabalho enviem solicitações assim que forem iniciadas, independente de o proxy da malha de serviço que intercepta e redireciona o tráfego estar em execução. Para pods que usam a federação de identidade da carga de trabalho para o GKE, essas solicitações iniciais que ocorrem antes do início do proxy podem não chegar ao servidor de metadados do GKE. Como resultado, a autenticação nas APIs Google Cloud falha. Se você não configurar seus aplicativos para repetir as solicitações, as cargas de trabalho poderão falhar.

Para confirmar se esse problema é a causa dos seus erros, consulte os registros e verifique se o contêiner istio-proxy foi iniciado corretamente:

  1. No console do Google Cloud , acesse a página Análise de registros.

    Acessar o Explorador de registros

  2. No painel de consulta, digite a seguinte consulta:

    (resource.type="k8s_container"
    resource.labels.pod_name="POD_NAME"
    textPayload:"Envoy proxy is ready" OR textPayload:"ERROR_MESSAGE")
    OR
    (resource.type="k8s_pod"
    logName:"events"
    jsonPayload.involvedObject.name="POD_NAME")
    

    Substitua:

    • POD_NAME: o nome do pod com a carga de trabalho afetada.
    • ERROR_MESSAGE: o erro que o aplicativo recebeu (connection timeout ou connection refused).
  3. Clique em Executar consulta.

  4. Analise a saída e verifique quando o contêiner istio-proxy ficou pronto.

    No exemplo a seguir, o aplicativo tentou fazer uma chamada gRPC. No entanto, como o contêiner istio-proxy ainda estava sendo inicializado, o aplicativo recebeu um erro Connection refused. O carimbo de data/hora ao lado da mensagem Envoy proxy is ready indica quando o contêiner istio-proxy ficou pronto para solicitações de conexão:

    2024-11-11T18:37:03Z started container istio-init
    2024-11-11T18:37:12Z started container gcs-fetch
    2024-11-11T18:37:42Z Initializing environment
    2024-11-11T18:37:55Z Started container istio-proxy
    2024-11-11T18:38:06Z StatusCode="Unavailable", Detail="Error starting gRPC call. HttpRequestException: Connection refused (169.254.169.254:80)
    2024-11-11T18:38:13Z Envoy proxy is ready
    

Para resolver esse problema e evitar que ele se repita, tente uma das seguintes opções de configuração por carga de trabalho:

  • Impeça que os aplicativos enviem solicitações até que a carga de trabalho do proxy esteja pronta. Adicione a seguinte anotação ao campo metadata.annotations na especificação do pod:

    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  • Configure o Istio ou o Cloud Service Mesh para excluir o endereço IP do servidor de metadados do GKE do redirecionamento. Adicione a seguinte anotação ao campo metadata.annotations da especificação do pod:

    traffic.sidecar.istio.io/excludeOutboundIPRanges: 169.254.169.254/32
    

No Istio de código aberto, é possível mitigar esse problema para todos os pods definindo uma das seguintes opções de configuração global:

  • Exclua o endereço IP do servidor de metadados do GKE do redirecionamento: atualize a opção de configuração global global.proxy.excludeIPRanges para adicionar o intervalo de endereços IP 169.254.169.254/32.

  • Impedir que os aplicativos enviem solicitações até que o proxy seja iniciado: adicione a opção de configuração global global.proxy.holdApplicationUntilProxyStarts com o valor true à sua configuração do Istio.

O pod gke-metadata-server está falhando

O pod DaemonSet do sistema gke-metadata-server facilita a federação de identidade da carga de trabalho do GKE nos nós. O pod usa recursos de memória proporcionais ao número de contas de serviço do Kubernetes no cluster.

O problema a seguir ocorre quando o uso de recursos do pod gke-metadata-server excede os limites. O kubelet remove o pod com um erro de memória insuficiente. Você poderá ter esse problema se o cluster tiver mais de 3.000 contas de serviço do Kubernetes.

Para identificar o problema, faça o seguinte:

  1. Encontre pods gke-metadata-server com falha no namespace kube-system:

    kubectl get pods -n=kube-system | grep CrashLoopBackOff
    

    O resultado será assim:

    NAMESPACE     NAME                        READY     STATUS             RESTARTS   AGE
    kube-system   gke-metadata-server-8sm2l   0/1       CrashLoopBackOff   194        16h
    kube-system   gke-metadata-server-hfs6l   0/1       CrashLoopBackOff   1369       111d
    kube-system   gke-metadata-server-hvtzn   0/1       CrashLoopBackOff   669        111d
    kube-system   gke-metadata-server-swhbb   0/1       CrashLoopBackOff   30         136m
    kube-system   gke-metadata-server-x4bl4   0/1       CrashLoopBackOff   7          15m
    
  2. Descreva o pod com falha para confirmar que a causa foi uma remoção de falta de memória:

    kubectl describe pod POD_NAME --namespace=kube-system | grep OOMKilled
    

    Substitua POD_NAME pelo nome do pod a ser verificado.

Para restaurar a funcionalidade do servidor de metadados do GKE, reduza o número de contas de serviço no cluster para menos de 3 mil.

Falha ao ativar a federação de identidade da carga de trabalho do GKE com a mensagem de erro "DeployPatch"

O GKE usa o agente de serviço do Kubernetes Engine gerenciado pelo Google Cloudpara facilitar a federação de identidade da carga de trabalho do GKE nos seus clusters.O Google Cloud concede automaticamente a esse agente de serviço o papel de agente de serviço do Kubernetes Engine (roles/container.serviceAgent) no projeto quando você ativa a API Google Kubernetes Engine.

Se você tentar ativar a federação de identidade da carga de trabalho do GKE nos clusters de um projeto em que o agente de serviço não tem o papel de agente de serviço do Kubernetes Engine, a operação falhará com uma mensagem de erro semelhante a esta:

Error waiting for updating GKE cluster workload identity config: DeployPatch failed

Para resolver esse problema, tente o seguinte:

  1. Verifique se o agente de serviço existe no projeto e se ele está configurado corretamente:

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

    Substitua PROJECT_ID pelo ID do projeto do Google Cloud.

    Se o agente de serviço estiver configurado corretamente, a saída mostrará a identidade completa dele:

    serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
    

    Se a saída não mostrar o agente de serviço, conceda a ele o papel de agente de serviço do Kubernetes Engine. Para conceder esse papel, conclua as etapas a seguir.

  2. Confira o número do projeto Google Cloud :

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

    O resultado será assim:

    123456789012
    
  3. Conceda ao agente de serviço o seguinte papel:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com \
        --role=roles/container.serviceAgent \
        --condition=None
    

    Substitua PROJECT_NUMBER pelo número do seu projeto Google Cloud.

  4. Tente ativar a federação de identidade da carga de trabalho do GKE de novo.

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: