O ACK KubeSkoop, anteriormente conhecido como ACK Net Exporter, é um conjunto open source de monitoramento e diagnóstico de rede do Alibaba Cloud Container Service for Kubernetes. Ele ajuda a monitorar e solucionar rapidamente problemas complexos de rede no cluster. Este tópico apresenta as melhores práticas para usar o KubeSkoop em um cluster ACK gerenciado e resolver problemas reais.
Informações básicas
O KubeSkoop oferece uma série de recursos baseados em eBPF, incluindo monitoramento profundo de rede, diagnóstico de conectividade, captura de pacotes e sondagem de latência. Ele expõe métricas do Prometheus e eventos de anomalia. O KubeSkoop executa como um Pod DaemonSet em cada nó. A tecnologia eBPF coleta informações dos nós e as agrega para Pods específicos, fornecendo interfaces padronizadas de observabilidade para informações de rede de alto nível. A figura a seguir mostra a arquitetura principal do KubeSkoop.
Instalar e configurar o ACK KubeSkoop
Instalar o ACK KubeSkoop
Faça login no console do ACK. No painel de navegação à esquerda, clique em Clusters.
Na página Clusters, clique no nome do cluster. No painel de navegação à esquerda, clique em Components and Add-ons.
Na página Add-ons, pesquise ACK KubeSkoop, localize o componente e clique em Install.
No painel Install ACK KubeSkoop, clique em Confirm.
Configurar o KubeSkoop
-
Para configurar o componente KubeSkoop, edite o ConfigMap executando o seguinte comando:
kubectl edit cm kubeskoop-config -n ack-kubeskoop -
Como alternativa, configure o componente no console do ACK:
Faça login no console do ACK. No painel de navegação à esquerda, clique em Clusters.
Na página Clusters, clique no nome do cluster. No painel de navegação à esquerda, clique em .
Na página ConfigMaps, defina o Namespace como ack-kubeskoop, pesquise kubeskoop-config e clique em Edit na coluna Actions à direita de kubeskoop-config.
-
No painel Edit, configure os parâmetros e clique em OK. A tabela a seguir descreve as opções de configuração compatíveis com o KubeSkoop.
Parâmetro
Descrição
Padrão
debugmode
Define se o modo de depuração deve ser ativado. Valores válidos:
-
false: Modo de depuração desativado.
-
true: Modo de depuração ativado. Quando habilitado, esta opção fornece logs de nível DEBUG, interfaces de depuração e ferramentas de diagnóstico Go pprof e gops.
falseport
Porta do serviço de métricas, que fornece um endpoint HTTP.
9102enableController
Indica se o componente controller deve ser ativado. O controller interage com a API do Kubernetes para executar tarefas de monitoramento e gerenciamento.
truecontrollerAddr
Endereço do componente controller do KubeSkoop.
dns:kubeskoop-controller:10263metrics.probes
Lista de tipos de métricas de monitoramento a serem coletadas. Cada sonda corresponde a uma categoria de métrica.
metrics: probes: - name: conntrack - name: qdisc - name: netdev - name: io - name: sock - name: tcpsummary - name: tcp - name: tcpext - name: udp - name: rdmaPara mais informações, consulte Probes, Metrics, and Events.
O componente ACK KubeSkoop recarrega automaticamente as alterações de configuração do ConfigMap, portanto, não é necessário reiniciá-lo.
-
Configurar o painel do ARMS Prometheus
Faça login no console do ARMS.
No painel de navegação à esquerda, clique em Integration Management.
Na página Integration Management, clique em Add Integration. Na caixa de pesquisa, procure KubeSkoop e clique em ACK KubeSkoop Network Monitoring.
Na caixa de diálogo ACK KubeSkoop Network Monitoring, selecione o cluster ACK a ser integrado, insira um Integration Name e clique em OK para ativar o monitoramento do KubeSkoop.
Faça login no console do ACK. No painel de navegação à esquerda, clique em Clusters.
Na página Clusters, clique no nome do cluster. No painel de navegação à esquerda, clique em .
Clique na aba Others. Na lista de painéis, localize os painéis de monitoramento do KubeSkoop para nós e Pods, denominados Ack KubeSkoop Network Monitor - Node e Ack KubeSkoop Network Monitor - Pod.
Para mais informações sobre o Managed Service for Prometheus, consulte Integração com o Alibaba Cloud Managed Service for Prometheus.
Usar o KubeSkoop
Visualizar manualmente as métricas de monitoramento do KubeSkoop
O KubeSkoop fornece dados de monitoramento no formato Prometheus. Após instalar o KubeSkoop, acesse a porta de serviço de qualquer instância de Pod do KubeSkoop para obter todas as métricas.
-
Execute o seguinte comando para obter todas as instâncias do KubeSkoop.
kubectl get pod -n ack-kubeskoop -o wide | grep kubeskoop-agentSaída esperada:
kubeskoop-agent-2chvw 1/1 Running 0 43m 172.16.16.xxx cn-hangzhou.172.16.16.xxx <none> <none> kubeskoop-agent-2qtbf 1/1 Running 0 43m 172.16.16.xxx cn-hangzhou.172.16.16.xxx <none> <none> kubeskoop-agent-72pgf 1/1 Running 0 43m 172.16.16.xxx cn-hangzhou.172.16.16.xxx <none> <none> -
Execute o comando a seguir para obter as métricas. Substitua
172.16.16.xxxpelo endereço IP de uma instância do KubeSkoop obtida na etapa anterior.curl http://172.16.16.xxx:9102/metrics
O KubeSkoop fornece métricas de monitoramento no seguinte formato:
kubeskoop_netdev_rxbytes{k8s_namespace="",k8s_node="cn-hangzhou.172.16.16.xxx",k8s_pod=""} 2.970963745e+09
Solucionar problemas intermitentes de rede
As seções a seguir fornecem orientações para solucionar problemas típicos de ambientes cloud-native usando o ACK KubeSkoop.
Problemas de timeout de DNS
Em ambientes cloud-native, problemas de timeout no serviço de DNS podem causar falhas no acesso aos serviços. As causas comuns incluem:
O servidor DNS responde lentamente e não consegue concluir a consulta antes do timeout da aplicação.
Falha no envio oportuno do pacote de consulta DNS devido a um problema no lado do cliente.
O servidor responde prontamente, mas o remetente descarta pacotes devido a problemas como memória insuficiente.
Utilize as métricas abaixo para ajudar a solucionar problemas intermitentes de timeout de DNS:
|
Nome da métrica |
Descrição |
|
kubeskoop_pod_udpsndbuferrors |
Quantidade de erros ocorridos ao enviar dados UDP pela camada de rede. |
|
kubeskoop_pod_udpincsumerrors |
Número de erros de checksum ao receber pacotes UDP. |
|
kubeskoop_pod_udpnoports |
Vezes em que um Socket para a porta correspondente não foi encontrado quando a camada de rede chama |
|
kubeskoop_pod_udpinerrors |
Total de erros durante o recebimento de pacotes UDP. |
|
kubeskoop_pod_udpoutdatagrams |
Pacotes enviados com sucesso via UDP através da camada de rede. |
|
kubeskoop_pod_udprcvbuferrors |
Erros causados por fila de recepção de socket insuficiente ao copiar dados para a camada de aplicação. |
Como muitos serviços em ambientes cloud-native dependem do CoreDNS para resolução de nomes de domínio, observe também as métricas acima para Pods relacionados ao CoreDNS caso o problema envolva esse componente.
Erros HTTP 499/502/503/504 no Nginx Ingress
Gateways de Ingress e outros serviços de proxy frequentemente apresentam exceções intermitentes em ambientes cloud-native. Para o Nginx Ingress e outros proxies baseados em Nginx, os erros 499, 502, 503 e 504 são os mais comuns e indicam o seguinte:
-
499 Client Closed Request: O cliente fecha a conexão TCP antes que o Nginx responda. Causas frequentes incluem:O cliente estabelece a conexão, mas envia a solicitação tardiamente, atingindo o timeout do lado do cliente enquanto o Nginx ainda está respondendo. Isso é comum em frameworks de requisições assíncronas em clientes Android.
Processamento lento da conexão pelo servidor após o estabelecimento. Requer investigação adicional.
Lentidão do servidor ao processar solicitações enviadas ao backend upstream.
-
502 Bad Gateway: Geralmente indica problemas no nível de conexão entre o Nginx e o backend upstream, como falha de conexão ou fechamento anormal pelo backend. Motivos comuns:Falha na resolução de DNS para o backend configurado, frequente ao usar um Serviço do Kubernetes como backend.
Incapacidade de estabelecer conexão com o upstream.
Solicitação ou resposta upstream excessivamente grande, causando falhas na alocação de memória que interrompem as interações normais.
-
503 Service Unavailable: No Nginx, este código indica que todos os servidores upstream estão indisponíveis. Em cenários cloud-native, possui significados específicos. Causas prováveis:Ausência de backends disponíveis (cenário raro).
Tráfego excessivo sendo limitado pelo rate limit do Ingress.
504 Gateway Timeout: Indica um problema de timeout nos pacotes de negócio entre o Nginx e o upstream. A causa mais comum é uma resposta atrasada do upstream.
Ao encontrar esses problemas, colete primeiro informações gerais para determinar o escopo e definir os próximos passos da solução:
Informações do log de acesso do Nginx, especialmente
request_time,upstream_connect_timeeupstream_response_time.Revise o error_log do Nginx em busca de mensagens de erro anormais durante a ocorrência do problema.
Verifique o status das verificações de integridade (liveness ou readiness), caso estejam configuradas.
Com base nessas informações, monitore as variações nas métricas a seguir quando houver suspeita de falha de conexão:
|
Nome da métrica |
Descrição |
|
kubeskoop_tcpext_listenoverflow |
Incrementada quando a fila de meia-conexão de um socket no estado LISTEN transborda. |
|
kubeskoop_tcpext_listendrops |
Incrementada quando um socket no estado LISTEN falha ao criar um socket no estado SYN_RECV. |
|
kubeskoop_netdev_txdropped |
Vezes em que a placa de interface de rede (NIC) descartou pacotes devido a erro de transmissão. |
|
kubeskoop_netdev_rxdropped |
Descartes de pacotes pela NIC devido a erros de recepção. |
|
kubeskoop_tcp_activeopens |
Tentativas bem-sucedidas de início de handshake TCP com pacote SYN por um Pod. Não inclui retransmissões de SYN, mas conexões falhas também incrementam esta métrica. |
|
kubeskoop_tcp_passiveopens |
Total acumulado de handshakes TCP concluídos com alocação bem-sucedida de socket. Representa, em geral, o número de conexões estabelecidas com sucesso. |
|
kubeskoop_tcp_retranssegs |
Total de segmentos retransmitidos em um único Pod. O valor é calculado após a segmentação pelo TCP Segmentation Offload (TSO). |
|
kubeskoop_tcp_estabresets |
Fechamentos anormais de conexões TCP em um único Pod. Esta métrica contabiliza apenas o resultado final. |
|
kubeskoop_tcp_outrsts |
Pacotes de reset enviados pelo TCP em um único Pod. |
|
kubeskoop_conntrack_invalid |
Falhas no estabelecimento de entradas de rastreamento de conexão (conntrack) por diversos motivos, sem descarte do pacote. |
|
kubeskoop_conntrack_drop |
Pacotes descartados porque não foi possível estabelecer uma entrada conntrack. |
Se as respostas do Nginx estiverem lentas — por exemplo, quando ocorrem timeouts, mas o request_time do Nginx é curto — monitore as variações nas seguintes métricas:
|
Nome da métrica |
Descrição |
|
kubeskoop_tcpsummary_tcpestablishedconn |
Quantidade atual de conexões TCP no estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcptimewaitconn |
Conexões TCP atuais no estado TIME_WAIT. |
|
kubeskoop_tcpsummary_tcptxqueue |
Total de bytes na fila de envio das conexões TCP atualmente no estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcprxqueue |
Bytes totais na fila de recepção das conexões TCP em estado ESTABLISHED. |
|
kubeskoop_tcpext_tcpretransfail |
Incrementada quando um pacote retransmitido retorna um erro diferente de EBUSY, indicando falha na retransmissão. |
As variações nessas métricas durante o incidente ajudam a restringir o escopo da investigação .
Problemas de reset TCP
Um pacote de reset TCP é uma resposta a situações inesperadas no protocolo TCP. Normalmente, causa os seguintes erros em programas de usuário:
Erro
connection reset by peer, comum em aplicações dependentes de bibliotecas C, como o Nginx.Erro
Broken pipe, frequente em aplicações que utilizam wrappers de conexão TCP, como Java ou Python.
Em ambientes de rede cloud-native, existem vários motivos comuns para pacotes de reset. Alguns deles são:
Exceções no lado do servidor impedem o serviço normal, como memória insuficiente configurada para TCP. Essa situação geralmente dispara um reset proativo.
Ao usar um Serviço ou balanceamento de carga, o tráfego é encaminhado para um backend inesperado devido a anomalias em mecanismos com estado, como seleção de endpoints ou conntrack.
Liberação de conexão por motivos de segurança.
Em ambientes NAT ou cenários de alta concorrência, ocorre Protection Against Wrapped Sequence Numbers (PAWS) ou wraparound de números de sequência.
Uso de TCP Keepalive para manter conexões, mas sem comunicação de negócio normal por um longo período.
Para diferenciar rapidamente essas causas raiz, colete algumas informações básicas e métricas:
Analise a topologia de rede entre o cliente e o servidor no momento da geração do pacote de reset.
-
Monitore as variações nas seguintes métricas:
Nome da métrica
Descrição
kubeskoop_tcpext_tcpabortontimeout
Incrementada quando um reset é enviado porque o número máximo de chamadas de keepalive, window probe ou retransmissão foi excedido.
kubeskoop_tcpext_tcpabortonlinger
Resets enviados para recuperar rapidamente conexões no estado FIN_WAIT2 quando a opção TCP Linger2 está ativada.
kubeskoop_tcpext_tcpabortonclose
Incrementada quando um pacote de reset é enviado porque ainda há dados não lidos no momento do fechamento de uma conexão TCP por motivos externos à máquina de estados.
kubeskoop_tcpext_tcpabortonmemory
Resets enviados para encerrar uma conexão devido a memória insuficiente, acionados por
tcp_check_oomdurante a alocação de recursos comotw_sockoutcp_sock.kubeskoop_tcpext_tcpabortondata
Resets enviados para recuperação rápida de conexão quando a opção Linger ou Linger2 está habilitada.
kubeskoop_tcpext_tcpackskippedsynrecv
Vezes em que um socket no estado SYN_RECV não responde com um ACK.
kubeskoop_tcpext_tcpackskippedpaws
Casos em que um pacote ACK não é enviado devido ao limitador de taxa Out-of-Window (OOW), mesmo após correção pelo mecanismo PAWS.
kubeskoop_tcp_estabresets
Fechamentos anormais de conexões TCP em um único Pod. Esta métrica contabiliza apenas o resultado.
kubeskoop_tcp_outrsts
Pacotes de reset enviados pelo TCP em um único Pod.
Variação intermitente de latência de rede
A variação intermitente de latência de rede é um problema comum e difícil de diagnosticar em ambientes cloud-native. Possui muitas causas e pode levar aos três tipos de problemas mencionados anteriormente. Em cenários de rede de contêineres, a latência dentro de um nó geralmente tem as seguintes origens:
Um processo em tempo real gerenciado pelo escalonador RT executa por tempo excessivo, fazendo com que processos de negócio ou threads de kernel de rede fiquem enfileirados por muito tempo ou sejam processados lentamente.
O próprio processo sofre chamadas externas longas ocasionais, como respostas lentas de discos em nuvem ou aumentos intermitentes no Round-Trip Time (RTT) do RDS, retardando o processamento de requisições.
Problemas de configuração do nó levam a uma carga desigual entre diferentes CPUs ou nós NUMA, causando lentidão no sistema sobrecarregado.
Latência causada por mecanismos com estado no kernel, como a operação confirm do conntrack, ou muitos sockets órfãos afetando buscas normais de socket.
Embora esses problemas se manifestem como questões de rede, sua causa raiz frequentemente está relacionada a outros fatores do sistema operacional. Monitore as métricas a seguir para reduzir o escopo da investigação:
|
Nome da métrica |
Descrição |
|
kubeskoop_io_ioreadsyscall |
Vezes em que um processo realiza operações de leitura no sistema de arquivos, como |
|
kubeskoop_io_iowritesyscall |
Operações de escrita no sistema de arquivos realizadas por um processo, como |
|
kubeskoop_io_ioreadbytes |
Bytes lidos por um processo do sistema de arquivos, geralmente de um dispositivo de bloco. |
|
kubeskoop_io_iowritebytes |
Quantidade de bytes que um processo grava no sistema de arquivos. |
|
kubeskoop_tcpext_tcptimeouts |
Acionada quando o estado de Evitação de Congestionamento (CA) não entrou em recuperação, perda ou desordem. Incrementada quando um pacote SYN não é reconhecido e é retransmitido. |
|
kubeskoop_tcpsummary_tcpestablishedconn |
Número atual de conexões TCP no estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcptimewaitconn |
Conexões TCP atuais no estado TIME_WAIT. |
|
kubeskoop_tcpsummary_tcptxqueue |
Total de bytes na fila de envio das conexões TCP em estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcprxqueue |
Bytes totais na fila de recepção das conexões TCP atualmente ESTABLISHED. |
|
kubeskoop_softnet_processed |
Pacotes do backlog da NIC processados por todas as CPUs dentro de um único Pod. |
|
kubeskoop_softnet_dropped |
Pacotes descartados por todas as CPUs dentro de um único Pod. |
Estudos de caso
Os estudos de caso a seguir mostram como o ACK KubeSkoop foi usado para solucionar problemas complexos de rede.
Caso 1: Timeout intermitente de DNS
Problema
Um cliente enfrentou timeouts intermitentes na resolução de DNS. A aplicação do cliente rodava em PHP e o serviço de DNS estava configurado com CoreDNS.
Processo de solução
Com base na descrição do cliente, obtivemos dados de monitoramento relacionados ao DNS.
-
A análise dos dados durante o período de erro revelou o seguinte:
A métrica
kubeskoop_udp_noportsaumentou em 1 durante o período de erro. O valor geral da métrica era baixo.A métrica
kubeskoop_packetloss_totalaumentou em 1. A variação na perda de pacotes foi pequena.
O cliente informou que o endereço DNS configurado pertencia a um provedor de serviços público. Essa informação, combinada com os dados de monitoramento, indicou que uma resposta lenta do DNS era a causa raiz. O pacote de resposta do DNS chegou depois que a aplicação do lado do usuário já havia atingido o timeout.
Caso 2: Falhas intermitentes de conexão em Java
Problema
Um cliente relatou que sua instância Tomcat ficava indisponível intermitentemente, com cada interrupção durando de 5 a 10 segundos.
Processo de solução
A análise de logs confirmou que o Java Runtime do cliente estava realizando uma operação de Garbage Collection (GC) quando o problema ocorreu.
Após implantar o monitoramento do KubeSkoop, encontramos um aumento significativo na métrica
kubeskoop_tcpext_listendropsno momento do problema.Concluímos que, quando o Java Runtime do cliente realizava GC, a velocidade de processamento de requisições diminuía, atrasando a liberação de conexões. No entanto, novas solicitações de conexão não eram limitadas, criando um grande volume de conexões. Isso preencheu o backlog do socket de escuta e causou um transbordamento, levando ao aumento de
kubeskoop_tcpext_listendrops.O acúmulo de conexões do cliente era de curta duração e a capacidade de processamento não era um problema. Recomendamos que o cliente ajustasse os parâmetros relevantes do Tomcat, o que resolveu o problema.
Caso 3: Variação intermitente de latência de rede
Problema
Um cliente descobriu que as requisições entre sua aplicação e o Redis apresentavam aumentos intermitentes de RTT, causando timeouts de negócio. Contudo, o problema não pôde ser reproduzido.
Processo de solução
A análise de logs mostrou que o cliente sofreu requisições intermitentes ao Redis com tempo total de resposta superior a 300 ms.
Após implantar o KubeSkoop, os dados de monitoramento mostraram um aumento na métrica
kubeskoop_virtcmdlatency_latencyquando o problema ocorreu. Os valores dele(rótulo de bucket de histograma do Prometheus) que aumentaram foram 18 e 15. Isso indicou que duas chamadas de virtualização de alta latência haviam ocorrido. Aquela comle=15causou um atraso superior a 36 ms, e a comle=18causou um atraso superior a 200 ms.Como as chamadas de virtualização do kernel ocupam a CPU e não podem ser preemptadas, a latência intermitente foi causada por chamadas de virtualização de longa duração durante a criação e exclusão em lote de Pods.
Caso 4: Falhas na verificação de integridade do Ingress Nginx
Problema
A máquina de Ingress apresentou falhas intermitentes na verificação de integridade, acompanhadas de falhas em requisições de negócio.
Processo de solução
-
Após implantar o monitoramento, descobrimos que várias métricas apresentaram alterações anormais no momento do problema:
Tanto
kubeskoop_tcpsummary_tcprxqueuequantokubeskoop_tcpsummary_tcptxqueueaumentaram.Houve aumento em
kubeskoop_tcpext_tcptimeouts.kubeskoop_tcpsummary_tcptimewaitconndiminuiu, enquantokubeskoop_tcpsummary_tcpestablishedconnaumentou.
A análise confirmou que o kernel funcionava normalmente e as conexões estavam sendo estabelecidas corretamente. Entretanto, a execução do processo estava anormal, incluindo o processamento de pacotes do socket de recepção e o envio de pacotes. Suspeitamos de um problema de escalonamento ou limite de recursos no processo do usuário.
Uma revisão do monitoramento de Cgroup revelou que o cliente sofreu throttling de CPU no momento do problema. Isso provou que as limitações do Cgroup impediram intermitentemente o escalonamento do processo do usuário.
Seguindo o guia Ativar a política de otimização de desempenho CPU Burst, configuramos o recurso CPU Burst para o Ingress, o que resolveu esse tipo de problema.