ACK KubeSkoop, anciennement ACK Net Exporter, est une suite open source de surveillance et de diagnostic réseau proposée par Alibaba Cloud Container Service for Kubernetes. Elle vous aide à surveiller votre cluster et à résoudre rapidement des problèmes réseau complexes. Cet article présente les bonnes pratiques d'utilisation de KubeSkoop dans un cluster ACK managé pour résoudre des problèmes concrets.
Informations générales
KubeSkoop offre diverses fonctionnalités basées sur eBPF, notamment la surveillance approfondie du réseau, le diagnostic de la connectivité réseau, la capture de paquets et la sonde de latence. Il expose des métriques Prometheus et des événements d'anomalie. KubeSkoop s'exécute en tant que Pod DaemonSet sur chaque nœud. Il utilise la technologie eBPF pour collecter des informations depuis les nœuds et les agréger pour des Pods spécifiques, fournissant ainsi des interfaces d'observabilité standardisées pour les informations réseau de haut niveau. Le schéma suivant illustre l'architecture principale de KubeSkoop.
Installation et configuration d'ACK KubeSkoop
Installation d'ACK KubeSkoop
Connectez-vous à la console ACK. Dans le volet de navigation de gauche, cliquez sur Clusters.
Sur la page Clusters, cliquez sur le nom de votre cluster. Dans le volet de navigation de gauche, cliquez sur Components and Add-ons .
Sur la page Add-ons, recherchez ACK KubeSkoop, identifiez le composant, puis cliquez sur Install.
Dans le panneau Install ACK KubeSkoop, cliquez sur Confirm.
Configuration de KubeSkoop
-
Pour configurer le composant KubeSkoop, modifiez sa ConfigMap en exécutant la commande suivante :
kubectl edit cm kubeskoop-config -n ack-kubeskoop -
Vous pouvez également configurer le composant via la console ACK :
Connectez-vous à la console ACK. Dans le volet de navigation de gauche, cliquez sur Clusters.
Sur la page Clusters, cliquez sur le nom de votre cluster. Dans le volet de navigation de gauche, cliquez sur .
Sur la page ConfigMaps, définissez le paramètre Namespace sur ack-kubeskoop, recherchez kubeskoop-config, puis cliquez sur Edit dans la colonne Actions à droite de kubeskoop-config.
-
Dans le panneau Edit, configurez les paramètres, puis cliquez sur OK. Le tableau suivant décrit les options de configuration prises en charge par KubeSkoop.
Paramètre
Description
Valeur par défaut
debugmode
Indique si le mode de débogage est activé. Valeurs possibles :
-
false : le mode de débogage est désactivé.
-
true : le mode de débogage est activé. Lorsque cette option est activée, elle fournit des journaux au niveau DEBUG, des interfaces de débogage ainsi que les outils de diagnostic Go pprof et gops.
falseport
Port du service de métriques, qui expose un endpoint HTTP.
9102enableController
Indique si le composant contrôleur est activé. Le contrôleur interagit avec l'API Kubernetes pour surveiller et gérer le cluster.
truecontrollerAddr
Adresse du composant contrôleur KubeSkoop.
dns:kubeskoop-controller:10263metrics.probes
Liste des types de métriques de surveillance à collecter. Chaque sonde correspond à une catégorie de métriques.
metrics: probes: - name: conntrack - name: qdisc - name: netdev - name: io - name: sock - name: tcpsummary - name: tcp - name: tcpext - name: udp - name: rdmaPour plus d'informations, consultez Probes, Metrics, and Events.
Le composant ACK KubeSkoop recharge automatiquement à chaud les modifications de configuration apportées à la ConfigMap ; il n'est donc pas nécessaire de le redémarrer.
-
Configuration du tableau de bord ARMS Prometheus
Connectez-vous à la console ARMS.
Dans le volet de navigation de gauche, cliquez sur Integration Management.
Sur la page Integration Management, cliquez sur Add Integration. Dans la zone de recherche, saisissez KubeSkoop, puis cliquez sur ACK KubeSkoop Network Monitoring.
Dans la boîte de dialogue ACK KubeSkoop Network Monitoring, sélectionnez le cluster ACK à intégrer, saisissez un Integration Name, puis cliquez sur OK pour activer la surveillance KubeSkoop.
Connectez-vous à la console ACK. Dans le volet de navigation de gauche, cliquez sur Clusters.
Sur la page Clusters, cliquez sur le nom de votre cluster. Dans le volet de navigation de gauche, cliquez sur .
Cliquez sur l'onglet Others. Dans la liste des tableaux de bord, vous trouverez les tableaux de bord de surveillance KubeSkoop pour les nœuds et les Pods, nommés Ack KubeSkoop Network Monitor - Node et Ack KubeSkoop Network Monitor - Pod.
Pour plus d'informations sur Managed Service for Prometheus, consultez Intégration avec Alibaba Cloud Managed Service for Prometheus.
Utilisation de KubeSkoop
Consultation manuelle des métriques de surveillance KubeSkoop
KubeSkoop fournit des données de surveillance au format Prometheus. Après l'installation de KubeSkoop, accédez au port de service de n'importe quelle instance de Pod KubeSkoop pour récupérer toutes les métriques.
-
Exécutez la commande suivante pour obtenir toutes les instances KubeSkoop.
kubectl get pod -n ack-kubeskoop -o wide | grep kubeskoop-agentRésultat attendu :
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> -
Exécutez la commande suivante pour obtenir les métriques. Remplacez
172.16.16.xxxpar l'adresse IP d'une instance KubeSkoop obtenue à l'étape précédente.curl http://172.16.16.xxx:9102/metrics
KubeSkoop fournit les métriques de surveillance au format suivant :
kubeskoop_netdev_rxbytes{k8s_namespace="",k8s_node="cn-hangzhou.172.16.16.xxx",k8s_pod=""} 2.970963745e+09
Dépannage des problèmes réseau intermittents
Les sections suivantes fournissent des conseils pour résoudre les problèmes cloud-native typiques à l'aide d'ACK KubeSkoop.
Problèmes de délai d'expiration DNS
Dans un environnement cloud-native, les délais d'expiration du service DNS peuvent entraîner des échecs d'accès aux services. Les causes courantes des délais d'expiration DNS incluent :
Le serveur DNS répond lentement et ne peut pas terminer une requête DNS avant l'expiration du délai de l'application.
L'émetteur ne parvient pas à envoyer rapidement le paquet de requête DNS en raison d'un problème côté client.
Le serveur répond rapidement, mais l'émetteur perd des paquets en raison de problèmes tels qu'un manque de mémoire.
Utilisez les métriques suivantes pour aider à résoudre les problèmes intermittents de délai d'expiration DNS :
|
Nom de la métrique |
Description |
|
kubeskoop_pod_udpsndbuferrors |
Nombre d'erreurs survenant lors de l'envoi de données UDP via la couche réseau. |
|
kubeskoop_pod_udpincsumerrors |
Nombre d'erreurs de somme de contrôle survenant lors de la réception de paquets UDP. |
|
kubeskoop_pod_udpnoports |
Nombre de fois où un Socket pour le port correspondant est introuvable lorsque la couche réseau appelle |
|
kubeskoop_pod_udpinerrors |
Nombre d'erreurs survenant lors de la réception de paquets UDP. |
|
kubeskoop_pod_udpoutdatagrams |
Nombre de paquets envoyés avec succès par UDP via la couche réseau. |
|
kubeskoop_pod_udprcvbuferrors |
Nombre d'erreurs causées par une file d'attente de réception de socket insuffisante lors de la copie des données vers la couche application. |
Étant donné que de nombreux services dans un environnement cloud-native s'appuient sur CoreDNS pour la résolution de noms de domaine, observez également les métriques précédentes pour les Pods liés à CoreDNS si le problème DNS concerne ce dernier.
Erreurs Nginx Ingress HTTP 499/502/503/504
Dans les environnements cloud-native, les passerelles Ingress et autres services proxy rencontrent souvent des exceptions intermittentes. Pour Nginx Ingress et autres services proxy basés sur Nginx, les erreurs 499, 502, 503 et 504 sont les plus courantes. Elles indiquent ce qui suit :
-
499 Client Closed Request: le client ferme la connexion TCP avant que Nginx ne réponde. Les causes courantes incluent :Le client établit une connexion mais envoie la requête tardivement, ce qui entraîne l'atteinte du délai d'expiration côté client pendant que Nginx répond. Ce cas est fréquent dans les frameworks de requêtes asynchrones sur les clients Android.
Le serveur traite la connexion lentement après son établissement. Cela nécessite une investigation plus poussée.
Le serveur traite lentement les requêtes envoyées au backend amont (upstream).
-
502 Bad Gateway: cela indique souvent des problèmes au niveau de la connexion entre Nginx et le backend amont, tels qu'un échec de connexion ou une fermeture anormale par le backend. Les causes courantes incluent :Échec de la résolution DNS pour le backend configuré, ce qui se produit souvent lors de l'utilisation d'un Kubernetes Service comme backend.
Échec de l'établissement d'une connexion avec l'amont.
La requête ou la réponse amont est trop volumineuse, entraînant des échecs d'allocation de mémoire qui perturbent les interactions métier normales.
-
503 Service Unavailable: dans Nginx, ce code d'état indique que tous les serveurs amonts sont indisponibles. Dans les scénarios cloud-native, cela a des significations spécifiques. Les causes courantes incluent :Absence de backends disponibles, ce qui est rare.
Le trafic est trop important et est limité par la limite de débit Ingress.
504 Gateway Timeout: cette erreur indique un problème de délai d'expiration avec les paquets liés à l'activité métier entre Nginx et l'amont. La cause courante est une réponse retardée de l'amont.
Lorsque vous rencontrez ces problèmes, commencez par collecter des informations générales pour déterminer l'étendue du problème et les prochaines étapes de dépannage :
Les informations du journal d'accès Nginx, en particulier
request_time,upstream_connect_timeetupstream_response_time.Consultez les informations error_log de Nginx pour détecter tout message d'erreur anormal lorsque le problème survient.
Si une vérification d'intégrité liveness ou readiness est configurée, vérifiez son état.
Sur la base de ces informations, surveillez les variations des métriques suivantes lorsqu'une défaillance de connexion peut s'être produite :
|
Nom de la métrique |
Description |
|
kubeskoop_tcpext_listenoverflow |
Incrémenté lorsque la file d'attente de demi-connexions d'un socket à l'état LISTEN déborde. |
|
kubeskoop_tcpext_listendrops |
Incrémenté lorsqu'un socket à l'état LISTEN ne parvient pas à créer un socket à l'état SYN_RECV. |
|
kubeskoop_netdev_txdropped |
Nombre de fois où la carte réseau (NIC) perd des paquets en raison d'une erreur de transmission. |
|
kubeskoop_netdev_rxdropped |
Nombre de fois où la carte réseau perd des paquets en raison d'une erreur de réception. |
|
kubeskoop_tcp_activeopens |
Nombre de fois où un Pod initie avec succès une poignée de main TCP avec un paquet SYN. Cela n'inclut pas les retransmissions SYN, mais une connexion échouée augmente également cette métrique. |
|
kubeskoop_tcp_passiveopens |
Nombre cumulé de fois où un Pod termine une poignée de main TCP et alloue avec succès un socket. Cela peut généralement être compris comme le nombre de connexions établies avec succès. |
|
kubeskoop_tcp_retranssegs |
Nombre total de segments retransmis dans un seul Pod. La valeur est calculée après segmentation par TCP Segmentation Offload (TSO). |
|
kubeskoop_tcp_estabresets |
Nombre de fois où une connexion TCP est fermée de manière anormale dans un seul Pod. Cette métrique ne compte que le résultat. |
|
kubeskoop_tcp_outrsts |
Nombre de paquets de réinitialisation envoyés par TCP dans un seul Pod. |
|
kubeskoop_conntrack_invalid |
Nombre de fois où une entrée de suivi de connexion (conntrack) ne peut pas être établie pour diverses raisons, mais le paquet n'est pas perdu. |
|
kubeskoop_conntrack_drop |
Nombre de paquets perdus car une entrée conntrack n'a pas pu être établie. |
Si vous rencontrez une situation où les réponses Nginx sont lentes, par exemple lorsque des délais d'expiration se produisent alors que le request_time de Nginx est court, surveillez les variations des métriques suivantes :
|
Nom de la métrique |
Description |
|
kubeskoop_tcpsummary_tcpestablishedconn |
Nombre actuel de connexions TCP à l'état ESTABLISHED. |
|
kubeskoop_tcpsummary_tcptimewaitconn |
Nombre actuel de connexions TCP à l'état TIME_WAIT. |
|
kubeskoop_tcpsummary_tcptxqueue |
Total des octets de données dans la file d'attente d'envoi des connexions TCP actuellement à l'état ESTABLISHED. |
|
kubeskoop_tcpsummary_tcprxqueue |
Total des octets de données dans la file d'attente de réception des connexions TCP actuellement à l'état ESTABLISHED. |
|
kubeskoop_tcpext_tcpretransfail |
Incrémenté lorsqu'un paquet retransmis renvoie une erreur autre que EBUSY, indiquant que la retransmission a échoué. |
Les variations de ces métriques durant l'incident peuvent vous aider à restreindre le périmètre de votre investigation .
Problèmes de réinitialisation TCP
Un paquet de réinitialisation TCP est une réponse à des situations inattendues dans le protocole TCP. Il provoque généralement les erreurs suivantes dans les programmes utilisateur :
Erreur
connection reset by peer, couramment observée dans les applications qui dépendent des bibliothèques C, telles que Nginx.Erreur
Broken pipe, couramment observée dans les applications qui utilisent des wrappers de connexion TCP, telles que Java ou Python.
Dans un environnement réseau cloud-native, il existe de nombreuses raisons courantes aux paquets de réinitialisation. Voici quelques causes fréquentes :
Des anomalies côté serveur empêchent le bon fonctionnement du service, comme une mémoire insuffisante configurée pour TCP. Cette situation déclenche généralement une réinitialisation proactive.
Lors de l'utilisation d'un Service ou d'un équilibreur de charge, le trafic est transféré vers un backend inattendu en raison d'anomalies dans les mécanismes avec état, tels que la sélection de points de terminaison ou conntrack.
Libération de connexion pour des raisons de sécurité.
Dans les environnements NAT ou les scénarios à forte concurrence, une Protection Against Wrapped Sequence Numbers (PAWS) ou un bouclage de numéro de séquence se produit.
Utilisation de TCP Keepalive pour maintenir les connexions, mais sans communication métier normale pendant une longue période.
Pour différencier rapidement ces causes profondes, collectez certaines informations de base et métriques :
Analysez la topologie réseau entre le client et le serveur lorsque le paquet de réinitialisation est généré.
-
Surveillez les variations des métriques suivantes :
Nom de la métrique
Description
kubeskoop_tcpext_tcpabortontimeout
Incrémenté lorsqu'une réinitialisation est envoyée parce que le nombre maximal d'appels keepalive, de sondes de fenêtre ou de retransmissions est dépassé.
kubeskoop_tcpext_tcpabortonlinger
Nombre de réinitialisations envoyées pour récupérer rapidement les connexions à l'état FIN_WAIT2 lorsque l'option TCP Linger2 est activée.
kubeskoop_tcpext_tcpabortonclose
Incrémenté lorsqu'un paquet de réinitialisation est envoyé car il reste des données non lues lors de la fermeture d'une connexion TCP pour des raisons externes à la machine d'états.
kubeskoop_tcpext_tcpabortonmemory
Nombre de réinitialisations envoyées pour terminer une connexion en raison d'un manque de mémoire déclenché par
tcp_check_oomlors de l'allocation de ressources telles quetw_sockoutcp_sock.kubeskoop_tcpext_tcpabortondata
Nombre de réinitialisations envoyées pour une récupération rapide des connexions lorsque l'option Linger ou Linger2 est activée.
kubeskoop_tcpext_tcpackskippedsynrecv
Nombre de fois où un socket à l'état SYN_RECV ne répond pas par un ACK.
kubeskoop_tcpext_tcpackskippedpaws
Nombre de fois où un paquet ACK n'est pas envoyé en raison d'une limitation de débit Out-of-Window (OOW), même si une correction a été déclenchée par le mécanisme PAWS.
kubeskoop_tcp_estabresets
Nombre de fois où une connexion TCP est fermée de manière anormale dans un seul Pod. Cette métrique ne compte que le résultat.
kubeskoop_tcp_outrsts
Nombre de paquets de réinitialisation envoyés par TCP dans un seul Pod.
Gigue de latence réseau intermittente
La gigue de latence réseau intermittente est un problème courant et difficile à diagnostiquer dans les environnements cloud-native. Elle a de nombreuses causes et peut conduire aux trois types de problèmes mentionnés précédemment. Dans un scénario de réseau de conteneurs, la latence réseau au sein d'un nœud a généralement les causes suivantes :
Un processus temps réel géré par l'ordonnanceur RT s'exécute trop longtemps, ce qui entraîne une mise en file d'attente prolongée ou un traitement lent des processus métier ou des threads kernel réseau.
Le processus lui-même subit occasionnellement de longs appels externes, tels que des réponses lentes des disques cloud ou des augmentations intermittentes du temps aller-retour (RTT) RDS, ce qui ralentit le traitement des requêtes.
Des problèmes de configuration du nœud entraînent une charge inégale entre différents CPU ou nœuds NUMA, ce qui ralentit le système fortement chargé.
Latence causée par des mécanismes avec état dans le kernel, tels que l'opération de confirmation de conntrack, ou par de nombreux sockets orphelins affectant les recherches de sockets normales.
Bien que ces problèmes se manifestent comme des problèmes réseau, leur cause profonde est souvent liée à d'autres facteurs du système d'exploitation. Surveillez les métriques suivantes pour restreindre le périmètre de votre investigation :
|
Nom de la métrique |
Description |
|
kubeskoop_io_ioreadsyscall |
Nombre de fois où un processus effectue des opérations de lecture sur le système de fichiers, telles que |
|
kubeskoop_io_iowritesyscall |
Nombre de fois où un processus effectue des opérations d'écriture sur le système de fichiers, telles que |
|
kubeskoop_io_ioreadbytes |
Nombre d'octets lus par un processus depuis le système de fichiers, généralement depuis un périphérique bloc. |
|
kubeskoop_io_iowritebytes |
Nombre d'octets écrits par un processus sur le système de fichiers. |
|
kubeskoop_tcpext_tcptimeouts |
Déclenché lorsque l'état Congestion Avoidance (CA) n'est pas entré en récupération, perte ou désordre. Incrémenté lorsqu'un paquet SYN n'est pas accusé de réception et est retransmis. |
|
kubeskoop_tcpsummary_tcpestablishedconn |
Nombre actuel de connexions TCP à l'état ESTABLISHED. |
|
kubeskoop_tcpsummary_tcptimewaitconn |
Nombre actuel de connexions TCP à l'état TIME_WAIT. |
|
kubeskoop_tcpsummary_tcptxqueue |
Total des octets de données dans la file d'attente d'envoi des connexions TCP actuellement à l'état ESTABLISHED. |
|
kubeskoop_tcpsummary_tcprxqueue |
Total des octets de données dans la file d'attente de réception des connexions TCP actuellement à l'état ESTABLISHED. |
|
kubeskoop_softnet_processed |
Nombre de paquets de la backlog de la NIC traités par tous les CPU au sein d'un seul Pod. |
|
kubeskoop_softnet_dropped |
Nombre de paquets perdus par tous les CPU au sein d'un seul Pod. |
Études de cas
Les études de cas suivantes montrent comment ACK KubeSkoop a été utilisé pour résoudre des problèmes réseau complexes.
Cas 1 : Délai d'expiration DNS intermittent
Problème
Un client a rencontré des délais d'expiration intermittents lors de la résolution DNS. L'application du client s'exécutait sur PHP et le service DNS était configuré avec CoreDNS.
Processus de dépannage
Sur la base de la description du client, nous avons obtenu les données de surveillance liées au DNS.
-
L'analyse des données pendant la période d'erreur a révélé ce qui suit :
La métrique
kubeskoop_udp_noportsa augmenté de 1 pendant la période d'erreur. La valeur globale de la métrique était faible.La métrique
kubeskoop_packetloss_totala augmenté de 1. La variation de la perte de paquets était faible.
Le client a signalé que l'adresse DNS configurée était celle d'un fournisseur de services public. Ces informations, combinées aux données de surveillance, ont indiqué qu'une réponse DNS lente était la cause profonde. Le paquet de réponse DNS est arrivé après que l'application côté utilisateur avait déjà atteint son délai d'expiration.
Cas 2 : Échecs de connexion intermittents en Java
Problème
Un client a signalé que son instance Tomcat devenait intermittente indisponible, chaque panne durant de 5 à 10 secondes.
Processus de dépannage
L'analyse des journaux a confirmé que le Runtime Java du client effectuait une opération de Garbage Collection (GC) lorsque le problème est survenu.
Après le déploiement de la surveillance KubeSkoop, nous avons constaté une augmentation significative de la métrique
kubeskoop_tcpext_listendropsau moment du problème.Nous avons conclu que lorsque le Runtime Java du client effectuait un GC, la vitesse de traitement des requêtes ralentissait, retardant la libération des connexions. Cependant, les nouvelles demandes de connexion n'étaient pas limitées, ce qui créait un grand nombre de connexions. Cela a rempli la backlog du socket d'écoute et provoqué un débordement, entraînant l'augmentation de
kubeskoop_tcpext_listendrops.L'accumulation de connexions du client était de courte durée et la capacité de traitement n'était pas un problème. Nous avons recommandé au client d'ajuster les paramètres Tomcat pertinents, ce qui a résolu le problème.
Cas 3 : Gigue de latence réseau intermittente
Problème
Un client a découvert que les requêtes entre son application et Redis connaissaient des augmentations intermittentes du RTT, entraînant des délais d'expiration métier. Cependant, le problème ne pouvait pas être reproduit.
Processus de dépannage
L'analyse des journaux a montré que le client rencontrait des requêtes Redis intermittentes avec un temps de réponse total dépassant 300 ms.
Après le déploiement de KubeSkoop, les données de surveillance ont montré une augmentation de la métrique
kubeskoop_virtcmdlatency_latencylorsque le problème est survenu. Les valeursle(étiquette de bucket d'histogramme Prometheus) qui ont augmenté étaient 18 et 15. Cela indiquait que deux appels de virtualisation à haute latence s'étaient produits. Celui avecle=15a causé un retard de plus de 36 ms, et celui avecle=18a causé un retard de plus de 200 ms.Étant donné que les appels de virtualisation du kernel occupent le CPU et ne peuvent pas être préemptés, la latence intermittente a été causée par des appels de virtualisation de longue durée lors de la création et de la suppression groupées de Pods.
Cas 4 : Échecs des vérifications d'intégrité Ingress Nginx
Problème
La machine Ingress a connu des échecs intermittents des vérifications d'intégrité, accompagnés d'échecs de requêtes métier.
Processus de dépannage
-
Après le déploiement de la surveillance, nous avons constaté que plusieurs métriques présentaient des variations anormales au moment du problème :
Les métriques
kubeskoop_tcpsummary_tcprxqueueetkubeskoop_tcpsummary_tcptxqueueont toutes deux augmenté.La métrique
kubeskoop_tcpext_tcptimeoutsa augmenté.La métrique
kubeskoop_tcpsummary_tcptimewaitconna diminué, etkubeskoop_tcpsummary_tcpestablishedconna augmenté.
L'analyse a confirmé que le kernel fonctionnait normalement et que les connexions étaient correctement établies. Cependant, l'exécution du processus était anormale, y compris le traitement des paquets du socket de réception et l'envoi de paquets. Nous avons suspecté un problème de planification ou de limite de ressources avec le processus utilisateur.
Un examen de la surveillance Cgroup a révélé que le client subissait une limitation du CPU au moment du problème. Cela a prouvé que les limitations Cgroup empêchaient intermittemment la planification du processus utilisateur.
En suivant le guide Activation de la politique d'optimisation des performances CPU Burst, nous avons configuré la fonctionnalité CPU Burst pour Ingress, ce qui a résolu ce type de problème.