Solucionando Conectividade no Kubernetes: Usando exec e port-forward de Forma Eficaz
Solucione problemas de conectividade no Kubernetes e de aplicações internas com confiança. Este guia fornece exemplos práticos de uso de `kubectl exec` para executar comandos dentro de contêineres e `kubectl port-forward` para acessar serviços com segurança a partir de sua máquina local. Aprenda a diagnosticar problemas de rede, inspecionar configurações e obter insights profundos sobre o comportamento da sua aplicação dentro do cluster.
Solucionando Conectividade no Kubernetes: Usando exec e port-forward de Forma Eficaz
Quando um serviço Kubernetes atinge o tempo limite, geralmente você precisa responder a uma pergunta simples antes de poder consertar qualquer coisa: onde a conexão para de funcionar? kubectl exec permite testar de dentro do cluster, perto da aplicação. kubectl port-forward permite trazer um pod ou serviço de volta ao seu laptop sem alterar um Ingress, LoadBalancer, regra de firewall ou registro DNS.
Usados juntos, esses dois comandos ajudam a evitar suposições. Você pode testar se o aplicativo está ouvindo, se o DNS do cluster funciona, se um Service aponta para os pods corretos e se o problema está na rede do Kubernetes ou na própria aplicação.
Entendendo kubectl exec
O comando kubectl exec permite executar comandos dentro de um contêiner em execução em um pod. Isso é extremamente útil para inspecionar logs, verificar configurações e executar ferramentas de diagnóstico diretamente onde sua aplicação reside.
Use-o com cuidado em produção. Você está executando um comando dentro de um contêiner de carga de trabalho real. Um env, cat, curl ou ss inofensivo é normal. Instalar pacotes, alterar arquivos ou executar diagnósticos caros dentro de um pod ativo pode ocultar o problema original ou criar um novo.
Sintaxe Básica
A sintaxe fundamental para kubectl exec é:
kubectl exec <nome-do-pod> -- <comando> [args...]
<nome-do-pod>: O nome do pod no qual você deseja executar um comando.--: Este separador é crucial. Ele distingue entre flags dokubectle o comando que você deseja executar dentro do contêiner.<comando>: O comando a ser executado dentro do contêiner (por exemplo,ls,cat,ping).[args...]: Quaisquer argumentos para o comando.
Acesso Interativo ao Shell
Um dos usos mais comuns do kubectl exec é obter um shell interativo (como bash ou sh) dentro de um contêiner. Isso permite explorar o sistema de arquivos do contêiner e executar vários comandos.
Para obter um shell interativo:
kubectl exec -it <nome-do-pod> -- /bin/bash
-i(ou--stdin): Mantém a entrada padrão aberta mesmo se não estiver anexada.-t(ou--tty): Aloca um pseudo-TTY, necessário para sessões de shell interativas.
Exemplo: Acessando um shell bash em um pod chamado my-app-pod:
kubectl exec -it my-app-pod -- /bin/bash
Uma vez dentro, você pode usar comandos Linux padrão. Para sair do shell, digite exit ou pressione Ctrl+D. Se /bin/bash não estiver presente, tente /bin/sh; muitas imagens pequenas não vêm com Bash.
Executando um Único Comando
Você também pode executar um único comando sem um shell interativo. Isso é útil para verificações rápidas ou scripts.
Exemplo: Verificando arquivos no diretório /app do my-app-pod:
kubectl exec my-app-pod -- ls /app
Exemplo: Visualizando o conteúdo de um arquivo de configuração config.yaml:
kubectl exec my-app-pod -- cat /etc/my-app/config.yaml
Especificando um Contêiner dentro de um Pod
Se o seu pod tiver vários contêineres, você precisa especificar em qual contêiner executar o comando usando a flag -c.
kubectl exec <nome-do-pod> -c <nome-do-contêiner> -- <comando>
Exemplo: Executando env no sidecar-container do multi-container-pod:
kubectl exec multi-container-pod -c sidecar-container -- env
Entendendo kubectl port-forward
O comando kubectl port-forward permite estabelecer um túnel seguro de sua máquina local para um pod ou serviço específico em seu cluster Kubernetes. Isso é inestimável para depurar aplicações que não estão expostas externamente, acessar bancos de dados ou testar APIs internas.
Não é um caminho de tráfego de produção. É um túnel de depuração sobre sua conexão com a API do Kubernetes. Se a conexão com o servidor da API cair, seu túnel local também cairá.
Sintaxe Básica
A sintaxe geral é:
kubectl port-forward <nome-do-pod> <porta-local>:<porta-remota>
<nome-do-pod>: O nome do pod ao qual você deseja se conectar.<porta-local>: A porta em sua máquina local que escutará por conexões.<porta-remota>: A porta no pod que receberá o tráfego encaminhado.
Exemplo: Encaminhando a porta local 8080 para a porta 80 do my-app-pod:
kubectl port-forward my-app-pod 8080:80
Assim que este comando estiver em execução, você pode acessar sua aplicação navegando para http://localhost:8080 em seu navegador da web ou usando ferramentas como curl em sua máquina local.
Encaminhando para um Serviço
Você também pode encaminhar tráfego para um Serviço Kubernetes em vez de um pod específico. O kubectl selecionará automaticamente um pod que suporta esse serviço.
kubectl port-forward service/<nome-do-serviço> <porta-local>:<porta-do-serviço>
Exemplo: Encaminhando a porta local 3000 para a porta 80 do serviço my-service:
kubectl port-forward service/my-service 3000:80
Ao encaminhar para um Serviço, lembre-se de que o kubectl escolhe um pod de suporte. Se apenas uma réplica estiver quebrada, o encaminhamento em nível de serviço pode não detectá-la. Por exemplo, um Deployment com três pods pode ter dois pods saudáveis e um pod com uma configuração ruim. Encaminhar para service/my-service pode escolher um pod saudável e fazer o serviço parecer bom. Quando você suspeitar de um problema específico de réplica, encaminhe para o nome exato do pod.
Encaminhando para Deployments ou StatefulSets
Da mesma forma, você pode encaminhar para Deployments ou StatefulSets. O kubectl selecionará um dos pods gerenciados pelo recurso especificado.
kubectl port-forward deployment/<nome-do-deployment> <porta-local>:<porta-do-contêiner>
kubectl port-forward statefulset/<nome-do-statefulset> <porta-local>:<porta-do-contêiner>
Vinculando a um Endereço Específico
Por padrão, port-forward vincula-se a localhost. Você pode especificar um endereço local diferente usando a flag --address.
kubectl port-forward --address 127.0.0.1 <nome-do-pod> <porta-local>:<porta-remota>
Encaminhamento de Múltiplas Portas
kubectl port-forward pode encaminhar várias portas simultaneamente.
kubectl port-forward my-app-pod 8080:80 9090:90
Este comando encaminha a porta local 8080 para a porta 80 do pod e a porta local 9090 para a porta 90 do pod.
Cenários Comuns de Solução de Problemas e Soluções
Cenário 1: Aplicação não responde, mas o pod parece saudável.
- Problema: O pod está em execução, mas as solicitações ao seu serviço estão falhando ou expirando. A aplicação pode ter problemas de configuração interna ou estar travada.
- Solução com
kubectl exec:- Obtenha um shell interativo no pod:
kubectl exec -it <nome-do-pod> -- /bin/bash - Dentro do shell, verifique os logs da aplicação (por exemplo,
tail -f /var/log/myapp.log). - Verifique os arquivos de configuração interna da aplicação.
- Verifique a conectividade de rede de dentro do pod para outros serviços usando
pingoucurl(se instalados).
- Obtenha um shell interativo no pod:
- Solução com
kubectl port-forward:- Encaminhe uma porta para a porta de escuta da aplicação:
kubectl port-forward <nome-do-pod> 8080:<porta-da-aplicação> - Tente acessar a aplicação localmente via
http://localhost:8080. Isso ajuda a determinar se o problema está na descoberta de serviço ou ingress do Kubernetes, ou se a própria aplicação não está respondendo.
- Encaminhe uma porta para a porta de escuta da aplicação:
Se o port-forward funcionar, mas a URL normal do serviço falhar, inspecione o seletor do Service e os endpoints:
kubectl get service <nome-do-serviço> -n <namespace> -o yaml
kubectl get endpoints <nome-do-serviço> -n <namespace>
kubectl get pods -n <namespace> --show-labels
Uma falha muito comum é uma incompatibilidade de rótulos. Os pods estão saudáveis, o serviço existe, mas o seletor não corresponde aos rótulos do pod, então o Service não tem endpoints.
Cenário 2: Necessidade de depurar um banco de dados em execução em um pod.
- Problema: Você precisa conectar seu cliente de banco de dados local a um banco de dados em execução dentro de um pod Kubernetes para inspecionar dados ou executar consultas.
- Solução com
kubectl port-forward:- Identifique o pod que está executando o banco de dados e sua porta (por exemplo,
mysql-pod, porta3306). - Encaminhe uma porta local para a porta do banco de dados:
kubectl port-forward mysql-pod 3306:3306 - Configure seu cliente de banco de dados local para conectar-se a
localhost:3306usando as credenciais de banco de dados apropriadas.
- Identifique o pod que está executando o banco de dados e sua porta (por exemplo,
Cenário 3: Diagnosticando problemas de resolução de DNS dentro de um pod.
- Problema: Uma aplicação dentro de um pod não consegue alcançar outros serviços por seus nomes de serviço, sugerindo um problema de DNS.
- Solução com
kubectl exec:- Obtenha um shell interativo no pod:
kubectl exec -it <nome-do-pod> -- /bin/bash - Dentro do shell, tente resolver um nome de serviço conhecido:
nslookup <nome-do-serviço>.<namespace>.svc.cluster.localoudig <nome-do-serviço>.<namespace>.svc.cluster.local. - Verifique o conteúdo de
/etc/resolv.confpara garantir que a configuração de DNS do cluster esteja correta dentro do pod.
- Obtenha um shell interativo no pod:
Se a imagem não incluir nslookup, dig ou curl, use um pod de depuração temporário no mesmo namespace:
kubectl run net-debug -n <namespace> --rm -it --image=curlimages/curl -- sh
A partir daí, teste o mesmo nome de serviço que sua aplicação usa. Isso ajuda a separar "minha imagem de aplicação não tem ferramentas" de "o DNS do cluster está quebrado".
Cenário 4: Port-forward conecta, mas fecha imediatamente.
- Problema:
kubectl port-forwardimprime uma mensagem de encaminhamento, mas a conexão fecha quando você abre o navegador ou executacurl. - Causas prováveis: O processo de destino não está ouvindo na porta remota, a aplicação só se vincula a
127.0.0.1dentro do contêiner, ou o pod reinicia enquanto o túnel está aberto. - Verificações:
kubectl exec <nome-do-pod> -n <namespace> -- ss -lntp kubectl get pod <nome-do-pod> -n <namespace> -w kubectl logs <nome-do-pod> -n <namespace> --tail=100
Se o processo ouvir na porta 8080, mas você encaminhar para a 80, o túnel em si está bom; o alvo está errado. Se o pod reiniciar enquanto você testa, corrija a causa da reinicialização antes de perseguir problemas de rede.
Cenário 5: O serviço funciona de um pod, mas não de outro.
- Problema: Um backend consegue alcançar o Redis, mas um pod worker em outro namespace não consegue.
- Verificações com
exec:kubectl exec <pod-de-origem> -n <namespace-de-origem> -- curl -v http://<serviço>.<namespace-de-destino>.svc.cluster.local:<porta> kubectl exec <pod-de-origem> -n <namespace-de-origem> -- cat /etc/resolv.conf
Se o DNS resolver, mas o TCP falhar, verifique NetworkPolicies, endpoints de serviço e se a aplicação de destino aceita tráfego daquele namespace. Se o DNS não resolver, teste o nome de serviço totalmente qualificado antes de culpar a aplicação.
Uma Escada Simples de Conectividade
Quando uma solicitação falha, teste do mais próximo ao mais distante:
- Dentro do pod, teste o processo da aplicação local:
kubectl exec <pod> -n <namespace> -- curl -v http://127.0.0.1:<porta>/health - De um pod diferente no mesmo namespace, teste o Service:
kubectl run curl-test -n <namespace> --rm -it --image=curlimages/curl -- curl -v http://<serviço>:<porta>/health - Do seu laptop, teste através do port-forward:
kubectl port-forward service/<serviço> -n <namespace> 8080:<porta-do-serviço> curl -v http://localhost:8080/health - Somente depois que esses passarem, vá para fora, para Ingress, balanceadores de carga, DNS e regras de firewall.
Essa ordem economiza tempo porque cada etapa prova uma camada. Se o localhost dentro do pod falhar, o Ingress é irrelevante. Se o pod-local for bem-sucedido, mas o acesso ao Service falhar, a aplicação provavelmente está boa e a descoberta de serviço do Kubernetes precisa de atenção.
Mais um hábito ajuda: mantenha o namespace explícito durante a depuração. Muitas sessões confusas vêm de executar kubectl exec no namespace padrão enquanto a carga de trabalho quebrada está em outro lugar. Defina o namespace em seu contexto para a sessão ou adicione -n <namespace> a cada comando. A digitação extra é mais barata do que testar o pod errado.
Também salve o comando exato que provou a falha. A próxima pessoa de plantão pode executá-lo novamente sem reconstruir seu contexto de memória.
Melhores Práticas e Dicas
- Mantenha
port-forwardem execução:kubectl port-forwardé executado em primeiro plano. Você precisará manter a janela do terminal aberta. Para executá-lo em segundo plano, você pode usar ferramentas comonohupouscreen/tmux. - Use pods específicos ao depurar: Embora encaminhar para serviços seja conveniente, para identificar problemas com uma instância específica, encaminhar para um pod específico usando seu nome é geralmente mais eficaz.
- Segurança: Esteja atento às portas que você expõe. Evite encaminhar portas sensíveis, a menos que seja absolutamente necessário, e certifique-se de que sua máquina local esteja segura.
- Uso de Recursos:
kubectl execpode consumir recursos. Use-o com moderação, especialmente em clusters de produção. - Permissões: Certifique-se de que seu contexto
kubectltenha as permissões necessárias para executar comandos em pods ou encaminhar portas.
O que Anotar Depois de Corrigir
Uma boa depuração deixa um rastro. Capture a URL com falha, o pod de origem, o serviço de destino, o namespace, o comando exato que reproduziu o problema e a camada onde falhou. "Problema de conectividade" é muito vago para ajudar da próxima vez. "O seletor do Service não correspondia aos pods após a renomeação do rótulo" é um padrão corrigível.