Às vezes, as coisas dão errado. Este guia tem como objetivo ajudá-lo a corrigir esses problemas. Ele está dividido em duas seções:
Depurando sua aplicação - Útil para usuários que estão implantando código no Kubernetes e se perguntando por que não está funcionando.
Depurando seu cluster - Útil para administradores de clusters e para aqueles cujo cluster Kubernetes está apresentando problemas.
Você também deve verificar os problemas conhecidos da versão que está utilizando.
Obtendo ajuda
Se o seu problema não for resolvido por nenhum dos guias acima, há várias maneiras de obter ajuda da comunidade Kubernetes.
Perguntas
A documentação neste site foi estruturada para fornecer respostas a uma ampla gama de perguntas. Conceitos explicam a arquitetura do Kubernetes e como cada componente funciona, enquanto Configuração oferece instruções práticas para começar. Tarefas mostram como realizar tarefas comumente utilizadas, e os Tutoriais são guias mais abrangentes de cenários reais, específicos da indústria ou de desenvolvimento completo de ponta a ponta.
A seção de Referência fornece documentação detalhada sobre a API do Kubernetes e as interfaces de linha de comando (CLIs), como kubectl.
Socorro! Minha pergunta não foi respondida! Preciso de ajuda agora!
Stack Exchange, Stack Overflow ou Server Fault
Se você tem dúvidas relacionadas ao desenvolvimento de software para sua aplicação containerizada, você pode perguntar no Stack Overflow.
Se você tem perguntas sobre Kubernetes relacionadas à gestão do cluster ou configuração, você pode perguntar no Server Fault.
Muitas pessoas da comunidade Kubernetes estão no Slack do Kubernetes no canal #kubernetes-users.
O Slack requer registro; você pode solicitar um convite, e o registro está aberto para todos.
Sinta-se à vontade para entrar e fazer qualquer tipo de pergunta.
Depois de registrado, explore a lista crescente de canais para vários assuntos de interesse.
Por exemplo, novos usuários do Kubernetes podem querer entrar no canal #kubernetes-novice.
Desenvolvedores devem entrar no canal #kubernetes-contributors.
Também existem muitos canais específicos por país/idioma. Sinta-se à vontade para entrar nesses canais para suporte localizado e informações:
Antes de registrar um problema, pesquise os problemas existentes para verificar se sua questão já foi abordada.
Se for relatar um bug, inclua informações detalhadas sobre como reproduzir o problema, como:
Versão do Kubernetes: kubectl version
Provedor de nuvem, distribuição do SO, configuração de rede e versão do runtime do container
Passos para reproduzir o problema
1 - Solução de Problemas em Aplicações
Depuração de problemas comuns em aplicações conteinerizadas.
Este documento contém um conjunto de recursos para solucionar problemas em aplicações conteinerizadas. Ele aborda questões comuns relacionadas a recursos do Kubernetes (como Pods, Services e StatefulSets), orientações para interpretar mensagens de término de contêineres e métodos para depurar contêineres em execução.
1.1 - Depuração de Pods
Este guia foi criado para ajudar os usuários a depurar aplicações implantadas no Kubernetes
que não estão se comportando corretamente. Este não é um guia para quem deseja depurar seu cluster.
Para isso, você deve conferir este guia.
Diagnosticando o problema
O primeiro passo na solução de problemas é a triagem. Qual é o problema?
São seus Pods, seu Replication Controller ou seu Service?
O primeiro passo para depurar um Pod é examiná-lo. Verifique o estado atual
do Pod e eventos recentes com o seguinte comando:
kubectl describe pods ${POD_NAME}
Observe o estado dos containers no pod. Todos estão em Running?
Houve reinicializações recentes?
Continue a depuração dependendo do estado dos pods.
Meu pod fica em estado pending
Se um Pod estiver preso em Pending, significa que ele não pode ser alocado em um nó.
Geralmente, isso ocorre porque há recursos insuficientes de algum tipo, impedindo a alocação.
Verifique a saída do comando kubectl describe ... mencionado acima.
Deve haver mensagens do escalonador explicando por que o Pod não pode ser alocado. As razões incluem:
Você não tem recursos suficientes: Pode ser que você tenha esgotado a capacidade de CPU ou Memória no seu cluster.
Nesse caso, você precisa excluir Pods, ajustar as solicitações de recursos ou adicionar novos nós ao cluster.
Consulte o documento Recursos de Computação para mais informações.
Você está usando hostPort: Quando você vincula um Pod a um hostPort, há um número limitado de locais onde esse Pod pode ser alocado.
Na maioria dos casos, hostPort é desnecessário, tente usar um objeto Service para expor seu Pod.
Se você realmente precisar de hostPort, então só poderá alocar tantos Pods quanto o número de nós no seu cluster Kubernetes.
Meu pod fica em estado waiting
Se um Pod estiver preso no estado Waiting, significa que ele foi alocado para um nó de trabalho,
mas não pode ser executado nessa máquina. Novamente, as informações do comando kubectl describe ...
devem fornecer detalhes úteis.
A causa mais comum para Pods em estado Waiting é a falha ao baixar a imagem.
Há três coisas que você deve verificar:
Certifique-se de que o nome da imagem está correto.
Você enviou a imagem para o registro?
Tente baixar a imagem manualmente para verificar se ela pode ser baixada. Por exemplo,
se você usa Docker no seu PC, execute docker pull .
Meu pod fica em estado terminating
Se um Pod estiver preso no estado Terminating, significa que uma solicitação de exclusão foi emitida,
mas a camada de gerenciamento não conseguiu remover o objeto do Pod.
Isso geralmente ocorre se o Pod possui um finalizer
e há um admission webhook
instalado no cluster que impede a camada de gerenciamento de remover o finalizer.
Para identificar esse cenário, verifique se seu cluster possui algum ValidatingWebhookConfiguration ou MutatingWebhookConfiguration que tenha como alvo
operações UPDATE para recursos pods.
Se o webhook for fornecido por um terceiro:
Certifique-se de estar usando a versão mais recente.
Desative o webhook para operações UPDATE.
Relate um problema ao provedor correspondente.
Se você for o autor do webhook:
Para um webhook de mutação, certifique-se de que ele nunca altere campos imutáveis
em operações UPDATE. Por exemplo, mudanças em contêineres geralmente não são permitidas.
Para um webhook de validação, garanta que suas regras de validação se apliquem apenas a novas alterações.
Em outras palavras, você deve permitir que Pods com violações existentes passem pela validação.
Isso permite que Pods criados antes da instalação do webhook continuem em execução.
Meu pod está falhando ou não está íntegro
Depois que seu Pod for alocado, você pode usar os métodos descritos em
Depurando Pods em Execução para depuração.
Meu pod está em execução, mas não faz o que eu defini
Se o seu pod não está se comportando como esperado, pode haver um erro na descrição do pod
(por exemplo, no arquivo mypod.yaml em sua máquina local) que foi ignorado silenciosamente
ao criar o pod. Muitas vezes, uma seção da descrição do pod pode estar aninhada incorretamente
ou um nome de chave pode ter sido digitado incorretamente, fazendo com que a chave seja ignorada.
Por exemplo, se você digitou commnd em vez de command, o pod será criado,
mas não usará o comando que você pretendia.
A primeira coisa a fazer é excluir seu pod e tentar criá-lo novamente usando a opção --validate.
Por exemplo, execute kubectl apply --validate -f mypod.yaml.
Se você digitou command incorretamente como commnd, verá um erro como este:
I0805 10:43:25.129850 46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973 46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod
A próxima coisa a verificar é se o pod no servidor da API corresponde ao pod que você pretendia criar
(por exemplo, no arquivo yaml em sua máquina local).
Por exemplo, execute kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml em seguida,
compare manualmente a descrição original do pod, mypod.yaml com a versão obtida do servidor da API, mypod-on-apiserver.yaml.
Normalmente, a versão do "servidor da API" terá algumas linhas extras que não estão na versão original,
o que é esperado. No entanto, se houver linhas na versão original que não aparecem na versão do servidor da API,
isso pode indicar um problema na especificação do seu pod.
Depurando Replication Controllers
Replication Controllers são bastante diretos. Eles podem criar pods ou não.
Se não conseguirem criar pods, consulte as
instruções acima para depurar seus pods.
Você também pode usar kubectl describe rc ${CONTROLLER_NAME} para examinar eventos
relacionados ao replication controller.
Depurando Services
Os Services fornecem balanceamento de carga entre um conjunto de pods.
Existem vários problemas comuns que podem fazer com que os Services não funcionem corretamente.
As instruções a seguir devem ajudar na depuração de problemas com Services.
Primeiro, verifique se há endpoints para o Service.
Para cada objeto Service, o servidor da API disponibiliza um recurso endpoints.
Você pode visualizar esse recurso com o seguinte comando:
kubectl get endpoints ${SERVICE_NAME}
Certifique-se de que os endpoints correspondem ao número de pods que você espera que sejam membros do seu service.
Por exemplo, se seu Service estiver associado a um container Nginx com 3 réplicas,
você deve esperar ver três endereços IP diferentes nos endpoints do Service.
Meu Service não possui endpoints
Se os endpoints estiverem ausentes, tente listar os pods usando os rótulos que o Service utiliza.
Por exemplo, imagine que você tenha um Service com os seguintes rótulos:
...spec:- selector:name:nginxtype:frontend
Você pode usar:
kubectl get pods --selector=name=nginx,type=frontend
para listar os pods que correspondem a esse seletor. Verifique se a lista corresponde aos pods que você espera que forneçam seu Service.
Além disso, certifique-se de que o containerPort do pod corresponde ao targetPort do service.
Se nenhuma das soluções acima resolver seu problema, siga as instruções no
documento de Depuração de Services
para garantir que seu Service está em execução, possui Endpoints e que seus Pods
estão realmente respondendo; além disso, verifique se o DNS está funcionando,
as regras do iptables estão configuradas corretamente e se o kube-proxy não está com problemas.
Um problema que surge com bastante frequência em novas instalações do Kubernetes
é que um Service não está funcionando corretamente. Você implantou seus Pods
através de um Deployment (ou outro controlador de carga de trabalho) e criou um Service,
mas não recebe nenhuma resposta ao tentar acessá-lo. Este documento,
esperançosamente, ajudará você a descobrir o que está errado.
Executando comandos em um Pod
Para muitas etapas aqui, você desejará ver o que um Pod em execução no cluster
está enxergando. A maneira mais simples de fazer isso é executar um Pod interativo
com busybox:
kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox sh
Nota:
Se você não vir um prompt de comando, tente pressionar Enter.
Se você já tem um Pod em execução que prefere usar, você pode executar um
comando nele usando:
Para os propósitos deste passo a passo, vamos executar alguns Pods. Como você
provavelmente está depurando seu próprio Service, pode substituir os detalhes
pelos seus próprios ou seguir junto para obter um segundo ponto de referência.
O rótulo "app" é definido automaticamente pelo kubectl create deployment como o nome do Deployment.
Você pode confirmar que seus Pods estão em execução:
kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 2m
hostnames-632524106-ly40y 1/1 Running 0 2m
hostnames-632524106-tlaok 1/1 Running 0 2m
Você também pode confirmar que seus Pods estão respondendo. Você pode obter a
lista de endereços IP dos Pods e testá-los diretamente.
kubectl get pods -l app=hostnames \
-o go-template='{{range .items}}{{.status.podIP}}{{"\n"}}{{end}}'
10.244.0.5
10.244.0.6
10.244.0.7
O contêiner de exemplo usado neste passo a passo serve seu próprio hostname
via HTTP na porta 9376, mas se você estiver depurando sua própria aplicação,
deverá usar o número da porta na qual seus Pods estão escutando.
De dentro de um Pod:
for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do wget -qO- $epdone
Se você não estiver recebendo as respostas esperadas neste ponto, seus Pods
podem não estar íntegro ou podem não estar ouvindo na porta que você pensa
que estão. Você pode achar útil usar kubectl logs para ver o que está
acontecendo ou, talvez, seja necessário executar kubectl exec diretamente
em seus Pods e depurar a partir daí.
Supondo que tudo tenha ocorrido conforme o esperado até agora, você pode começar
a investigar por que seu Service não está funcionando.
O Service existe?
O leitor atento terá notado que você ainda não criou um Service – isso é
intencional. Esse é um passo que às vezes é esquecido e é a primeira coisa a verificar.
O que aconteceria se você tentasse acessar um Service inexistente? Se você
tiver outro Pod que consome esse Service pelo nome, obteria algo como:
wget -O- hostnames
Resolving hostnames (hostnames)... failed: Name or service not known.
wget: unable to resolve host address 'hostnames'
A primeira coisa a verificar é se esse Service realmente existe:
kubectl get svc hostnames
No resources found.
Error from server (NotFound): services "hostnames" not found
Vamos criar o Service. Como antes, isso faz parte do passo a passo – você pode
usar os detalhes do seu próprio Service aqui.
Para destacar toda a gama de configurações, o Service que você criou aqui
usa um número de porta diferente dos Pods. Para muitos Services do mundo real,
esses valores podem ser os mesmos.
Alguma regra de Network Policy Ingress está afetando os Pods de destino?
Se você implantou alguma regra de Network Policy Ingress que possa afetar o
tráfego de entrada para os Pods hostnames-*, elas precisam ser revisadas.
Se isso funcionar, você precisará ajustar sua aplicação para usar um nome
qualificado pelo namespace ou executar sua aplicação e o Service no mesmo Namespace.
Se isso ainda falhar, tente um nome totalmente qualificado:
Observe o sufixo aqui: "default.svc.cluster.local". O "default" é o Namespace
no qual você está operando. O "svc" indica que este é um Service. O "cluster.local"
é o domínio do seu cluster, que PODE ser diferente no seu próprio cluster.
Você também pode tentar isso a partir de um Node no cluster:
Nota:
10.0.0.10 é o IP do Service DNS do cluster, o seu pode ser diferente.
Se você conseguir fazer uma consulta de nome totalmente qualificado, mas não
uma relativa, precisará verificar se o arquivo /etc/resolv.conf no seu Pod
está correto. De dentro de um Pod:
A linha nameserver deve indicar o Service DNS do seu cluster. Isso é passado
para o kubelet com a flag --cluster-dns.
A linha search deve incluir um sufixo apropriado para que o nome do Service
seja encontrado. Neste caso, ele está procurando Services no Namespace local
("default.svc.cluster.local"), Services em todos os Namespaces ("svc.cluster.local"),
e, por último, nomes no cluster ("cluster.local"). Dependendo da sua instalação,
você pode ter registros adicionais depois disso (até um total de 6). O sufixo
do cluster é passado para o kubelet com a flag --cluster-domain. Ao longo
deste documento, assumimos que o sufixo do cluster é "cluster.local". Seu
cluster pode estar configurado de forma diferente, e, nesse caso, você deve
ajustar isso em todos os comandos anteriores.
A linha options deve definir ndots com um valor alto o suficiente para que
sua biblioteca cliente de DNS considere os caminhos de pesquisa. O Kubernetes
define isso como 5 por padrão, o que é suficiente para cobrir todos os nomes
DNS que ele gera.
Algum Service funciona pelo nome DNS?
Se as etapas anteriores ainda falharem, as consultas DNS não estão funcionando
para seu Service. Você pode dar um passo atrás e verificar o que mais não está
funcionando. O Service principal do Kubernetes deve sempre funcionar. De dentro
de um Pod:
Se isso falhar, consulte a seção kube-proxy deste
documento ou até volte ao início e comece novamente, mas, em vez de depurar seu
próprio Service, depure o Service de DNS.
O Service funciona pelo IP?
Supondo que você tenha confirmado que o DNS está funcionando, o próximo passo
é testar se o seu Service funciona pelo endereço IP. A partir de um Pod no seu
cluster, acesse o IP do Service (obtido com kubectl get acima).
for i in $(seq 1 3); do wget -qO- 10.0.1.175:80
done
Se o seu Service estiver funcionando, você deverá obter respostas corretas.
Caso contrário, há várias possíveis causas para o problema. Continue lendo.
O Service está definido corretamente?
Pode parecer óbvio, mas você deve realmente verificar duas ou três vezes se
seu Service está correto e corresponde à porta do seu Pod. Leia novamente seu
Service e verifique:
A porta do Service que você está tentando acessar está listada em spec.ports[]?
O targetPort está correto para seus Pods (alguns Pods usam uma porta diferente da do Service)?
Se você pretende usar uma porta numérica, ela está especificada como um número (9376) ou como uma string ("9376")?
Se você pretende usar uma porta nomeada, seus Pods expõem uma porta com o mesmo nome?
O protocol da porta está correto para seus Pods?
O Service tem algum Endpoint?
Se você chegou até aqui, já confirmou que seu Service está corretamente
definido e resolvido pelo DNS. Agora, vamos verificar se os Pods que você
executou estão realmente sendo selecionados pelo Service.
Anteriormente, você viu que os Pods estavam em execução. Você pode verificar
novamente:
kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 1h
hostnames-632524106-ly40y 1/1 Running 0 1h
hostnames-632524106-tlaok 1/1 Running 0 1h
O argumento -l app=hostnames é um seletor de rótulo configurado no Service.
A coluna "AGE" indica que esses Pods têm cerca de uma hora de idade, o que
implica que estão funcionando corretamente e não estão falhando.
A coluna "RESTARTS" indica que esses Pods não estão falhando frequentemente
ou sendo reiniciados. Reinicializações frequentes podem causar problemas
intermitentes de conectividade. Se a contagem de reinicializações for alta,
leia mais sobre como depurar pods.
Dentro do sistema Kubernetes, existe um loop de controle que avalia o seletor
de cada Service e salva os resultados em um objeto Endpoints correspondente.
kubectl get endpoints hostnames
NAME ENDPOINTS
hostnames 10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376
Isso confirma que o controlador de endpoints encontrou os Pods corretos para
seu Service. Se a coluna ENDPOINTS estiver com <none>, você deve verificar
se o campo spec.selector do seu Service realmente seleciona os valores de
metadata.labels nos seus Pods. Um erro comum é ter um erro de digitação ou
outra inconsistência, como o Service selecionando app=hostnames, mas o
Deployment especificando run=hostnames, como em versões anteriores à 1.18,
onde o comando kubectl run também poderia ser usado para criar um Deployment.
Os Pods estão funcionando?
Neste ponto, você já sabe que seu Service existe e selecionou seus Pods. No
início deste passo a passo, você verificou os próprios Pods. Vamos verificar
novamente se os Pods estão realmente funcionando – você pode ignorar o
mecanismo do Service e ir diretamente para os Pods, conforme listado nos
Endpoints acima.
Nota:
Esses comandos usam a porta do Pod (9376), em vez da porta do Service (80).
De dentro de um Pod:
for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do wget -qO- $epdone
Você espera que cada Pod na lista de Endpoints retorne seu próprio hostname.
Se isso não acontecer (ou se o comportamento correto for diferente para seus
próprios Pods), você deve investigar o que está acontecendo.
O kube-proxy está funcionando?
Se você chegou até aqui, seu Service está em execução, possui Endpoints e seus
Pods estão realmente respondendo. Neste ponto, todo o mecanismo de proxy do
Service pode ser o problema. Vamos confirmá-lo, parte por parte.
A implementação padrão dos Services, e a mais usada na maioria dos clusters,
é o kube-proxy. Esse é um programa que roda em cada nó e configura um dos
mecanismos disponíveis para fornecer a abstração de Service. Se seu cluster
não usa kube-proxy, as próximas seções não se aplicarão, e você precisará
investigar qual implementação de Services está em uso.
O kube-proxy está em execução?
Confirme que o kube-proxy está rodando nos seus Nodes. Executando diretamente
em um Node, você deve obter algo como o seguinte:
Em seguida, confirme que ele não está falhando em algo óbvio, como contatar o
master. Para isso, você precisará verificar os logs. O acesso aos logs depende
do sistema operacional do Node. Em alguns sistemas, é um arquivo, como
/var/log/kube-proxy.log, enquanto em outros, os logs podem ser acessados com
journalctl. Você deve ver algo como:
I1027 22:14:53.995134 5063 server.go:200] Running in resource-only container "/kube-proxy"
I1027 22:14:53.998163 5063 server.go:247] Using iptables Proxier.
I1027 22:14:54.038140 5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns-tcp" to [10.244.1.3:53]
I1027 22:14:54.038164 5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns" to [10.244.1.3:53]
I1027 22:14:54.038209 5063 proxier.go:352] Setting endpoints for "default/kubernetes:https" to [10.240.0.2:443]
I1027 22:14:54.038238 5063 proxier.go:429] Not syncing iptables until Services and Endpoints have been received from master
I1027 22:14:54.040048 5063 proxier.go:294] Adding new service "default/kubernetes:https" at 10.0.0.1:443/TCP
I1027 22:14:54.040154 5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns" at 10.0.0.10:53/UDP
I1027 22:14:54.040223 5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns-tcp" at 10.0.0.10:53/TCP
Se você vir mensagens de erro sobre a impossibilidade de contatar o master,
deve verificar novamente a configuração do seu Node e as etapas de instalação.
O kube-proxy pode rodar em diferentes modos. No log listado acima, a linha
Using iptables Proxier indica que o kube-proxy está rodando no modo
"iptables". O outro modo mais comum é o "ipvs".
Modo Iptables
No modo "iptables", você deve ver algo como o seguinte em um Node:
iptables-save | grep hostnames
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR
Para cada porta de cada Service, deve haver uma regra em KUBE-SERVICES e
uma cadeia KUBE-SVC-<hash>. Para cada endpoint do Pod, deve haver um pequeno
número de regras nessa cadeia KUBE-SVC-<hash> e uma cadeia KUBE-SEP-<hash>
com algumas regras dentro dela. As regras exatas podem variar dependendo da sua
configuração específica (incluindo node-ports e load-balancers).
Modo IPVS
No modo "ipvs", você deve ver algo como o seguinte em um Node:
Para cada porta de cada Service, além de qualquer NodePort, IP externo e IP de
load-balancer, o kube-proxy criará um servidor virtual. Para cada endpoint de
Pod, ele criará servidores reais correspondentes. Neste exemplo, o Service
hostnames (10.0.1.175:80) tem 3 endpoints (10.244.0.5:9376,
10.244.0.6:9376, 10.244.0.7:9376).
O kube-proxy está realizando o proxy?
Supondo que você tenha identificado um dos casos acima, tente novamente acessar
seu Service pelo IP a partir de um dos seus Nodes:
curl 10.0.1.175:80
hostnames-632524106-bbpiw
Se isso ainda falhar, verifique os logs do kube-proxy em busca de linhas
específicas como:
Setting endpoints for default/hostnames:default to [10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376]
Se você não encontrar essas mensagens nos logs, tente reiniciar o kube-proxy
com a flag -v definida como 4 e, em seguida, verifique os logs novamente.
Caso extremo: Um Pod não consegue acessar a si mesmo pelo IP do Service
Isso pode parecer improvável, mas acontece e deveria funcionar corretamente.
Esse problema pode ocorrer quando a rede não está configurada corretamente para
tráfego "hairpin", geralmente quando o kube-proxy está rodando no modo
iptables e os Pods estão conectados por meio de uma rede bridge. O Kubelet
expõe um parâmetro hairpin-mode na linha de comando
que permite que os endpoints de um Service realizem balanceamento de carga para
si mesmos ao tentar acessar seu próprio VIP do Service. O parâmetro
hairpin-mode deve estar configurado como hairpin-veth ou promiscuous-bridge.
As etapas comuns para solucionar esse problema são as seguintes:
Confirme se o hairpin-mode está configurado como hairpin-veth ou
promiscuous-bridge. Você deve ver algo semelhante ao seguinte. No exemplo
abaixo, hairpin-mode está definido como promiscuous-bridge:
Confirme o hairpin-mode efetivo. Para isso, será necessário verificar o
log do kubelet. O acesso aos logs depende do sistema operacional do Node. Em
alguns sistemas, ele está em um arquivo como /var/log/kubelet.log, enquanto
em outros, os logs podem ser acessados com journalctl. Observe que o modo
hairpin efetivo pode não corresponder à flag --hairpin-mode devido a
questões de compatibilidade. Verifique se há linhas de log contendo a palavra-chave
hairpin no kubelet.log. Deve haver linhas indicando o modo hairpin efetivo,
como algo semelhante ao seguinte:
I0629 00:51:43.648698 3252 kubelet.go:380] Hairpin mode set to "promiscuous-bridge"
Se o modo hairpin efetivo for hairpin-veth, certifique-se de que o Kubelet
tem permissão para operar em /sys no Node. Se tudo estiver funcionando
corretamente, você deve ver algo como:
for intf in /sys/devices/virtual/net/cbr0/brif/*; do cat $intf/hairpin_mode; done
1
1
1
1
Se o modo hairpin efetivo for promiscuous-bridge, certifique-se de que o
Kubelet tem permissão para manipular a bridge Linux no Node. Se a bridge cbr0
for usada e configurada corretamente, você deve ver:
ifconfig cbr0 |grep PROMISC
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1460 Metric:1
Procure ajuda se nenhuma das opções acima funcionar.
Procure ajuda
Se você chegou até aqui, algo muito estranho está acontecendo. Seu Service
está rodando, tem Endpoints e seus Pods estão realmente respondendo. O DNS
está funcionando e o kube-proxy não parece estar com problemas. E, mesmo
assim, seu Service não está funcionando. Informe-nos o que está acontecendo,
para que possamos ajudar a investigar!
Você precisa ter um cluster Kubernetes e a ferramenta de linha de comando kubectl
configurada para se comunicar com seu cluster.
Você deve ter um StatefulSet em execução que deseja investigar.
Depuração de um StatefulSet
Para listar todos os Pods que pertencem a um StatefulSet e possuem o rótulo app.kubernetes.io/name=MyApp definido, você pode usar o seguinte comando:
kubectl get pods -l app.kubernetes.io/name=MyApp
Se você notar que algum dos Pods listados está no estado Unknown ou Terminating por um longo período, consulte a tarefa Excluindo Pods de um StatefulSet para obter instruções sobre como lidar com esses casos.
Você pode depurar Pods individuais em um StatefulSet utilizando o guia Depuração de Pods.
Esta página mostra como escrever e ler uma mensagem de término do contêiner.
Mensagens de término fornecem uma maneira para os contêineres registrarem informações sobre eventos fatais em um local onde possam ser facilmente recuperadas e exibidas por ferramentas como painéis e softwares de monitoramento. Na maioria dos casos, as informações incluídas em uma mensagem de término também devem ser registradas nos
logs do Kubernetes.
Antes de você começar
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Neste exercício, você cria um Pod que executa um único contêiner.
O manifesto para esse Pod especifica um comando que é executado quando o contêiner é iniciado:
No arquivo YAML, nos campos command e args, é possível ver que o
contêiner dorme por 10 segundos e, em seguida, escreve "Sleep expired"
no arquivo /dev/termination-log. Após escrever a mensagem "Sleep expired",
o contêiner é encerrado.
Exiba informações sobre o Pod:
kubectl get pod termination-demo
Repita o comando anterior até que o Pod não esteja mais em execução.
Use um template Go para filtrar a saída, de modo que inclua apenas a mensagem de término:
kubectl get pod termination-demo -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}"
Se você estiver executando um Pod com vários contêineres, pode usar um template Go
para incluir o nome do contêiner.
Dessa forma, você pode descobrir qual dos contêineres está falhando:
kubectl get pod multi-container-pod -o go-template='{{range .status.containerStatuses}}{{printf "%s:\n%s\n\n" .name .lastState.terminated.message}}{{end}}'
Personalizando a mensagem de término
O Kubernetes recupera mensagens de término do arquivo especificado no campo
terminationMessagePath de um contêiner, que tem o valor padrão de /dev/termination-log.
Ao personalizar esse campo, você pode instruir o Kubernetes a usar um arquivo diferente.
O Kubernetes usa o conteúdo do arquivo especificado para preencher a mensagem de status
do contêiner, tanto em casos de sucesso quanto de falha.
A mensagem de término deve ser um breve status final, como uma mensagem de falha de asserção.
O kubelet trunca mensagens que excedam 4096 bytes.
O tamanho total da mensagem entre todos os contêineres é limitado a 12KiB,
sendo dividido igualmente entre cada contêiner.
Por exemplo, se houver 12 contêineres (initContainers ou containers),
cada um terá 1024 bytes disponíveis para a mensagem de término.
O caminho padrão para a mensagem de término é /dev/termination-log.
Não é possível definir o caminho da mensagem de término após o lançamento de um Pod.
No exemplo a seguir, o contêiner grava mensagens de término em
/tmp/my-log para que o Kubernetes possa recuperá-las:
Além disso, os usuários podem definir o campo terminationMessagePolicy de um contêiner
para uma personalização adicional. Esse campo tem como valor padrão "File",
o que significa que as mensagens de término são recuperadas apenas do arquivo
de mensagem de término.
Ao definir terminationMessagePolicy como "FallbackToLogsOnError", você instrui
o Kubernetes a usar o último trecho do log de saída do contêiner caso o arquivo
de mensagem de término esteja vazio e o contêiner tenha encerrado com erro.
A saída do log é limitada a 2048 bytes ou 80 linhas, o que for menor.
Esta página mostra como investigar problemas relacionados à execução de contêineres de inicialização.
As linhas de comando de exemplo abaixo referem-se ao pod como <pod-name> e aos contêineres de inicialização como <init-container-1> e
<init-container-2>.
Antes de você começar
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
Você também pode acessar programaticamente os status dos contêineres de inicialização,
lendo o campo status.initContainerStatuses nas especificações do pod:
kubectl get pod nginx --template '{{.status.initContainerStatuses}}'
Este comando retornará as mesmas informações acima em JSON bruto.
Acessando logs de contêineres de inicialização
Passe o nome do contêiner de inicialização junto com o nome do Pod
para acessar seus logs.
kubectl logs <pod-name> -c <init-container-2>
Contêineres de inicialização que executam comandos de script de shell imprimem
à medida que são executados. Por exemplo, você pode fazer isso no Bash executando set -x no início do script.
Entendendo sobre o status do pod
Um status do Pod começando com Init: resume o status da execução de contêineres de inicialização.
A tabela abaixo descreve alguns valores de status de exemplo que você pode ver durante a depuração de contêineres de inicialização.
Status
Significado
Init:N/M
O pod tem contêineres de inicialização M e N que foram concluídas até agora.
Init:Error
Um contêiner de inicialização falhou ao executar.
Init:CrashLoopBackOff
Um contêiner de inicialização falhou repetidamente.
Pending
O pod ainda não começou a executar o contêiner de inicialização.
PodInitializing ou Running
O pod já concluiu a execução dos contêineres de inicialização.
1.6 - Depuração de Pods em Execução
Esta página explica como depurar Pods em execução (ou com falha) em um Nó.
Antes de você começar
Seu Pod já deve estar alocado e em execução.
Se o seu Pod ainda não estiver em execução, comece com Depuração de Pods.
Para algumas etapas avançadas de depuração, você precisa saber em qual Nó o Pod está sendo executado e ter acesso ao shell para executar comandos nesse Nó.
No entanto, você não precisa desse acesso para executar as etapas padrão de depuração que utilizam kubectl.
Usando kubectl describe pod para obter detalhes sobre os Pods
Neste exemplo, usaremos um Deployment para criar dois Pods, semelhante ao exemplo anterior.
NAME READY STATUS RESTARTS AGE
nginx-deployment-67d4bdd6f5-cx2nz 1/1 Running 0 13s
nginx-deployment-67d4bdd6f5-w6kd7 1/1 Running 0 13s
Podemos obter muito mais informações sobre cada um desses Pods usando kubectl describe pod. Por exemplo:
kubectl describe pod nginx-deployment-67d4bdd6f5-w6kd7
Name: nginx-deployment-67d4bdd6f5-w6kd7
Namespace: default
Priority: 0
Node: kube-worker-1/192.168.0.113
Start Time: Thu, 17 Feb 2022 16:51:01 -0500
Labels: app=nginx
pod-template-hash=67d4bdd6f5
Annotations: <none>
Status: Running
IP: 10.88.0.3
IPs:
IP: 10.88.0.3
IP: 2001:db8::1
Controlled By: ReplicaSet/nginx-deployment-67d4bdd6f5
Containers:
nginx:
Container ID: containerd://5403af59a2b46ee5a23fb0ae4b1e077f7ca5c5fb7af16e1ab21c00e0e616462a
Image: nginx
Image ID: docker.io/library/nginx@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 17 Feb 2022 16:51:05 -0500
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 128Mi
Requests:
cpu: 500m
memory: 128Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bgsgp (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-bgsgp:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 34s default-scheduler Successfully assigned default/nginx-deployment-67d4bdd6f5-w6kd7 to kube-worker-1
Normal Pulling 31s kubelet Pulling image "nginx"
Normal Pulled 30s kubelet Successfully pulled image "nginx" in 1.146417389s
Normal Created 30s kubelet Created container nginx
Normal Started 30s kubelet Started container nginx
Aqui você pode ver informações de configuração sobre o(s) contêiner(es) e o Pod (rótulos, requisitos de recursos, etc.), assim como informações de status sobre o(s) contêiner(es) e o Pod (estado, prontidão, contagem de reinicializações, eventos, etc.).
O estado do contêiner pode ser Waiting, Running ou Terminated. Dependendo do estado, informações adicionais serão fornecidas -- aqui você pode ver que, para um contêiner no estado Running, o sistema informa quando o contêiner foi iniciado.
Ready informa se o contêiner passou na última verificação de prontidão. (Neste caso, o contêiner não possui uma verificação de prontidão configurada; o contêiner é considerado pronto se nenhuma verificação de prontidão for configurada.)
Restart Count informa quantas vezes o contêiner foi reiniciado; essa informação pode ser útil para detectar loops de falha em contêineres configurados com a política de reinício 'Always'.
Atualmente, a única condição (campo Condition) associada a um Pod é a condição binária Ready, que indica se o Pod pode atender a solicitações e deve ser adicionado aos pools de balanceamento de carga de todos os serviços correspondentes.
Por fim, você verá um log dos eventos recentes relacionados ao seu Pod. "From" indica o componente que está registrando o evento. "Reason" e "Message" informam o que aconteceu.
Exemplo: depuração de Pods em estado Pending
Um cenário comum que você pode detectar usando eventos é quando você criou um Pod que não pode ser alocado em nenhum Nó. Por exemplo, o Pod pode solicitar mais recursos do que estão disponíveis em qualquer Nó, ou pode especificar um seletor de rótulo que não corresponde a nenhum Nó.
Vamos supor que criamos a instalação anterior com 5 réplicas (em vez de 2) e solicitando 600 milicores em vez de 500, em um cluster de quatro Nós onde cada máquina (virtual) possui 1 CPU. Nesse caso, um dos Pods não conseguirá ser alocado. (Observe que, devido aos Pods de complemento do cluster, como fluentd, skydns, etc., que são executados em cada Nó, se solicitássemos 1000 milicores, nenhum dos Pods poderia ser alocado.)
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-1006230814-6winp 1/1 Running 0 7m
nginx-deployment-1006230814-fmgu3 1/1 Running 0 7m
nginx-deployment-1370807587-6ekbw 1/1 Running 0 1m
nginx-deployment-1370807587-fg172 0/1 Pending 0 1m
nginx-deployment-1370807587-fz9sd 0/1 Pending 0 1m
Para descobrir por que o Pod nginx-deployment-1370807587-fz9sd não está em execução, podemos usar kubectl describe pod no Pod em estado Pending e verificar seus eventos:
kubectl describe pod nginx-deployment-1370807587-fz9sd
Name: nginx-deployment-1370807587-fz9sd
Namespace: default
Node: /
Labels: app=nginx,pod-template-hash=1370807587
Status: Pending
IP:
Controllers: ReplicaSet/nginx-deployment-1370807587
Containers:
nginx:
Image: nginx
Port: 80/TCP
QoS Tier:
memory: Guaranteed
cpu: Guaranteed
Limits:
cpu: 1
memory: 128Mi
Requests:
cpu: 1
memory: 128Mi
Environment Variables:
Volumes:
default-token-4bcbi:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-4bcbi
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 48s 7 {default-scheduler } Warning FailedScheduling pod (nginx-deployment-1370807587-fz9sd) failed to fit in any node
fit failure on node (kubernetes-node-6ta5): Node didn't have enough resource: CPU, requested: 1000, used: 1420, capacity: 2000
fit failure on node (kubernetes-node-wul5): Node didn't have enough resource: CPU, requested: 1000, used: 1100, capacity: 2000
Aqui você pode ver o evento gerado pelo escalonador informando que o Pod falhou ao ser alocado pelo motivo FailedScheduling (e possivelmente outros). A mensagem nos informa que não havia recursos suficientes para o Pod em nenhum dos Nós.
Para corrigir essa situação, você pode usar kubectl scale para atualizar seu Deployment e especificar quatro ou menos réplicas. (Ou você pode deixar um Pod em estado Pending, o que é inofensivo.)
Eventos como os que você viu no final de kubectl describe pod são armazenados no etcd e fornecem informações de alto nível sobre o que está acontecendo no cluster. Para listar todos os eventos, você pode usar
kubectl get events
mas você deve lembrar que os eventos são associados a namespaces. Isso significa que, se você estiver interessado em eventos de um objeto dentro de um namespace específico (por exemplo, o que aconteceu com os Pods no namespace my-namespace), você precisa fornecer explicitamente um namespace ao comando:
kubectl get events --namespace=my-namespace
Para ver eventos de todos os namespaces, você pode usar o argumento --all-namespaces.
Além de kubectl describe pod, outra maneira de obter informações adicionais sobre um Pod (além do que é fornecido por kubectl get pod) é usar a opção de formato de saída -o yaml com kubectl get pod. Isso fornecerá, no formato YAML, ainda mais informações do que kubectl describe pod — essencialmente, todas as informações que o sistema possui sobre o Pod.
Aqui, você verá itens como anotações (que são metadados no formato chave-valor sem as restrições dos rótulos, utilizadas internamente pelos componentes do sistema Kubernetes), política de reinício, portas e volumes.
kubectl get pod nginx-deployment-1006230814-6winp -o yaml
Se a imagem do contêiner incluir ferramentas de depuração, como é o caso de imagens baseadas nos sistemas operacionais Linux e Windows, você pode executar comandos dentro de um contêiner específico usando kubectl exec:
ESTADO DA FUNCIONALIDADE:Kubernetes v1.25 [stable]
Contêineres efêmeros são úteis para uma solução de problemas
interativa quando kubectl exec não é suficiente, como no caso de um contêiner que falhou ou uma imagem de contêiner
que não inclui ferramentas de depuração, como ocorre com imagens distroless.
Exemplo de depuração usando contêineres efêmeros
Você pode usar o comando kubectl debug para adicionar contêineres efêmeros a um Pod em execução.
Primeiro, crie um Pod para o exemplo:
kubectl run ephemeral-demo --image=registry.k8s.io/pause:3.1 --restart=Never
Os exemplos nesta seção usam a imagem do contêiner pause porque ela não contém ferramentas de depuração, mas esse método funciona com todas as imagens de contêiner.
Se você tentar usar kubectl exec para criar um shell, verá um erro, pois não há um shell nesta imagem de contêiner.
kubectl exec -it ephemeral-demo -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
Em vez disso, você pode adicionar um contêiner de depuração usando kubectl debug.
Se você especificar o argumento -i/--interactive, o kubectl conectará automaticamente ao console do Contêiner Efêmero.
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #
Este comando adiciona um novo contêiner busybox e o anexa. O parâmetro --target define o namespace de processo de outro contêiner.
Ele é necessário aqui porque kubectl run não habilita o compartilhamento do namespace de processo no Pod que ele cria.
Nota:
O parâmetro --target deve ser suportado pelo Agente de execução do Contêiner. Quando não for suportado, o Contêiner Efêmero pode não ser iniciado ou pode ser iniciado com um namespace de processo isolado, de modo que ps não revelará processos em outros contêineres.
Você pode visualizar o estado do contêiner efêmero recém-criado usando kubectl describe:
Use kubectl delete para remover o Pod quando terminar:
kubectl delete pod ephemeral-demo
Depuração usando uma cópia do Pod
Às vezes, as opções de configuração do Pod dificultam a solução de problemas em determinadas situações.
Por exemplo, você não pode executar kubectl exec para depurar seu contêiner se a imagem do contêiner
não incluir um shell ou se sua aplicação falhar na inicialização.
Nesses casos, você pode usar kubectl debug para criar uma cópia do Pod com valores de configuração
modificados para facilitar a depuração.
Copiando um Pod enquanto adiciona um novo contêiner
Adicionar um novo contêiner pode ser útil quando sua aplicação está em execução,
mas não se comporta como esperado e você deseja adicionar ferramentas adicionais
de depuração ao Pod.
Por exemplo, talvez as imagens do contêiner da sua aplicação sejam baseadas em busybox, mas você precise de ferramentas de depuração que não estão incluídas no busybox.
Você pode simular esse cenário usando kubectl run:
kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d
Execute este comando para criar uma cópia de myapp chamada myapp-debug, adicionando um novo contêiner Ubuntu para depuração:
Defaulting debug container name to debugger-w7xmf.
If you don't see a command prompt, try pressing enter.
root@myapp-debug:/#
Nota:
kubectl debug gera automaticamente um nome para o contêiner caso você não escolha um usando a opção --container.
A opção -i faz com que kubectl debug anexe ao novo contêiner por padrão.
Você pode impedir isso especificando --attach=false. Se sua sessão for desconectada, você pode se reconectar usando kubectl attach.
Não se esqueça de limpar o Pod de depuração quando terminar de usá-lo:
kubectl delete pod myapp myapp-debug
Copiando um Pod enquanto altera seu comando
Às vezes, é útil alterar o comando de um contêiner, por exemplo, para adicionar uma opção de depuração ou porque a aplicação está falhando.
Para simular uma aplicação com falha, use kubectl run para criar um contêiner que termine imediatamente:
kubectl run --image=busybox:1.28 myapp -- false
Você pode ver, usando kubectl describe pod myapp, que este contêiner está falhando:
Você pode usar kubectl debug para criar uma cópia deste Pod com o comando alterado para um shell interativo:
kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh
If you don't see a command prompt, try pressing enter.
/ #
Agora você tem um shell interativo que pode usar para realizar tarefas como verificar caminhos do sistema de arquivos ou executar manualmente o comando do contêiner.
Nota:
Para alterar o comando de um contêiner específico, você deve
especificar seu nome usando --container, caso contrário, kubectl debug
criará um novo contêiner para executar o comando especificado.
A opção -i faz com que kubectl debug anexe ao contêiner por padrão.
Você pode impedir isso especificando --attach=false. Se sua sessão for
desconectada, você pode se reconectar usando kubectl attach.
Não se esqueça de limpar o Pod de depuração quando terminar de usá-lo:
kubectl delete pod myapp myapp-debug
Copiando um Pod enquanto altera as imagens do contêiner
Em algumas situações, pode ser necessário alterar um Pod com comportamento inesperado, substituindo suas imagens de contêiner de produção por uma imagem contendo uma versão de depuração ou utilitários adicionais.
Como exemplo, crie um Pod usando kubectl run:
kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d
Agora use kubectl debug para criar uma cópia e alterar a imagem do contêiner para ubuntu:
A sintaxe de --set-image usa o mesmo formato container_name=image que kubectl set image.
*=ubuntu significa alterar a imagem de todos os contêineres para ubuntu.
Não se esqueça de limpar o Pod de depuração quando terminar de usá-lo:
kubectl delete pod myapp myapp-debug
Depuração via shell no Nó
Se nenhuma dessas abordagens funcionar, você pode identificar o Nó onde o Pod está sendo executado e criar um Pod nesse Nó.
Para criar um shell interativo em um Nó usando kubectl debug, execute:
kubectl debug node/mynode -it --image=ubuntu
Creating debugging pod node-debugger-mynode-pdx84 with container debugger on node mynode.
If you don't see a command prompt, try pressing enter.
root@ek8s:/#
Ao criar uma sessão de depuração em um Nó, tenha em mente que:
kubectl debug gera automaticamente o nome do novo Pod com base no nome do Nó.
O sistema de arquivos raiz do Nó será montado em /host.
O contêiner é executado nos namespaces de IPC, Rede e PID do host,
embora o Pod não seja privilegiado, então a leitura de algumas informações de
processos pode falhar, e chroot /host pode não funcionar.
Se você precisar de um Pod privilegiado, crie-o manualmente ou use a opção --profile=sysadmin.
Não se esqueça de limpar o Pod de depuração quando terminar de usá-lo:
kubectl delete pod node-debugger-mynode-pdx84
Depuração de um Pod ou Nó aplicando um perfil
Ao usar kubectl debug para depurar um Nó por meio de um Pod de depuração, um Pod por meio de um Contêiner Efêmero ou um Pod copiado, você pode aplicar um perfil a eles.
Ao aplicar um perfil, propriedades específicas, como securityContext, são definidas, permitindo a adaptação a diferentes cenários.
Existem dois tipos de perfis: perfil estático e perfil personalizado.
Aplicando um Perfil Estático
Um perfil estático é um conjunto de propriedades predefinidas que podem ser aplicadas usando a opção --profile.
Os perfis disponíveis são os seguintes:
Profile
Description
legacy
Um conjunto de propriedades para retrocompatibilidade com o comportamento da versão 1.22
general
Um conjunto razoável de propriedades genéricas para cada processo de depuração
Um conjunto de propriedades incluindo privilégios de Administrador de Rede
sysadmin
Um conjunto de propriedades incluindo privilégios de Administrador do Sistema (root)
Nota:
Se você não especificar --profile, o perfil legacy será usado por padrão, mas há planos para sua descontinuação em um futuro próximo.
Portanto, é recomendável usar outros perfis, como general.
Suponha que você crie um Pod e queira depurá-lo.
Primeiro, crie um Pod chamado myapp como exemplo:
kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d
Em seguida, depure o Pod usando um Contêiner Efêmero.
Se o Contêiner Efêmero precisar de privilégios, você pode usar o perfil sysadmin:
Targeting container "myapp". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-6kg4x.
If you don't see a command prompt, try pressing enter.
/ #
Verifique as capacidades do processo do Contêiner Efêmero executando o seguinte comando dentro do contêiner:
Isso significa que o processo do contêiner recebeu todas as capacidades de um contêiner privilegiado ao aplicar o perfil sysadmin.
Veja mais detalhes sobre capacidades.
Você também pode verificar que o Contêiner Efêmero foi criado como um contêiner privilegiado:
kubectl get pod myapp -o jsonpath='{.spec.ephemeralContainers[0].securityContext}'
{"privileged":true}
Remova o Pod quando terminar de usá-lo:
kubectl delete pod myapp
Aplicando um Perfil Personalizado
ESTADO DA FUNCIONALIDADE:Kubernetes v1.32 [stable]
Você pode definir uma especificação parcial de contêiner para depuração como um perfil personalizado,
em formato YAML ou JSON, e aplicá-lo usando a opção --custom.
Nota:
O perfil personalizado suporta apenas a modificação da especificação do contêiner,
mas não permite alterações nos campos name, image, command, lifecycle e volumeDevices da especificação do contêiner.
Ele também não suporta a modificação da especificação do Pod.
Crie um Pod chamado myapp como exemplo:
kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d
Crie um perfil personalizado no formato YAML ou JSON.
Aqui, crie um arquivo no formato YAML chamado custom-profile.yaml:
kubectl get pod myapp -o jsonpath='{.spec.ephemeralContainers[0].securityContext}'
{"capabilities":{"add":["NET_ADMIN","SYS_TIME"]}}
Remova o Pod quando terminar de usá-lo:
kubectl delete pod myapp
1.7 - Obter um Shell em um Contêiner em Execução
Esta página mostra como usar kubectl exec para obter um shell em um contêiner em execução.
Antes de você começar
Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:
O duplo traço (--) separa os argumentos que você deseja passar para o comando dos argumentos do kubectl.
No seu shell, liste o diretório raiz:
# Execute isso dentro do contêinerls /
No seu shell, experimente outros comandos. Aqui estão alguns exemplos:
# Você pode executar esses comandos de exemplo dentro do contêinerls /
cat /proc/mounts
cat /proc/1/maps
apt-get update
apt-get install -y tcpdump
tcpdump
apt-get install -y lsof
lsof
apt-get install -y procps
ps aux
ps aux | grep nginx
Escrevendo a página raiz para o nginx
Veja novamente o arquivo de configuração do seu Pod. O Pod
possui um volume emptyDir, e o contêiner monta esse volume
em /usr/share/nginx/html.
No seu shell, crie um arquivo index.html no diretório /usr/share/nginx/html:
# Execute isso dentro do contêinerecho'Hello shell demo' > /usr/share/nginx/html/index.html
No seu shell, envie uma solicitação GET para o servidor nginx:
# Execute isso no shell dentro do seu contêinerapt-get update
apt-get install curl
curl http://localhost/
A saída exibe o texto que você escreveu no arquivo index.html:
Hello shell demo
Quando terminar de usar o shell, digite exit.
exit# Para sair do shell no contêiner
Executando comandos individuais em um contêiner
Em uma janela de comando comum, fora do seu shell, liste as variáveis de ambiente no contêiner em execução:
kubectl exec shell-demo -- env
Experimente executar outros comandos. Aqui estão alguns exemplos:
kubectl exec shell-demo -- ps aux
kubectl exec shell-demo -- ls /
kubectl exec shell-demo -- cat /proc/1/mounts
Abrindo um shell quando um Pod tem mais de um contêiner
Se um Pod tiver mais de um contêiner, use --container ou -c para
especificar um contêiner no comando kubectl exec. Por exemplo,
suponha que você tenha um Pod chamado my-pod, e esse Pod tenha dois contêineres
chamados main-app e helper-app. O seguinte comando abriria um
shell no contêiner main-app.
A primeira coisa a depurar no seu cluster é se todos os seus nós estão registrados corretamente.
Execute o seguinte comando:
kubectl get nodes
E verifique se todos os nós que você espera ver estão presentes e se todos estão no estado Ready.
Para obter informações detalhadas sobre a integridade geral do seu cluster, você pode executar:
kubectl cluster-info dump
Exemplo: depurando um nó indisponível/inacessível
Às vezes, durante a depuração, pode ser útil verificar o status de um nó -- por exemplo, porque
você notou um comportamento estranho de um Pod que está executando no nó, ou para descobrir por que um Pod
não será alocado no nó. Assim como com os Pods, você pode usar kubectl describe node e kubectl get node -o yaml para recuperar informações detalhadas sobre os nós. Por exemplo, aqui está o que você verá se
um nó estiver indisponível (desconectado da rede, ou o kubelet morre e não reinicia, etc.). Observe
os eventos que mostram que o nó está NotReady, e também observe que os pods não estão mais em execução
(eles são removidos após cinco minutos de status NotReady).
kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-worker-1 NotReady <none> 1h v1.23.3
kubernetes-node-bols Ready <none> 1h v1.23.3
kubernetes-node-st6x Ready <none> 1h v1.23.3
kubernetes-node-unaj Ready <none> 1h v1.23.3
kubectl describe node kube-worker-1
Name: kube-worker-1
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=kube-worker-1
kubernetes.io/os=linux
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Thu, 17 Feb 2022 16:46:30 -0500
Taints: node.kubernetes.io/unreachable:NoExecute
node.kubernetes.io/unreachable:NoSchedule
Unschedulable: false
Lease:
HolderIdentity: kube-worker-1
AcquireTime: <unset>
RenewTime: Thu, 17 Feb 2022 17:13:09 -0500
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
NetworkUnavailable False Thu, 17 Feb 2022 17:09:13 -0500 Thu, 17 Feb 2022 17:09:13 -0500 WeaveIsUp Weave pod has set this
MemoryPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
DiskPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
PIDPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
Ready Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status.
Addresses:
InternalIP: 192.168.0.113
Hostname: kube-worker-1
Capacity:
cpu: 2
ephemeral-storage: 15372232Ki
hugepages-2Mi: 0
memory: 2025188Ki
pods: 110
Allocatable:
cpu: 2
ephemeral-storage: 14167048988
hugepages-2Mi: 0
memory: 1922788Ki
pods: 110
System Info:
Machine ID: 9384e2927f544209b5d7b67474bbf92b
System UUID: aa829ca9-73d7-064d-9019-df07404ad448
Boot ID: 5a295a03-aaca-4340-af20-1327fa5dab5c
Kernel Version: 5.13.0-28-generic
OS Image: Ubuntu 21.10
Operating System: linux
Architecture: amd64
Container Runtime Version: containerd://1.5.9
Kubelet Version: v1.23.3
Kube-Proxy Version: v1.23.3
Non-terminated Pods: (4 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
default nginx-deployment-67d4bdd6f5-cx2nz 500m (25%) 500m (25%) 128Mi (6%) 128Mi (6%) 23m
default nginx-deployment-67d4bdd6f5-w6kd7 500m (25%) 500m (25%) 128Mi (6%) 128Mi (6%) 23m
kube-system kube-proxy-dnxbz 0 (0%) 0 (0%) 0 (0%) 0 (0%) 28m
kube-system weave-net-gjxxp 100m (5%) 0 (0%) 200Mi (10%) 0 (0%) 28m
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 1100m (55%) 1 (50%)
memory 456Mi (24%) 256Mi (13%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
Events:
...
kubectl get node kube-worker-1 -o yaml
apiVersion:v1kind:Nodemetadata:annotations:node.alpha.kubernetes.io/ttl:"0"volumes.kubernetes.io/controller-managed-attach-detach:"true"creationTimestamp:"2022-02-17T21:46:30Z"labels:beta.kubernetes.io/arch:amd64beta.kubernetes.io/os:linuxkubernetes.io/arch:amd64kubernetes.io/hostname:kube-worker-1kubernetes.io/os:linuxname:kube-worker-1resourceVersion:"4026"uid:98efe7cb-2978-4a0b-842a-1a7bf12c05f8spec:{}status:addresses:- address:192.168.0.113type:InternalIP- address:kube-worker-1type:Hostnameallocatable:cpu:"2"ephemeral-storage:"14167048988"hugepages-2Mi:"0"memory:1922788Kipods:"110"capacity:cpu:"2"ephemeral-storage:15372232Kihugepages-2Mi:"0"memory:2025188Kipods:"110"conditions:- lastHeartbeatTime:"2022-02-17T22:20:32Z"lastTransitionTime:"2022-02-17T22:20:32Z"message:Weave pod has set thisreason:WeaveIsUpstatus:"False"type:NetworkUnavailable- lastHeartbeatTime:"2022-02-17T22:20:15Z"lastTransitionTime:"2022-02-17T22:13:25Z"message:kubelet has sufficient memory availablereason:KubeletHasSufficientMemorystatus:"False"type:MemoryPressure- lastHeartbeatTime:"2022-02-17T22:20:15Z"lastTransitionTime:"2022-02-17T22:13:25Z"message:kubelet has no disk pressurereason:KubeletHasNoDiskPressurestatus:"False"type:DiskPressure- lastHeartbeatTime:"2022-02-17T22:20:15Z"lastTransitionTime:"2022-02-17T22:13:25Z"message:kubelet has sufficient PID availablereason:KubeletHasSufficientPIDstatus:"False"type:PIDPressure- lastHeartbeatTime:"2022-02-17T22:20:15Z"lastTransitionTime:"2022-02-17T22:15:15Z"message:kubelet is posting ready statusreason:KubeletReadystatus:"True"type:ReadydaemonEndpoints:kubeletEndpoint:Port:10250nodeInfo:architecture:amd64bootID:22333234-7a6b-44d4-9ce1-67e31dc7e369containerRuntimeVersion:containerd://1.5.9kernelVersion:5.13.0-28-generickubeProxyVersion:v1.23.3kubeletVersion:v1.23.3machineID:9384e2927f544209b5d7b67474bbf92boperatingSystem:linuxosImage:Ubuntu 21.10systemUUID:aa829ca9-73d7-064d-9019-df07404ad448
Examinando logs
Por enquanto, investigar mais profundamente o cluster requer fazer login nas máquinas relevantes. Veja abaixo as localizações
dos arquivos de log relevantes. Em sistemas baseados em systemd, você pode precisar usar journalctl ao invés de examinar arquivos de log.
Nós da camada de gerenciamento
/var/log/kube-apiserver.log - Servidor de API, responsável por servir a API
/var/log/kube-scheduler.log - Agendador, responsável por tomar decisões de alocação
/var/log/kube-controller-manager.log - um componente que executa a maioria dos
controladores embutidos do Kubernetes, com a notável exceção da alocação
(o kube-scheduler lida com a alocação).
Nós de carga de trabalho
/var/log/kubelet.log - logs do kubelet, responsável por executar contêineres no nó
/var/log/kube-proxy.log - logs do kube-proxy, que é responsável por direcionar tráfego para endpoints de Service
Modos de falha do cluster
Esta é uma lista incompleta de coisas que podem dar errado e como ajustar a configuração do seu cluster para mitigar os problemas.
Causas contribuintes
Desligamento de VM(s)
Partição de rede dentro do cluster, ou entre cluster e usuários
Falhas no software do Kubernetes
Perda de dados ou indisponibilidade de armazenamento persistente (por exemplo, volume GCE PD ou AWS EBS)
Erro do operador, por exemplo, software do Kubernetes ou software de aplicação mal configurados
Cenários específicos
Desligamento de VM do servidor de API ou falha do servidor de API
Resultados
incapaz de parar, atualizar ou iniciar novos pods, services, replication controller
pods e services existentes devem continuar funcionando normalmente, a menos que dependam da API do Kubernetes
Armazenamento de apoio do servidor de API perdido
Resultados
o componente kube-apiserver falha ao iniciar com sucesso e se tornar íntegro
kubelets não conseguirão alcançá-lo, mas continuarão a executar os mesmos pods e fornecer o mesmo proxy de serviço
recuperação manual ou recriação do estado do servidor de API necessária antes que o servidor de API seja reiniciado
Desligamento ou falha de VM dos serviços de apoio (controlador de nó, gerenciador de replication controller, agendador, etc)
atualmente eles estão localizados junto com o servidor de API, e sua indisponibilidade tem consequências similares ao servidor de API
no futuro, estes serão replicados também e podem não estar localizados juntos
eles não têm seu próprio estado persistente
Nó individual (VM ou máquina física) desliga
Resultados
pods nesse nó param de executar
Partição de rede
Resultados
partição A pensa que os nós na partição B estão inativos; partição B pensa que o servidor de API está inativo.
(Assumindo que a VM principal fique na partição A.)
Falha de software do Kubelet
Resultados
kubelet com falha não consegue iniciar novos pods no nó
kubelet pode deletar os pods ou não
nó marcado como não íntegro
replication controllers iniciam novos pods em outros lugares
Erro do operador do cluster
Resultados
perda de pods, services, etc
perda do armazenamento de apoio do servidor de API
usuários incapazes de ler a API
etc.
Mitigações
Ação: Use a funcionalidade de reinicialização automática de VM do provedor IaaS para VMs IaaS
Mitiga: Desligamento de VM do servidor de API ou falha do servidor de API
Mitiga: Desligamento de VM de serviços de apoio ou falhas
Ação: Use armazenamento confiável de provedores IaaS (por exemplo, GCE PD ou volume AWS EBS) para VMs com servidor de API + etcd
Mitiga: Armazenamento de apoio do servidor de API perdido
Mitiga: Desligamento de nó da camada de gerenciamento ou falha de componentes da camada de gerenciamento (agendador, servidor de API, controller-manager)
Tolerará uma ou mais falhas simultâneas de nó ou componente
Mitiga: Armazenamento de apoio do servidor de API (ou seja, diretório de dados do etcd) perdido
Assume configuração de etcd HA (alta disponibilidade)
Ação: Fazer snapshot de PDs/volumes EBS do servidor de API periodicamente
Mitiga: Armazenamento de apoio do servidor de API perdido
Mitiga: Alguns casos de erro do operador
Mitiga: Alguns casos de falha de software do Kubernetes
Ação: usar replication controller e services na frente dos pods
Mitiga: Desligamento de nó
Mitiga: Falha de software do Kubelet
Ação: aplicações (contêineres) projetadas para tolerar reinicializações inesperadas
Esta documentação é sobre investigar e diagnosticar
problemas relacionados ao kubectl.
Se você encontrar problemas ao acessar o kubectl ou ao conectar-se ao seu cluster, este
documento descreve vários cenários comuns e possíveis soluções para ajudar
a identificar e resolver a causa provável.
Certifique-se de que você instalou e configurou o kubectl corretamente em sua máquina local.
Verifique a versão do kubectl para garantir que esteja atualizada e compatível com seu cluster.
Se você vir Unable to connect to the server: dial tcp <server-ip>:8443: i/o timeout,
ao invés de Server Version, você precisa solucionar problemas de conectividade do kubectl com seu cluster.
O kubectl requer um arquivo kubeconfig para conectar-se a um cluster Kubernetes. O
arquivo kubeconfig geralmente está localizado no diretório ~/.kube/config. Certifique-se
de que você tem um arquivo kubeconfig válido. Se você não tiver um arquivo kubeconfig, você pode
obtê-lo do seu administrador do Kubernetes, ou pode copiá-lo do diretório /etc/kubernetes/admin.conf
da camada de gerenciamento do seu Kubernetes. Se você implantou seu
cluster Kubernetes em uma plataforma de nuvem e perdeu seu arquivo kubeconfig, você pode
recriá-lo usando as ferramentas do seu provedor de nuvem. Consulte a
documentação do provedor de nuvem para recriar um arquivo kubeconfig.
Verifique se a variável de ambiente $KUBECONFIG está configurada corretamente. Você pode definir
a variável de ambiente $KUBECONFIG ou usar o parâmetro --kubeconfig com o kubectl
para especificar o diretório de um arquivo kubeconfig.
Verificar conectividade VPN
Se você está usando uma Rede Privada Virtual (VPN) para acessar seu cluster Kubernetes,
certifique-se de que sua conexão VPN está ativa e estável. Às vezes, desconexões
da VPN podem levar a problemas de conexão com o cluster. Reconecte-se à VPN e tente acessar
o cluster novamente.
Autenticação e autorização
Se você está usando autenticação baseada em token e o kubectl está retornando um erro
relacionado ao token de autenticação ou endereço do servidor de autenticação, valide se
o token de autenticação do Kubernetes e o endereço do servidor de autenticação estão configurados
adequadamente.
Se o kubectl está retornando um erro relacionado à autorização, certifique-se de que você está
usando as credenciais de usuário válidas. E que você tem a permissão para acessar o recurso
que você solicitou.
Verificar contextos
O Kubernetes suporta múltiplos clusters e contextos.
Certifique-se de que você está usando o contexto correto para interagir com seu cluster.
Listar contextos disponíveis:
kubectl config get-contexts
Alternar para o contexto apropriado:
kubectl config use-context <context-name>
Servidor de API e balanceador de carga
O servidor kube-apiserver é o
componente central de um cluster Kubernetes. Se o servidor de API ou o balanceador de carga que
executa na frente dos seus servidores de API não estiver acessível ou não estiver respondendo, você não conseguirá
interagir com o cluster.
Verifique se o host do servidor de API está acessível usando o comando ping. Verifique a
conectividade de rede e firewall do cluster. Se você estiver usando um provedor de nuvem para implantar
o cluster, verifique o status de verificação de saúde do seu provedor de nuvem para o
servidor de API do cluster.
Verifique o status do balanceador de carga (se usado) para garantir que esteja íntegro e encaminhando
tráfego para o servidor de API.
Problemas de TLS
Ferramentas adicionais necessárias - base64 e openssl versão 3.0 ou superior.
O servidor de API do Kubernetes serve apenas requisições HTTPS por padrão. Nesse caso, problemas de TLS
podem ocorrer por várias razões, como expiração de certificado ou validade da cadeia de confiança.
Você pode encontrar o certificado TLS no arquivo kubeconfig, localizado no diretório
~/.kube/config. O atributo certificate-authority contém o certificado CA e o
atributo client-certificate contém o certificado do cliente.
Algumas ferramentas auxiliares de autenticação do kubectl fornecem acesso fácil aos clusters Kubernetes. Se você
usou tais ferramentas auxiliares e está enfrentando problemas de conectividade, certifique-se de que as configurações
necessárias ainda estão presentes.
Verificar configuração do kubectl para detalhes de autenticação:
kubectl config view
Se você usou anteriormente uma ferramenta auxiliar (por exemplo, kubectl-oidc-login), certifique-se de que ela ainda esteja
instalada e configurada corretamente.
2.2 - Ferramentas para Monitorar Recursos
Para escalonar uma aplicação e fornecer um serviço confiável, você precisa
entender como a aplicação se comporta quando é implantada. Você pode examinar
o desempenho da aplicação em um cluster Kubernetes examinando os contêineres,
pods,
services, e
as características do cluster geral. O Kubernetes fornece informações detalhadas
sobre o uso de recursos de uma aplicação em cada um desses níveis.
Essas informações permitem que você avalie o desempenho da sua aplicação e
onde os gargalos podem ser removidos para melhorar o desempenho geral.
No Kubernetes, o monitoramento de aplicações não depende de uma única solução de monitoramento.
Em clusters novos, você pode usar pipelines de métricas de recursos ou
métricas completas para coletar estatísticas de monitoramento.
Pipeline de métricas de recursos
O pipeline de métricas de recursos fornece um conjunto limitado de métricas relacionadas aos
componentes do cluster, como o controlador
Horizontal Pod Autoscaler,
bem como o utilitário kubectl top.
Essas métricas são coletadas pelo
metrics-server leve, de curto prazo e em memória,
e são expostas via API metrics.k8s.io.
O metrics-server descobre todos os nós no cluster e
consulta o kubelet de cada nó para
uso de CPU e memória. O kubelet atua como uma ponte entre a camada de gerenciamento do Kubernetes e
os nós de carga de trabalho, gerenciando os pods e contêineres executando em uma máquina. O kubelet
traduz cada pod em seus contêineres integrantes e busca estatísticas de uso
de contêineres individuais do agente de execução de contêiner através da interface do agente
de execução de contêiner. Se você usa um agente de execução de contêiner que utiliza cgroups e
namespaces do Linux para implementar contêineres, e o agente de execução de contêiner não publica
estatísticas de uso, então o kubelet pode consultar essas estatísticas diretamente
(usando código do cAdvisor).
Não importa como essas estatísticas chegam, o kubelet então expõe as estatísticas agregadas de
uso de recursos do pod através da API de Métricas de Recursos do metrics-server.
Esta API é servida em /metrics/resource/v1beta1 nas portas autenticadas e
somente leitura do kubelet.
Pipeline de métricas completas
Um pipeline de métricas completas oferece acesso a métricas mais ricas. O Kubernetes pode
responder a essas métricas automaticamente escalonando ou adaptando o cluster
baseado no seu estado atual, usando mecanismos como o Horizontal Pod
Autoscaler. O pipeline de monitoramento busca métricas do kubelet e
então as expõe ao Kubernetes através de um adaptador que implemente a API
custom.metrics.k8s.io ou external.metrics.k8s.io.
Se você der uma olhada no
CNCF Landscape,
você pode ver vários projetos de monitoramento que podem funcionar com o Kubernetes coletando
dados de métricas e usando isso para ajudá-lo a observar seu cluster. Cabe a você selecionar a ferramenta
ou ferramentas que atendam às suas necessidades. O landscape da CNCF para observabilidade e análise inclui uma
mistura de software de código aberto, software-como-serviço pago e outros produtos comerciais.
Quando você projeta e implementa um pipeline de métricas completas, você pode tornar esses dados de monitoramento
disponíveis de volta ao Kubernetes. Por exemplo, um HorizontalPodAutoscaler pode usar as métricas processadas
para determinar quantos Pods executar para um componente da sua carga de trabalho.
A integração de um pipeline de métricas completas na sua implementação do Kubernetes está fora
do escopo da documentação do Kubernetes devido ao escopo muito amplo de possíveis
soluções.
A escolha da plataforma de monitoramento depende fortemente das suas necessidades, orçamento e recursos técnicos.
O Kubernetes não recomenda nenhum pipeline de métricas específico; muitas opções estão disponíveis.
Seu sistema de monitoramento deve ser capaz de lidar com o padrão de transmissão de métricas OpenMetrics
e precisa ser escolhido para se adequar melhor ao design geral e implantação da
sua plataforma de infraestrutura.
Próximos passos
Aprenda sobre ferramentas adicionais de depuração, incluindo:
Para o Kubernetes, a API de Métricas oferece um conjunto básico de métricas para dar suporte ao escalonamento automático e
casos de uso similares. Esta API disponibiliza informações sobre o uso de recursos para nó e pod, incluindo métricas para CPU e memória.
Se você implantar a API de Métricas em seu cluster, os clientes da API do Kubernetes podem então consultar essas informações,
e você pode usar os mecanismos de controle de acesso do Kubernetes para gerenciar permissões ao fazê-lo.
O HorizontalPodAutoscaler (HPA) e o
VerticalPodAutoscaler (VPA)
usam dados da API de métricas para ajustar réplicas e recursos de cargas de trabalho para atender à demanda do cliente.
Você também pode visualizar as métricas de recursos usando o comando
kubectl top.
Nota:
A API de Métricas e o pipeline de métricas que ela habilita oferecem apenas as métricas mínimas
de CPU e memória para habilitar o escalonamento automático usando HPA e/ou VPA.
Se você quiser fornecer um conjunto mais completo de métricas, você pode complementar
a API de Métricas mais simples implantando um segundo
pipeline de métricas
que usa a API de Métricas Personalizadas.
A Figura 1 ilustra a arquitetura do pipeline de métricas de recursos.
flowchart RL
subgraph cluster[Cluster]
direction RL
S[
]
A[Metrics- Server]
subgraph B[Nós]
direction TB
D[cAdvisor] --> C[kubelet]
E[Agente de execução do contêiner] --> D
E1[Agente de execução do contêiner] --> D
P[dados do pod] -.- C
end
L[Servidor de API]
W[HPA]
C ---->|métricas de recursos no nível do nó| A -->|API de métricas| L --> W
end
L ---> K[kubectl top]
classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000;
class W,B,P,K,cluster,D,E,E1 box
classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000
class S spacewhite
classDef k8s fill:#326ce5,stroke:#fff,stroke-width:1px,color:#fff;
class A,L,C k8s
Figura 1. Pipeline de Métricas de Recursos
Os componentes da arquitetura, da direita para a esquerda na figura, consistem no seguinte:
cAdvisor: Daemon para coletar, agregar e expor
métricas de contêiner incluído no Kubelet.
kubelet: Agente do nó para gerenciar recursos de contêiner.
As métricas de recursos são acessíveis usando os endpoints da API do kubelet /metrics/resource e /stats.
métricas de recursos no nível do nó: API fornecida pelo kubelet para descobrir e recuperar estatísticas resumidas por nó disponíveis através do endpoint /metrics/resource.
metrics-server: Componente complemento do cluster que coleta e agrega métricas de recursos extraídas de cada kubelet. O servidor de API serve a API de Métricas para uso pelo HPA, VPA e pelo comando kubectl top. O Metrics Server é uma implementação de referência da API de Métricas.
API de Métricas: API do Kubernetes que oferece suporte ao acesso à CPU e memória usadas para escalonamento automático de cargas de trabalho. Para fazer isso funcionar em seu cluster, você precisa de um servidor de extensão de API que forneça a API de Métricas.
Nota:
O cAdvisor oferece suporte à leitura de métricas de cgroups, que funciona com agentes de execução de contêiner típicos no Linux.
Se você usar um agente de execução de contêiner que usa outro mecanismo de isolamento de recursos, por exemplo
virtualização, então esse agente de execução de contêiner deve oferecer suporte às
Métricas de Contêiner CRI
para que as métricas estejam disponíveis para o kubelet.
API de Métricas
ESTADO DA FUNCIONALIDADE:Kubernetes 1.8 [beta]
O metrics-server implementa a API de Métricas. Esta API permite que você acesse o uso de CPU e memória
para os nós e pods em seu cluster. Seu papel principal é fornecer métricas de uso de recursos para os componentes
de escalonamento automático do K8s.
Aqui está um exemplo da solicitação da API de Métricas para um nó minikube direcionada através do jq para facilitar
a leitura:
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes/minikube" | jq '.'
Aqui está um exemplo da solicitação da API de Métricas para um pod kube-scheduler-minikube contido no
namespace kube-system e direcionada através do jq para facilitar a leitura:
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/kube-scheduler-minikube" | jq '.'
Você deve implantar o metrics-server ou adaptador alternativo que serve a API de Métricas para poder
acessá-la.
Medindo o uso de recursos
CPU
A CPU é reportada como o uso médio do núcleo medido em unidades de cpu. Uma cpu, no Kubernetes, é
equivalente a 1 vCPU/Núcleo para provedores de nuvem, e 1 hyper-thread em processadores Intel de servidor dedicado.
Este valor é derivado obtendo uma taxa sobre um contador cumulativo de CPU fornecido pelo kernel (em
kernels Linux e Windows). A janela de tempo usada para calcular a CPU é mostrada no campo window
na API de Métricas.
Para saber mais sobre como o Kubernetes aloca e mede recursos de CPU, consulte
significado da CPU.
Memória
A memória é reportada como o conjunto de trabalho, medido em bytes, no instante em que a métrica foi coletada.
Em um mundo ideal, o "conjunto de trabalho" é a quantidade de memória em uso que não pode ser liberada sob
pressão de memória. No entanto, o cálculo do conjunto de trabalho varia por sistema operacional do host, e geralmente faz
uso pesado de heurísticas para produzir uma estimativa.
O modelo do Kubernetes para o conjunto de trabalho de um contêiner espera que o agente de execução do contêiner conte
a memória anônima associada ao contêiner em questão. A métrica do conjunto de trabalho também inclui tipicamente alguma memória em cache (baseada em arquivo), porque o sistema operacional do host nem sempre pode recuperar páginas.
Para saber mais sobre como o Kubernetes aloca e mede recursos de memória, consulte
significado da memória.
Metrics Server
O metrics-server obtém métricas de recursos dos kubelets e as expõe no servidor de API do Kubernetes
através da API de Métricas para uso pelo HPA e VPA. Você também pode visualizar essas métricas
usando o comando kubectl top.
O metrics-server usa a API do Kubernetes para rastrear nós e pods em seu cluster. O
metrics-server consulta cada nó via HTTP para obter métricas. O metrics-server também constrói uma
visão interna dos metadados do pod e mantém um cache da integridade do pod. Essa informação de integridade do pod em cache
está disponível através da API de extensão que o metrics-server disponibiliza.
Por exemplo, com uma consulta HPA, o metrics-server precisa identificar quais pods atendem aos seletores de rótulos
na implantação.
O metrics-server chama a API do kubelet para
coletar métricas de cada nó. Dependendo da versão do metrics-server ele usa:
Endpoint de recurso de métricas /metrics/resource na versão v0.6.0+ ou
Endpoint da API de resumo /stats/summary em versões mais antigas