ACK KubeSkoop, anteriormente conocido como ACK Net Exporter, es un conjunto de herramientas de código abierto para el monitoreo y diagnóstico de redes de Alibaba Cloud Container Service for Kubernetes. Le permite monitorear y solucionar rápidamente problemas de red complejos en su clúster. Este artículo presenta las mejores prácticas para usar KubeSkoop en un clúster de ACK administrado y resolver problemas reales.
Contexto
KubeSkoop ofrece diversas capacidades basadas en eBPF, como el monitoreo profundo de la red, el diagnóstico de conectividad, la captura de paquetes y la medición de latencia. Además, expone métricas de Prometheus y eventos anómalos. KubeSkoop se ejecuta como un Pod de DaemonSet en cada nodo. Utiliza la tecnología eBPF para recopilar información de los nodos y la agrega para Pods específicos. Esto proporciona interfaces estandarizadas de observability para la información de red de alto nivel. La siguiente figura muestra la arquitectura central de KubeSkoop.
Instalación y configuración de ACK KubeSkoop
Instalar ACK KubeSkoop
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre de su clúster. En el panel de navegación izquierdo, haga clic en Components and Add-ons .
En la página Add-ons, busque ACK KubeSkoop, localice el componente y haga clic en Install.
En el panel Install de ACK KubeSkoop, haga clic en Confirm.
Configurar KubeSkoop
-
Para configurar el componente KubeSkoop, edite su ConfigMap mediante la ejecución del siguiente comando:
kubectl edit cm kubeskoop-config -n ack-kubeskoop -
También puede configurar el componente desde la consola de ACK:
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre de su clúster. En el panel de navegación izquierdo, seleccione .
En la página ConfigMaps, establezca Namespace en ack-kubeskoop, busque kubeskoop-config y haga clic en Edit en la columna Actions, a la derecha de kubeskoop-config.
-
En el panel Edit, configure los parámetros y haga clic en OK. A continuación se describen las opciones de configuración compatibles con KubeSkoop.
Parámetro
Descripción
Valor predeterminado
debugmode
Indica si se habilita el modo de depuración. Valores válidos:
-
false: el modo de depuración está deshabilitado.
-
true: el modo de depuración está habilitado. Cuando se activa, esta opción proporciona registros de nivel DEBUG, interfaces de depuración y las herramientas de diagnóstico Go pprof y gops.
falseport
El puerto del servicio de métricas, que proporciona un endpoint HTTP.
9102enableController
Indica si se habilita el componente controlador. El controlador interactúa con la API de Kubernetes para ejecutar tareas de monitoreo y gestión.
truecontrollerAddr
La dirección del componente controlador de KubeSkoop.
dns:kubeskoop-controller:10263metrics.probes
Una lista de los tipos de métricas de monitoreo que se van a recopilar. Cada sonda corresponde a una categoría 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 obtener más información, consulte Probes, Metrics, and Events.
El componente ACK KubeSkoop recarga automáticamente los cambios de configuración del ConfigMap sin interrupciones, por lo que no es necesario reiniciarlo.
-
Configurar el panel de ARMS Prometheus
Inicie sesión en la consola de ARMS.
En el panel de navegación izquierdo, haga clic en Integration Management.
En la página Integration Management, haga clic en Add Integration. En el cuadro de búsqueda, escriba KubeSkoop y haga clic en ACK KubeSkoop Network Monitoring.
En el cuadro de diálogo ACK KubeSkoop Network Monitoring, seleccione el clúster de ACK que desea integrar, introduzca un Integration Name y haga clic en OK para habilitar el monitoreo de KubeSkoop.
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre de su clúster. En el panel de navegación izquierdo, seleccione .
Haga clic en la pestaña Others. En la lista de paneles encontrará los dashboards de monitoreo de KubeSkoop para nodos y Pods, llamados Ack KubeSkoop Network Monitor - Node y Ack KubeSkoop Network Monitor - Pod.
Para obtener más información sobre Managed Service for Prometheus, consulte Integrate with Alibaba Cloud Managed Service for Prometheus.
Uso de KubeSkoop
Consultar manualmente las métricas de monitoreo de KubeSkoop
KubeSkoop proporciona datos de monitoreo en formato Prometheus. Después de instalar KubeSkoop, acceda al puerto de servicio de cualquier instancia de Pod de KubeSkoop para recuperar todas las métricas.
-
Ejecute el siguiente comando para obtener todas las instancias de KubeSkoop.
kubectl get pod -n ack-kubeskoop -o wide | grep kubeskoop-agentResultado esperado:
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> -
Ejecute el siguiente comando para obtener las métricas. Reemplace
172.16.16.xxxcon la dirección IP de una instancia de KubeSkoop obtenida en el paso anterior.curl http://172.16.16.xxx:9102/metrics
KubeSkoop proporciona las métricas de monitoreo con el siguiente formato:
kubeskoop_netdev_rxbytes{k8s_namespace="",k8s_node="cn-hangzhou.172.16.16.xxx",k8s_pod=""} 2.970963745e+09
Solución de problemas de red intermitentes
En las siguientes secciones se describe cómo solucionar problemas típicos de entornos nativos de la nube mediante ACK KubeSkoop.
Problemas de tiempo de espera de DNS
En un entorno nativo de la nube, los tiempos de espera del servicio DNS pueden provocar errores de acceso a los servicios. Las causas más comunes incluyen:
El servidor DNS responde lentamente y no logra completar la consulta antes de que la aplicación agote su tiempo de espera.
El emisor no envía el paquete de consulta DNS a tiempo debido a un problema en el cliente.
El servidor responde a tiempo, pero el emisor descarta paquetes por problemas como falta de memoria.
Utilice las siguientes métricas para diagnosticar los problemas de tiempo de espera de DNS intermitentes:
|
Nombre de la métrica |
Descripción |
|
kubeskoop_pod_udpsndbuferrors |
Número de errores que ocurren al enviar datos UDP a través de la capa de red. |
|
kubeskoop_pod_udpincsumerrors |
Número de errores de suma de comprobación que ocurren al recibir paquetes UDP. |
|
kubeskoop_pod_udpnoports |
Número de veces que no se encuentra un socket para el puerto correspondiente cuando la capa de red llama a |
|
kubeskoop_pod_udpinerrors |
Número de errores que ocurren al recibir paquetes UDP. |
|
kubeskoop_pod_udpoutdatagrams |
Número de paquetes enviados correctamente por UDP a través de la capa de red. |
|
kubeskoop_pod_udprcvbuferrors |
Número de errores causados por una cola de recepción de socket insuficiente al copiar datos a la capa de aplicación. |
Dado que muchos servicios en un entorno nativo de la nube dependen de CoreDNS para la resolución de nombres de dominio, también debe revisar las métricas anteriores en los Pods relacionados con CoreDNS si el problema de DNS involucra a este componente.
Errores HTTP 499/502/503/504 en Nginx Ingress
En los entornos nativos de la nube, las puertas de enlace Ingress y otros servicios de proxy suelen presentar excepciones intermitentes. Para Nginx Ingress y otros servicios de proxy basados en Nginx, los errores más comunes son 499, 502, 503 y 504. Estos códigos indican lo siguiente:
-
499 Client Closed Request: el cliente cierra la conexión TCP antes de que Nginx responda. Las causas habituales incluyen:El cliente establece una conexión, pero envía la solicitud tarde. Esto provoca que se alcance el tiempo de espera del lado del cliente mientras Nginx responde. Es común en frameworks de solicitudes asíncronas en clientes Android.
El servidor procesa la conexión lentamente después de establecerla. Este caso requiere una investigación más profunda.
El servidor tarda en procesar las solicitudes enviadas al backend ascendente.
-
502 Bad Gateway: suele indicar problemas de conexión entre Nginx y el backend ascendente, como un fallo de conexión o un cierre anómalo por parte del backend. Las causas frecuentes son:Fallo en la resolución DNS del backend configurado, algo habitual cuando se usa un Service de Kubernetes como backend.
Imposibilidad de establecer una conexión con el servidor ascendente.
La solicitud o respuesta ascendente es demasiado grande, lo que genera fallos de asignación de memoria que interrumpen las interacciones normales del negocio.
-
503 Service Unavailable: en Nginx, este código de estado indica que todos los servidores ascendentes no están disponibles. En escenarios nativos de la nube tiene significados específicos. Las causas comunes incluyen:No hay backends disponibles, aunque es poco frecuente.
El tráfico es demasiado alto y el límite de velocidad de Ingress lo está restringiendo.
504 Gateway Timeout: este error indica un problema de tiempo de espera en los paquetes de negocio entre Nginx y el servidor ascendente. La causa habitual es una respuesta tardía del servidor ascendente.
Cuando enfrente estos problemas, primero recopile información general para determinar el alcance del incidente y definir los siguientes pasos de diagnóstico:
Revise la información del registro de acceso de Nginx, especialmente
request_time,upstream_connect_timeyupstream_response_time.Consulte la información de error_log de Nginx para detectar mensajes de error anómalos durante el incidente.
Si configuró una verificación de estado liveness o readiness, compruebe su estado.
Con base en esta información, supervise las variaciones de las siguientes métricas en el momento en que pudo ocurrir el fallo de conexión:
|
Nombre de la métrica |
Descripción |
|
kubeskoop_tcpext_listenoverflow |
Se incrementa cuando la cola de media conexión de un socket en estado LISTEN se desborda. |
|
kubeskoop_tcpext_listendrops |
Se incrementa cuando un socket en estado LISTEN no logra crear un socket en estado SYN_RECV. |
|
kubeskoop_netdev_txdropped |
Número de veces que la tarjeta de interfaz de red (NIC) descarta paquetes debido a un error de transmisión. |
|
kubeskoop_netdev_rxdropped |
Número de veces que la NIC descarta paquetes debido a un error de recepción. |
|
kubeskoop_tcp_activeopens |
Número de veces que un Pod inicia correctamente un saludo TCP con un paquete SYN. No incluye retransmisiones SYN, pero una conexión fallida también incrementa esta métrica. |
|
kubeskoop_tcp_passiveopens |
Número acumulado de veces que un Pod completa un saludo TCP y asigna correctamente un socket. Por lo general, se interpreta como el número de conexiones establecidas correctamente. |
|
kubeskoop_tcp_retranssegs |
Número total de segmentos retransmitidos en un solo Pod. El valor se calcula después de la segmentación realizada por TCP Segmentation Offload (TSO). |
|
kubeskoop_tcp_estabresets |
Número de veces que una conexión TCP se cierra de forma anómala en un solo Pod. Esta métrica solo contabiliza el resultado. |
|
kubeskoop_tcp_outrsts |
Número de paquetes de restablecimiento enviados por TCP en un solo Pod. |
|
kubeskoop_conntrack_invalid |
Número de veces que no se puede establecer una entrada de seguimiento de conexiones (conntrack) por diversos motivos, pero el paquete no se descarta. |
|
kubeskoop_conntrack_drop |
Número de paquetes descartados porque no se pudo establecer una entrada conntrack. |
Si nota que las respuestas de Nginx son lentas, por ejemplo, cuando ocurren tiempos de espera pero el valor request_time de Nginx es bajo, supervise las variaciones de las siguientes métricas:
|
Nombre de la métrica |
Descripción |
|
kubeskoop_tcpsummary_tcpestablishedconn |
Número actual de conexiones TCP en estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcptimewaitconn |
Número actual de conexiones TCP en estado TIME_WAIT. |
|
kubeskoop_tcpsummary_tcptxqueue |
Total de bytes de datos en la cola de envío de las conexiones TCP que se encuentran actualmente en estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcprxqueue |
Total de bytes de datos en la cola de recepción de las conexiones TCP que se encuentran actualmente en estado ESTABLISHED. |
|
kubeskoop_tcpext_tcpretransfail |
Se incrementa cuando un paquete retransmitido devuelve un error distinto de EBUSY, lo que indica que la retransmisión falló. |
Las variaciones de estas métricas durante el incidente le ayudarán a reducir el alcance de la investigación .
Problemas de restablecimiento TCP
Un paquete de restablecimiento TCP es una respuesta ante situaciones inesperadas en el protocolo TCP. Normalmente provoca los siguientes errores en los programas de usuario:
Error
connection reset by peer, común en aplicaciones que dependen de bibliotecas C, como Nginx.Error
Broken pipe, frecuente en aplicaciones que usan contenedores de conexiones TCP, como Java o Python.
En un entorno de red nativo de la nube existen muchas razones habituales para los paquetes de restablecimiento. A continuación se presentan algunas de las más comunes:
Excepciones en el servidor impiden el funcionamiento normal del servicio, como una configuración de memoria insuficiente para TCP. Esta situación suele desencadenar un restablecimiento proactivo.
Al usar un Service o balanceo de carga, el tráfico se reenvía a un backend inesperado debido a anomalías en mecanismos con estado, como la selección de endpoints o conntrack.
Liberación de la conexión por motivos de seguridad.
En entornos NAT o escenarios de alta concurrencia, se produce Protection Against Wrapped Sequence Numbers (PAWS) o un desbordamiento de números de secuencia.
Se utiliza TCP Keepalive para mantener las conexiones, pero no hay comunicación de negocio normal durante mucho tiempo.
Para diferenciar rápidamente estas causas raíz, recopile información básica y métricas:
Analice la topología de red entre el cliente y el servidor en el momento en que se generó el paquete de restablecimiento.
-
Supervise las variaciones de las siguientes métricas:
Nombre de la métrica
Descripción
kubeskoop_tcpext_tcpabortontimeout
Se incrementa cuando se envía un restablecimiento porque se superó el número máximo de llamadas keepalive, de sondeo de ventana o de retransmisión.
kubeskoop_tcpext_tcpabortonlinger
Número de restablecimientos enviados para recuperar rápidamente conexiones en estado FIN_WAIT2 cuando la opción TCP Linger2 está habilitada.
kubeskoop_tcpext_tcpabortonclose
Se incrementa cuando se envía un paquete de restablecimiento porque aún quedan datos sin leer al cerrar una conexión TCP por motivos ajenos a la máquina de estados.
kubeskoop_tcpext_tcpabortonmemory
Número de restablecimientos enviados para finalizar una conexión por falta de memoria, detectada por
tcp_check_oomal asignar recursos comotw_sockotcp_sock.Número de restablecimientos enviados para recuperar conexiones rápidamente cuando la opción Linger o Linger2 está habilitada.
kubeskoop_tcpext_tcpackskippedsynrecv
Número de veces que un socket en estado SYN_RECV no responde con un ACK.
kubeskoop_tcpext_tcpackskippedpaws
Número de veces que no se envía un paquete ACK debido a la limitación de velocidad Out-of-Window (OOW), aunque el mecanismo PAWS haya activado una corrección.
kubeskoop_tcp_estabresets
Número de veces que una conexión TCP se cierra de forma anómala en un solo Pod. Esta métrica solo contabiliza el resultado.
kubeskoop_tcp_outrsts
Número de paquetes de restablecimiento enviados por TCP en un solo Pod.
Variaciones intermitentes de latencia de red
Las variaciones intermitentes de latencia de red son un problema común y difícil de diagnosticar en entornos nativos de la nube. Tienen múltiples causas y pueden derivar en los tres tipos de problemas mencionados anteriormente. En un escenario de red de contenedores, la latencia dentro de un nodo suele deberse a lo siguiente:
Un proceso en tiempo real gestionado por el planificador RT se ejecuta durante demasiado tiempo. Esto provoca que los procesos de negocio o los hilos del kernel de red permanezcan en cola mucho tiempo o se procesen lentamente.
El propio proceso experimenta llamadas externas largas de forma ocasional, como respuestas lentas de discos en la nube o aumentos intermitentes en el tiempo de ida y vuelta (RTT) de RDS, lo que ralentiza el procesamiento de solicitudes.
Problemas de configuración del nodo generan una carga desigual entre distintas CPU o nodos NUMA, lo que retrasa al sistema sobrecargado.
Latencia provocada por mecanismos con estado en el kernel, como la operación confirm de conntrack, o por una gran cantidad de sockets huérfanos que afectan las búsquedas normales de sockets.
Aunque estos problemas se manifiestan como fallos de red, su causa raíz suele estar relacionada con otros factores del sistema operativo. Supervise las siguientes métricas para reducir el alcance de la investigación:
|
Nombre de la métrica |
Descripción |
|
kubeskoop_io_ioreadsyscall |
Número de veces que un proceso ejecuta operaciones de lectura del sistema de archivos, como |
|
kubeskoop_io_iowritesyscall |
Número de veces que un proceso ejecuta operaciones de escritura del sistema de archivos, como |
|
kubeskoop_io_ioreadbytes |
Número de bytes que un proceso lee del sistema de archivos, generalmente desde un dispositivo de bloques. |
|
kubeskoop_io_iowritebytes |
Número de bytes que un proceso escribe en el sistema de archivos. |
|
kubeskoop_tcpext_tcptimeouts |
Se activa cuando el estado de evitación de congestión (CA) no ha entrado en recuperación, pérdida o desorden. Se incrementa cuando un paquete SYN no recibe confirmación y se retransmite. |
|
kubeskoop_tcpsummary_tcpestablishedconn |
Número actual de conexiones TCP en estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcptimewaitconn |
Número actual de conexiones TCP en estado TIME_WAIT. |
|
kubeskoop_tcpsummary_tcptxqueue |
Total de bytes de datos en la cola de envío de las conexiones TCP que se encuentran actualmente en estado ESTABLISHED. |
|
kubeskoop_tcpsummary_tcprxqueue |
Total de bytes de datos en la cola de recepción de las conexiones TCP que se encuentran actualmente en estado ESTABLISHED. |
|
kubeskoop_softnet_processed |
Número de paquetes del backlog de la NIC procesados por todas las CPU dentro de un solo Pod. |
|
kubeskoop_softnet_dropped |
Número de paquetes descartados por todas las CPU dentro de un solo Pod. |
Casos de estudio
Los siguientes casos de estudio muestran cómo se utilizó ACK KubeSkoop para solucionar problemas de red complejos.
Caso 1: Tiempo de espera de DNS intermitente
Problema
Un cliente experimentaba tiempos de espera intermitentes en la resolución DNS. Su aplicación se ejecutaba en PHP y el servicio DNS estaba configurado con CoreDNS.
Proceso de diagnóstico
Con base en la descripción del cliente, obtuvimos los datos de monitoreo relacionados con DNS.
-
El análisis de los datos durante el periodo de error reveló lo siguiente:
La métrica
kubeskoop_udp_noportsaumentó en 1 durante el periodo de error. El valor general de la métrica era bajo.La métrica
kubeskoop_packetloss_totalaumentó en 1. La variación en la pérdida de paquetes fue mínima.
El cliente informó que la dirección DNS configurada pertenecía a un proveedor de servicios público. Esta información, combinada con los datos de monitoreo, indicó que una respuesta DNS lenta era la causa raíz. El paquete de respuesta DNS llegó después de que la aplicación del usuario ya hubiera agotado su tiempo de espera.
Caso 2: Fallos de conexión intermitentes en Java
Problema
Un cliente reportó que su instancia de Tomcat dejaba de estar disponible de forma intermitente, y cada interrupción duraba entre 5 y 10 segundos.
Proceso de diagnóstico
El análisis de registros confirmó que el entorno de ejecución de Java del cliente ejecutaba una operación de recolección de basura (GC) cuando ocurría el problema.
Después de desplegar el monitoreo de KubeSkoop, encontramos un aumento significativo en la métrica
kubeskoop_tcpext_listendropsen el momento del problema.Determinamos que, cuando el entorno de ejecución de Java del cliente realizaba la GC, la velocidad de procesamiento de solicitudes disminuía y retrasaba la liberación de conexiones. Sin embargo, las nuevas solicitudes de conexión no tenían límites, lo que generó una gran cantidad de conexiones. Esto llenó el backlog del socket de escucha y provocó un desbordamiento, causando el aumento de
kubeskoop_tcpext_listendrops.La acumulación de conexiones del cliente fue breve y la capacidad de procesamiento no representaba un problema. Recomendamos ajustar los parámetros correspondientes de Tomcat, lo cual resolvió la situación.
Caso 3: Variaciones intermitentes de latencia de red
Problema
Un cliente descubrió que las solicitudes entre su aplicación y Redis presentaban aumentos intermitentes de RTT, lo que provocaba tiempos de espera en el negocio. Sin embargo, no lograba reproducir el problema.
Proceso de diagnóstico
El análisis de registros mostró que el cliente experimentaba solicitudes intermitentes a Redis con un tiempo de respuesta total superior a 300 ms.
Tras desplegar KubeSkoop, los datos de monitoreo mostraron un aumento en la métrica
kubeskoop_virtcmdlatency_latencycuando ocurrió el problema. Los valores dele(etiqueta de bucket del histograma de Prometheus) que aumentaron fueron 18 y 15. Esto indicó que se produjeron dos llamadas de virtualización de alta latencia. La llamada conle=15causó un retraso de más de 36 ms, y la dele=18provocó un retraso de más de 200 ms.Dado que las llamadas de virtualización del kernel ocupan la CPU y no admiten expropiación, la latencia intermitente se debió a llamadas de virtualización prolongadas durante la creación y eliminación masiva de Pods.
Caso 4: Fallos en la verificación de estado de Ingress Nginx
Problema
La máquina de Ingress presentaba fallos intermitentes en la verificación de estado, acompañados de errores en las solicitudes de negocio.
Proceso de diagnóstico
-
Después de desplegar el monitoreo, encontramos que varias métricas mostraban variaciones anómalas en el momento del incidente:
Tanto
kubeskoop_tcpsummary_tcprxqueuecomokubeskoop_tcpsummary_tcptxqueueaumentaron.kubeskoop_tcpext_tcptimeoutsaumentó.kubeskoop_tcpsummary_tcptimewaitconndisminuyó ykubeskoop_tcpsummary_tcpestablishedconnaumentó.
El análisis confirmó que el kernel funcionaba correctamente y que las conexiones se establecían sin problemas. Sin embargo, la ejecución del proceso era anómala, incluido el procesamiento de paquetes del socket de recepción y el envío de paquetes. Sospechamos que existía un problema de planificación o de límite de recursos en el proceso de usuario.
La revisión del monitoreo de Cgroup reveló que el cliente experimentaba limitación de CPU en el momento del incidente. Esto demostró que las restricciones de Cgroup impedían intermitentemente la planificación del proceso de usuario.
Siguiendo la guía Enable the CPU Burst performance optimization policy, configuramos la función CPU Burst para Ingress, lo cual resolvió este tipo de problemas.