Saiba mais sobre as etapas de solução de problemas que podem ser úteis se você tiver dúvidas ao usar o Google Kubernetes Engine (GKE).
Como depurar recursos do Kubernetes
Se você tiver um problema relacionado ao cluster, consulte Como solucionar problemas de clusters (em inglês) na documentação do Kubernetes.
Se você está tendo um problema com o aplicativo, os pods ou o objeto controlador, consulte Como solucionar problemas de aplicativos (em inglês).
Comando kubectl
não encontrado
Instale o
kubectl
binário executando o seguinte comando:sudo gcloud components update kubectl
Responda "sim" quando a modificação da variável de ambiente
$PATH
for solicitada no instalador. Quando essas variáveis são modificadas, você consegue usar os comandoskubectl
sem digitar o caminho completo do arquivo.Outra alternativa é adicionar a seguinte linha ao
~/.bashrc
(~/.bash_profile
, no macOS, ou sempre que o shell armazenar variáveis de ambiente):export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
Execute o seguinte comando para carregar seu arquivo
.bashrc
(ou.bash_profile
) atualizado:source ~/.bashrc
Os comandos kubectl
retornam o erro "conexão recusada"
Defina o contexto do cluster com o seguinte comando:
gcloud container clusters get-credentials cluster-name
Se você não tiver certeza sobre o que inserir em cluster-name, use o comando a seguir para listar os clusters:
gcloud container clusters list
Os comandos kubectl
retornam o erro "falha ao negociar versão da API"
Verifique se o kubectl tem as credenciais de autenticação:
gcloud auth application-default login
Os comandos kubectl
, logs
, attach
, exec
e port-forward
pararam de responder
Esses comandos dependem do plano de controle do cluster (mestre) ser capaz de se comunicar com os nós no cluster. Porém, como o plano de controle não está na mesma rede do Compute Engine que os nós do cluster, dependemos dos túneis SSH para ativar a comunicação segura.
O GKE salva um arquivo de chave pública SSH nos metadados do projeto do Compute Engine. Todas as VMs do Compute Engine que usam as imagens fornecidas pelo Google verificam regularmente os metadados comuns do projeto e os metadados da instância em busca das chaves SSH para adicionar à lista de usuários autorizados da VM. Além disso, o GKE adiciona uma regra de firewall à rede do Compute Engine, o que permite o acesso SSH do endereço IP do plano de controle a cada nó no cluster.
Se algum dos comandos kubectl
acima não for executado, é provável que o servidor
de APIs não consiga abrir os túneis SSH com os nós. Verifique as seguintes causas
possíveis:
O cluster não tem nenhum nó.
Se você reduziu o número de nós no cluster a zero, os túneis SSH não funcionam.
Para corrigir esse problema, redimensione o cluster para ter pelo menos um nó.
Os pods no cluster estão paralisados em um estado de encerramento e impedem a remoção dos nós que não existem mais do cluster.
Esse é um problema que afeta somente o Kubernetes versão 1.1, mas ele pode ser causado pelo redimensionamento repetido do cluster.
Para corrigi-lo, exclua os pods que estão no estado de encerramento há vários minutos. Os nós antigos são removidos do plano de controle e substituídos pelos novos nós.
As regras de firewall da rede não permitem acesso SSH ao plano de controle.
Todas as redes do Compute Engine são criadas com uma regra de firewall chamada
default-allow-ssh
, que permite o acesso SSH de todos os endereços IP, certamente com uma chave privada válida. O GKE também insere uma regra SSH em cada cluster público no formatogke-cluster-name-random-characters-ssh
, que permite o acesso SSH especificamente do plano de controle do cluster aos nós do cluster. Se não houver nenhuma dessas regras, o plano de controle não poderá abrir os túneis SSH.Para corrigir isso, adicione novamente uma regra de firewall que permita acesso às VMs com a tag que está em todos os nós do cluster do endereço IP do plano de controle.
A entrada de metadados comuns do projeto "ssh-keys" está cheia.
Se a entrada de metadados do projeto chamada "ssh-keys" estiver próxima do limite máximo de tamanho, o GKE não poderá adicionar a própria chave SSH para ativá-la e abrir túneis SSH. Veja os metadados do seu projeto executando o seguinte comando:
gcloud compute project-info describe [--project=PROJECT]
Em seguida, verifique o tamanho da lista de ssh-keys.
Para corrigir isso, exclua algumas chaves SSH que não são mais necessárias.
Você definiu um campo de metadados com a chave “ssh-keys” nas VMs no cluster.
O agente de nó nas VMs prefere as chaves SSH por instância do que do projeto inteiro. Portanto, se você definiu essas chaves especificamente nos nós do cluster, a chave SSH do plano de controle nos metadados do projeto não será usada pelos nós. Para verificar isso, execute
gcloud compute instances describe <VM-name>
e procure um campo "ssh-keys" nos metadados.Para corrigir esse problema, exclua as chaves SSH por instância dos metadados da instância.
Esses recursos não são necessários para o funcionamento correto do cluster. Se você preferir manter a rede do cluster bloqueada contra qualquer acesso externo, saiba que recursos como esse não funcionarão.
A versão do nó não é compatível com a versão do plano de controle
Verifique qual versão do Kubernetes o plano de controle do cluster está em execução e verifique qual versão do Kubernetes os pools de nós do cluster estão em execução. Se algum dos pools de nós do cluster tiver mais de duas versões secundárias mais antigas que o plano de controle, isso pode causar problemas com o cluster.
Periodicamente, a equipe do GKE realiza upgrades do plano de controle de cluster em seu nome. Os planos de controle são atualizados para versões estáveis mais recentes do Kubernetes. Por padrão, os nós de um cluster têm o upgrade automático ativado e é recomendável que ele não seja desativado.
Se o upgrade automático estiver desativado para os nós de um cluster e você não fizer o upgrade manual da versão do pool de nós para uma versão compatível com o plano de controle, seu controle. ele se tornará incompatível com os nós, já que o plano de controle é atualizado automaticamente ao longo do tempo. A incompatibilidade entre o plano de controle do cluster e os nós pode causar problemas inesperados.
A versão do Kubernetes e a política de suporte de diferença de versão garantem que os planos de controle sejam compatíveis com nós de até duas versões secundárias mais antigas que o plano de controle. Por exemplo, os planos de controle do Kubernetes 1.19 são compatíveis com os nós do Kubernetes 1.19, 1.18 e 1.17. Para resolver esse problema, faça upgrade manual da versão do pool de nós para uma que seja compatível com o plano de controle.
Se você estiver preocupado com o processo de upgrade que causa interrupção nas cargas de trabalho em execução nos nós afetados, siga as etapas na seção "Como migrar as cargas de trabalho" do Como migrar cargas de trabalho para diferentes tipos de máquina. Com estas etapas, é possível fazer uma migração sem problemas ao criar um novo pool de nós e, em seguida, dividir e drenar o pool de nós antigo.
As métricas do cluster não são exibidas no Cloud Monitoring
Certifique-se de que você ativou a API Cloud Monitoring e a API Cloud Logging do seu projeto e que consegue visualizá-lo no Cloud Monitoring.
Se o problema continuar, verifique estas possíveis causas:
Verifique se o monitoramento está ativado no cluster.
O Monitoring é ativado por padrão para clusters criados a partir do Console do Google Cloud e da ferramenta de linha de comando
gcloud
, mas você pode conferir executando o comando a seguir ou clicando nos detalhes do cluster no Console do Cloud:gcloud container clusters describe cluster-name
A saída desse comando deve indicar que o "monitoringService" é "monitoring.googleapis.com", e o Cloud Monitoring precisa estar ativado no Console do Cloud.
Se o monitoramento não estiver ativado, execute o seguinte comando para ativá-lo:
gcloud container clusters update cluster-name --monitoring-service=monitoring.googleapis.com
Quanto tempo faz desde que o cluster foi criado ou que o monitoramento foi ativado?
Pode levar até uma hora para que as métricas de um novo cluster comecem a aparecer no Cloud Monitoring.
Um
heapster
ougke-metrics-agent
(o Coletor OpenTelemetry) está em execução no seu cluster, no namespace "kube-system"?Talvez esse pod não consiga programar cargas de trabalho porque seu cluster deve estar com poucos recursos. Confira se o Heapster ou o OpenTelemetry está em execução chamando
kubectl get pods --namespace=kube-system
e verificando os pods comheapster
ougke-metrics-agent
no nome.O plano de controle do cluster pode se comunicar com os nós?
O Cloud Monitoring depende disso. Para verificar se esse é o caso, execute o seguinte comando:
kubectl logs pod-name
Se esse comando retornar um erro, os túneis SSH podem estar causando o problema. Consulte esta seção para mais informações.
Se você tiver um problema relacionado ao agente do Cloud Logging, consulte a documentação de solução de problemas.
Para mais informações, consulte a documentação do Logging.
Erro 404: recurso "não encontrado" ao chamar comandos gcloud container
Faça a autenticação novamente na ferramenta de linha de comando gcloud
:
gcloud auth login
Erro 400/403: permissões de edição ausentes na conta
A conta de serviço padrão do Compute Engine ou a conta de serviço associada ao GKE foi excluída ou editada manualmente.
Quando você ativa a API do Compute Engine ou do Kubernetes Engine, uma conta de serviço é criada e recebe permissões para edição no seu projeto. Se, em algum momento, você editar as permissões, remover o papel "Agente de Serviço do Kubernetes Engine", remover a conta completamente ou desativar a API, a criação do cluster e toda a funcionalidade de gerenciamento falharão.
O nome da sua conta de serviço do Google Kubernetes Engine é da maneira vista a seguir, em que project-number é o número do projeto:
service-project-number@container-engine-robot.iam.gserviceaccount.com
Para resolver o problema, caso você tenha removido o papel do Agente de serviço do Kubernetes Engine
da sua conta de serviço do Google Kubernetes Engine, adicione-o novamente. Caso contrário, você
precisará reativar a API do Kubernetes Engine,
que vai restaurar corretamente suas contas de serviço e permissões. Você pode fazer isso na ferramenta gcloud
ou no
Console do Cloud.
Console
Visite APIs e Serviços no Console do Cloud.
Selecione o projeto.
Clique em Ativar APIs e serviços.
Procure pelo Kubernetes e selecione a API nos resultados da pesquisa.
Clique em Ativar. Se já tiver ativado a API, você precisa primeiro desativá-la e, em seguida, reativá-la. Pode levar alguns minutos para que a API e os serviços relacionados sejam ativados.
gcloud
Execute o seguinte comando na ferramenta gcloud
:
gcloud services enable container.googleapis.com
Como replicar as regras de firewall automáticas 1.8.x (e anteriores) no 1.9.x e posterior
Se seu cluster estiver executando o Kubernetes versão 1.9.x, as regras de firewall automáticas foram alteradas para não permitir cargas de trabalho em um cluster GKE para iniciar a comunicação com outras VMs do Compute Engine que estejam fora do cluster, mas na mesma rede.
Replique o comportamento automático de regras de firewall de um cluster 1.8.x (e anterior) executando as seguintes etapas:
Encontre a rede do seu cluster:
gcloud container clusters describe cluster-name --format=get"(network)"
Busque o CIDR IPv4 do cluster usado para os contêineres:
gcloud container clusters describe cluster-name --format=get"(clusterIpv4Cidr)"
Crie uma regra de firewall para a rede, com o CIDR como intervalo de origem e autorize todos os protocolos:
gcloud compute firewall-rules create "cluster-name-to-all-vms-on-network" \ --network="network" --source-ranges="cluster-ipv4-cidr" \ --allow=tcp,udp,icmp,esp,ah,sctp
Restaurar conta de serviço padrão para seu projeto do GCP
A conta de serviço padrão do GKE, container-engine-robot
, pode
ser acidentalmente desassociada de um projeto. O Agente de serviços do GKE
é um papel de gerenciamento de identidade e acesso (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.
É possível verificar se a conta de serviço foi removida do seu projeto
usando a ferramenta gcloud
ou o Console do Cloud.
gcloud
Execute este comando:
gcloud projects get-iam-policy project-id
Substitua project-id pelo ID do projeto.
Console
Acesse a página IAM e administrador no Console do Cloud.
Se o comando ou o painel não exibe container-engine-robot
nas
suas contas de serviço, a conta de serviço está desvinculada.
Se você removeu a vinculação de papel do Agente de serviço do GKE, execute os seguintes comandos para restaurar a vinculação de papel:
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format "value(projectNumber)")
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member "serviceAccount:service-${PROJECT_NUMBER}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
Para confirmar se a vinculação de papel foi concedida:
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 concedida. Por exemplo:
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Chave do Cloud KMS desativada
A conta de serviço padrão do GKE não pode usar uma chave desativada do Cloud KMS na criptografia de secrets no nível do aplicativo.
Para reativar uma chave desativada, consulte Ativar uma versão de chave desativada.
Pods travados em estado pendente após a ativação do nó alocável
Se você estiver enfrentando problemas com pods travados no estado pendente depois de ativar o Node Alocável, observe o seguinte:
A partir da versão 1.7.6, o GKE reserva CPU e memória para sobrecarga do Kubernetes, incluindo o Docker e o sistema operacional. Consulte Arquitetura de cluster para saber quanto de cada tipo de máquina pode ser programado pelos pods.
Se os pods estiverem pendentes após um upgrade, sugerimos o seguinte:
Certifique-se de que as solicitações de CPU e memória para seus pods não excedam o pico de uso. Com o GKE reservando CPU e memória para sobrecarga, os pods não podem solicitar esses recursos. Os pods que solicitam mais CPU ou memória do que usam impedem que outros pods solicitem esses recursos, podendo deixar o cluster subutilizado. Para mais informações, consulte Como programar pods com solicitações de recursos.
Considere redimensionar seu cluster. Para instruções, consulte Como redimensionar um cluster.
Reverta essa alteração fazendo o downgrade do cluster. Para instruções, consulte Como fazer upgrade manual de um cluster ou pool de nós.
Os nós de cluster particulares foram criados, mas não estão mesclando com o cluster
Muitas vezes, ao usar roteamento personalizado e dispositivos de rede de terceiros na VPC que o cluster particular usa, a rota padrão (0.0.0.0/0) é redirecionada para o dispositivo, e não para o gateway de Internet padrão. Além da conectividade do plano de controle, você precisa garantir que os seguintes destinos estejam acessíveis:
- *.googleapis.com
- *.gcr.io
- gcr.io
Configure o Acesso privado do Google nos três domínios. Essa prática recomendada permite que os novos nós sejam inicializados e se mesclem com o cluster, mantendo o tráfego vinculado à Internet restrito.
Solução de problemas com cargas de trabalho implantadas
O GKE retornará um erro se houver problemas com os pods de uma carga de trabalho.
É possível verificar o status de um pod usando a ferramenta de linha de comando kubectl
ou
o Console do Cloud.
kubectl
Para ver todos os pods em execução no cluster, execute o seguinte comando:
kubectl get pods
Saída:
NAME READY STATUS RESTARTS AGE
pod-name 0/1 CrashLoopBackOff 23 8d
Para mais informações sobre um pod específico, execute o seguinte comando:
kubectl describe pod pod-name
Substitua pod-name pelo nome do pod que você quer.
Console
Siga as etapas abaixo:
Acesse o painel de cargas de trabalho do GKE no Console do Cloud.
Selecione a carga de trabalho desejada. A guia Visão geral exibe o status da carga de trabalho.
Na seção Gerenciar pods, clique na mensagem de status de erro.
Veja nas seções a seguir alguns erros comuns retornados por cargas de trabalho e como resolvê-los.
CrashLoopBackOff
CrashLoopBackOff
indica que um contêiner está repetidamente falhando após a reinicialização. Um contêiner pode falhar por vários motivos. Verificar os registros de um pod ajuda na solução de problemas da causa raiz.
Por padrão, os contêineres com falha são reiniciados com um atraso exponencial limitado a cinco minutos. Altere esse comportamento configurando o campo restartPolicy
Especificação do pod de implantação em spec: restartPolicy
. O valor padrão do campo é Always
.
Descubra o motivo da falha no contêiner do pod usando a ferramenta de linha de comando kubectl
ou o Console do Cloud.
kubectl
Para ver todos os pods em execução no cluster, execute o seguinte comando:
kubectl get pods
Procure o pod com o erro CrashLoopBackOff
.
Para receber os registros do pod, execute o seguinte comando:
kubectl logs pod-name
Substitua pod-name pelo nome do pod problemático.
Também é possível transferir a sinalização -p
para conseguir os registros da instância anterior do contêiner do pod, caso existam.
Console
Siga as etapas abaixo:
Acesse o painel de cargas de trabalho do GKE no Console do Cloud.
Selecione a carga de trabalho desejada. A guia Visão geral exibe o status da carga de trabalho.
Na seção Gerenciar Pods, clique no Pod problemático.
No menu do pod, clique na guia Registros.
Verificar o "código de saída" do contêiner com falha
Para encontrar o código de saída, execute as seguintes tarefas:
Execute este comando:
kubectl describe pod pod-name
Substitua pod-name pelo nome do pod.
Revise o valor no campo
containers: container-name: last state: exit code
:- Se o código de saída for 1, o contêiner falhou porque o aplicativo falhou.
- Se o código de saída for 0, verifique por quanto tempo seu aplicativo estava sendo executado.
Os contêineres saem quando o processo principal do aplicativo é encerrado. Se seu aplicativo concluir a execução rápido demais, o contêiner pode continuar reiniciando.
Conectar-se a um contêiner em execução
Abra um shell para o pod:
kubectl exec -it pod-name -- /bin/bash
Se houver mais de um contêiner no pod, adicione -c container-name
.
Agora, é possível executar comandos bash no contêiner: teste a rede ou verifique se você tem acesso a arquivos ou bancos de dados usados pelo aplicativo.
ImagePullBackOff e ErrImagePull
ImagePullBackOff
e ErrImagePull
indicam que a imagem usada por um contêiner não pode ser carregada do registro de imagem.
Verifique esse problema usando o Console do Cloud ou a ferramenta de linha de comando kubectl
.
kubectl
Para mais informações sobre a imagem do contêiner do pod, execute o seguinte comando:
kubectl describe pod pod-name
Console
Siga as etapas abaixo:
Acesse o painel de cargas de trabalho do GKE no Console do Cloud.
Selecione a carga de trabalho desejada. A guia Visão geral exibe o status da carga de trabalho.
Na seção Gerenciar Pods, clique no Pod problemático.
No menu do Pod, clique na guia Eventos.
Se a imagem não for encontrada
Se sua imagem não for encontrada:
- Verifique se o nome da imagem está correto.
- Verifique se a tag da imagem está correta. (Tente
:latest
ou nenhuma tag para extrair a imagem mais recente). - Se a imagem tiver um caminho de registro completo, verifique se ela existe no registro do Docker que você está usando. Se você fornecer apenas o nome da imagem, verifique o registro do Docker Hub.
Tente extrair a imagem do docker manualmente:
Use SSH para acessar o nó:
Por exemplo, para SSH em
example-instance
na zonaus-central1-a
:gcloud compute ssh example-instance --zone us-central1-a
Execute
docker pull image-name
.
Se essa opção funcionar, você provavelmente precisará especificar ImagePullSecrets em um pod. Os pods só podem referenciar segredos de extração de imagem nos próprios namespaces. Portanto, esse processo precisa ser feito uma vez por namespace.
Se você encontrar um erro de "permissão negada" ou "sem acesso para extrair", verifique se você está conectado e/ou tem acesso à imagem.
Se você estiver usando um registro particular, isso pode exigir chaves para ler imagens.
Se a imagem estiver hospedada no Container Registry, a conta de serviço associada ao pool de nós precisa ter acesso de leitura ao bucket do Cloud Storage que contém a imagem. Consulte a documentação do Container Registry para mais detalhes.
Pod não programável
PodUnschedulable
indica que seu pod não pode ser programado devido a recursos insuficientes ou a algum erro de configuração.
Recursos insuficientes
Talvez você encontre um erro indicando falta de CPU, memória ou outro recurso. Por exemplo: "não há nós disponíveis que correspondam a todos os predicados: CPU insuficiente (2)", o que indica que em dois nós não há CPU suficiente disponível para atender às solicitações de um pod.
A solicitação de CPU padrão é 100m ou 10% de uma CPU (ou um núcleo).
Se quiser solicitar mais ou menos recursos, especifique o valor na especificação do pod em spec: containers: resources: requests
MatchNodeSelector
MatchNodeSelector
indica que não há nós que correspondam ao seletor de
rótulos do pod.
Para verificar isso, confira os rótulos especificados no campo nodeSelector
da especificação do pod, em spec: nodeSelector
.
Para ver como os nós no cluster são rotulados, execute o seguinte comando:
kubectl get nodes --show-labels
Para anexar um rótulo a um nó, execute o seguinte comando:
kubectl label nodes node-name label-key=label-value
Substitua:
- node-name pelo nó que você quer;
- label-key pela chave do rótulo;
- label-value pelo valor do rótulo.
Para mais informações, consulte Como atribuir pods a nós.
PodToleratesNodeTaints
PodToleratesNodeTaints
indica que o pod não pode ser programado para qualquer nó porque nenhum deles atualmente tolera o taint do nó.
Para verificar se esse é o caso, execute o seguinte comando:
kubectl describe nodes node-name
Na saída, verifique o campo Taints
, que lista pares de valor-chave e efeitos de programação.
Se o efeito listado for NoSchedule
, nenhum pod poderá ser programado nesse nó,
a menos que exista uma tolerância correspondente.
Uma maneira de resolver esse problema é remover o taint. Para remover um taint NoSchedule, execute o seguinte comando:
kubectl taint nodes node-name key:NoSchedule-
PodFitsHostPorts
PodFitsHostPorts
indica que uma porta que um nó está tentando usar já está em uso.
Para resolver esse problema, verifique o valor hostPort
da especificação do pod em spec: containers: ports: hostPort
. Pode ser necessário alterar esse valor para outra porta.
Não há disponibilidade mínima
Se um nó tiver recursos adequados, mas ainda exibir a mensagem Does not have minimum availability
, verifique o status do pod. Se o status for SchedulingDisabled
ou Cordoned
, o nó não poderá programar novos pods. É possível verificar o status de um
nó usando o Console do Cloud ou a ferramenta de linha de comando kubectl
.
kubectl
Para receber o status dos seus nós, execute o seguinte comando:
kubectl get nodes
Para ativar a programação no nó, execute:
kubectl uncordon node-name
Console
Siga as etapas abaixo:
Acesse o painel de cargas de trabalho do GKE no Console do Cloud.
Selecione o cluster desejado. A guia Nós exibe os nós e o status deles.
Para ativar a programação no nó, execute as seguintes etapas:
Na lista, clique no nó desejado.
Em "Detalhes do nó", clique no botão Não programável.
Desvincular PersistentVolumeClaims
Unbound PersistentVolumeClaims
indica que o pod se refere a uma
PersistentVolumeClaim não vinculada. Esse erro pode acontecer caso seu
PersistentVolume falhe ao provisionar. É possível verificar se o provisionamento falhou
procurando por erros nos eventos do seu
PersistentVolumeClaim.
Para acessar eventos, execute o seguinte comando:
kubectl describe pvc statefulset-name-pvc-name-0
Substitua:
- statefulset-name pelo nome do objeto StatefulSet;
- pvc-name pelo nome do objeto PersistentVolumeClaim.
Isso também pode acontecer se houver um erro de configuração durante o pré-provisionamento manual de um PersistentVolume e sua vinculação a um PersistentVolumeClaim. É possível tentar pré-aprovisionar o volume novamente.
Problemas de conectividade
Conforme mencionado em Visão geral da rede, é importante entender como os pods são conectados desde os namespaces de rede até o namespace raiz no nó para solucionar problemas com eficiência. Para a discussão a seguir, salvo indicação em contrário, suponha que o cluster use CNI nativa do GKE, em vez do Calico. Ou seja, nenhuma política de rede foi aplicada.
Pods em nós selecionados sem disponibilidade
Se os Pods em nós selecionados não tiverem conectividade de rede, verifique se a ponte do Linux está ativa:
ip address show cbr0
Se a ponte do Linux estiver inativa, ative-a:
sudo ip link set cbr0 up
Assegure que o nó esteja aprendendo os endereços MAC do Pod anexados ao cbr0:
arp -an
Pods em nós selecionados com conectividade mínima
Se os pods em nós selecionados tiverem conectividade mínima, primeiro é preciso confirmar se há algum pacote perdido executando tcpdump
no contêiner da caixa de ferramentas:
sudo toolbox bash
Instale tcpdump
na caixa de ferramentas se ainda não tiver feito isso:
apt install -y tcpdump
Execute tcpdump
com cbr0:
tcpdump -ni cbr0 host hostname and port port-number and [tcp|udp|icmp]
Se parecer que grandes pacotes estão sendo descartados em downstream da ponte, por exemplo, o handshake TCP é concluído, mas nenhum SSL é recebido, certifique-se de que a MTU de ponte do Linux esteja definida corretamente como a MTU da rede VPC do cluster.
ip address show cbr0
Quando forem usadas sobreposições (por exemplo, Weave ou Flannel), essa MTU precisará ser ainda mais reduzida para acomodar a sobrecarga de encapsulamento.
Conexões com falha intermitente
Conexões de e para Pods são encaminhadas pelo iptables. Os fluxos são rastreados como entradas na tabela conntrack e, havendo muitas cargas de trabalho por nó, o esgotamento da tabela conntrack pode se manifestar como uma falha. Isso pode ser registrado no console serial do nó, por exemplo:
nf_conntrack: table full, dropping packet
Se você consegue determinar que problemas intermitentes são causados por esgotamento de conntrack, aumente o tamanho do cluster (reduzindo assim o número de cargas de trabalho e fluxos por nó) ou aumente o nf_conntrack_max
:
new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
&& echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf
"vincular: endereço já está em uso" relatado para um contêiner
Um contêiner em um Pod não pode iniciar porque, de acordo com os registros de contêiner, a porta em que o aplicativo está tentando se vincular já está reservada. O contêiner está em um ciclo de falha. Por exemplo, no Cloud Logging:
resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"
2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use
Quando o Docker falha, às vezes um contêiner em execução é deixado para trás e fica obsoleto. O processo ainda está executando no namespace de rede alocado para o Pod e escutando nessa porta. Como o Docker e o Kubelet desconhecem o contêiner obsoleto, eles tentam iniciar um novo contêiner com um novo processo, que não pode ser vinculado à porta já que está adicionado ao namespace de rede associada ao pod.
Para diagnosticar esse problema:
Você precisa do UUID do pod no campo
.metadata.uuid
:kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg name UUID ubuntu-6948dd5657-4gsgg db9ed086-edba-11e8-bdd6-42010a800164
Você recebe uma saída do nó com os seguintes comandos:
docker ps -a ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
Verifique processos em execução desse pod. Como o UUID dos namespaces do cgroup contém o UUID do pod, execute grep para o UUID do pod na saída
ps
. Execute grep na linha anterior. Assim, poderá ter os processosdocker-containerd-shim
, além do código do contêiner no argumento. Elimine o restante da coluna cgroup para conseguir uma saída mais simples:# ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/ 1283089 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 276e173b0846e24b704d4 12: 1283107 1283089 Ss sys_pause 4026532393 pause /pause 12: 1283150 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim ab4c7762f5abf40951770 12: 1283169 1283150 Ss do_wait 4026532393 sh /bin/sh -c echo hello && sleep 6000000 12: 1283185 1283169 S hrtimer_nanosleep 4026532393 sleep sleep 6000000 12: 1283244 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 44e76e50e5ef4156fd5d3 12: 1283263 1283244 Ss sigsuspend 4026532393 nginx nginx: master process nginx -g daemon off; 12: 1283282 1283263 S ep_poll 4026532393 nginx nginx: worker process
Nessa lista, é possível ver os IDs dos contêineres, que também devem estar visíveis no
docker ps
.Nesse caso:
docker-containerd-shim 276e173b0846e24b704d4
para pausardocker-containerd-shim ab4c7762f5abf40951770
para sh com suspensão (sleep-ctr)docker-containerd-shim 44e76e50e5ef4156fd5d3
para nginx (echoserver-ctr)
Verifique os que estão na saída
docker ps
:# docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3' 44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc "nginx -g 'daemon off;'" 14 hours ago Up 14 hours k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475 ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78 "/bin/sh -c 'echo hello && sleep 6000000'" 14 hours ago Up 14 hours k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327 k8s.gcr.io/pause-amd64:3.1
Nos casos normais, você vê todos os códigos dos contêineres de
ps
aparecendo emdocker ps
. Se algum deles não aparece, trata-se de um contêiner obsoleto, e provavelmente você verá um processo filho dodocker-containerd-shim process
detectando a porta TCP que informa já estar em uso.Para verificar isso, execute
netstat
no namespace de rede do contêiner. Receba o pid de qualquer processo de contêiner (diferente dedocker-containerd-shim
) para o pod.Do exemplo acima:
- 1283107 - pausar
- 1283169 - sh
- 1283185 - suspensão
- 1283263 - mestre nginx
- 1283282 - worker nginx
# nsenter -t 1283107 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast
Também é possível executar
netstat
usandoip netns
, mas é necessário vincular manualmente o namespace de rede do processo porque o Docker não está fazendo o vínculo:# ln -s /proc/1283169/ns/net /var/run/netns/1283169 gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list 1283169 (id: 2) gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
Mitigação:
A mitigação de curto prazo identifica processos obsoletos usando o método descrito
acima e os encerra por meio do comando kill [PID]
.
A mitigação de longo prazo consiste em identificar por que o Docker está falhando e corrigir esse problema. Entre as possíveis razões estão:
- Processos zumbi se acumulando, esgotando assim os namespaces PID
- Bug no Docker
- Pressão de recurso/OOM