
La creación de redes es una habilidad esencial del administrador de sistemas, pero a menudo se pasa por alto. Muchos administradores de sistemas consideran que los temas de redes son desafiantes y es difícil progresar desde las habilidades básicas de redes hasta las habilidades avanzadas de resolución de problemas sin una práctica regular. Probablemente es por eso que las redes son un tema candente en Habilitar Sysadmin.
Kubernetes y sus extensiones relacionadas, como mallas de servicio, introducen complejidades de red adicionales que los administradores deben estar preparados para enfrentar.Herramientas básicas de networking como ping
y traceroute
, puede ser útil durante la fase inicial de solución de problemas. Sin embargo, siempre he descubierto que mirar los paquetes que pasan por el cable es la mejor manera de solucionar y comprender problemas complejos de protocolo y nivel de aplicación.
Este artículo presenta ksniff, una excelente herramienta de código abierto que he estado usando. Ksniff es un complemento para kubectl que le permite capturar paquetes en pods de Kubernetes. Le mostraré cómo capturar, filtrar y guardar paquetes para su posterior análisis. ¡Empecemos!
Descargo de responsabilidad: las técnicas descritas en este artículo solo deben usarse en un entorno de desarrollo con pleno conocimiento de lo que está haciendo. La documentación oficial de ksniff aún no lo recomienda para uso en producción, debe tener en cuenta que carga un binario tcpdump precompilado en un pod en ejecución.
Instalar ksniff y herramientas relacionadas
Ksniff es un complemento para kubectl que debe instalar antes de poder comenzar a usarlo. Las instrucciones oficiales de instalación de ksniff recomiendan usar el administrador de complementos Krew, que es mi método de instalación preferido. Puede encontrar instrucciones de instalación para Krew en el sitio web del proyecto. Después de instalar Krew, puede instalar ksniff con un solo comando:
$ kubectl krew install sniff
Updated the local copy of plugin index.
Installing plugin: sniff
Installed plugin: sniff
\
| Use this plugin:
| kubectl sniff
| Documentation:
| https://github.com/eldadru/ksniff
| Caveats:
| \
| | This plugin needs the following programs:
| | * wireshark (optional, used for live capture)
| /
/
WARNING: You installed plugin "sniff" from the krew-index plugin repository.
These plugins are not audited for security by the Krew maintainers.
Run them at your own risk.
Si desea rastrear y ver paquetes capturados en una interfaz gráfica de usuario (GUI) o terminal, también debe instalar Wireshark y tshark.
[ You might be wondering: Red Hat OpenShift and Kubernetes … what’s the difference? ]
Configurar la carga de trabajo para la prueba
La mejor manera de comenzar con ksniff es realizar la captura de paquetes en una carga de trabajo familiar, como un servidor web básico. Recomiendo un pod Nginx simple que puede ejecutar con un comando. Estos ejemplos implementan una carga de trabajo simple en una instalación de K0s de un solo nodo que se ejecuta en mi estación de trabajo:
$ kubectl run --image=nginx nginx
pod/nginx created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 4s
Una vez que el pod se está ejecutando, puede exponerlo como un servicio de NodePort. Si bien la mayoría de los administradores generalmente evitan usar los servicios de NodePort en entornos de producción, brindan una manera conveniente de probar los servicios rápidamente:
$ kubectl expose pod nginx --port 80 --type=NodePort
service/nginx exposed
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 2d5h
nginx NodePort 10.99.139.251 80:32209/TCP 2s
Finalmente, puede confirmar que el servicio está operativo con una simple acción curl
Al servicio NodePort:
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
acritelli-k8s Ready control-plane 3d5h v1.23.3+k0s 10.10.0.207 Ubuntu 20.04.4 LTS 5.14.0-1029-oem containerd://1.5.9
$ curl 10.10.0.207:32209
Welcome to nginx!
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.
Thank you for using nginx.
[ Free online course: Red Hat Enterprise Linux technical overview. ]
captura de paquetes
Con ksniff instalado y pods en ejecución, es hora de capturar algo de tráfico de red.corriendo kubectl sniff $POD_NAME
Comenzará una captura de paquetes, se iniciará Wireshark y la captura de paquetes se enviará directamente a Wireshark:
$ kubectl sniff nginx
INFO[0000] using tcpdump path at: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump'
INFO[0000] no container specified, taking first container we found in pod.
INFO[0000] selected container: 'nginx'
INFO[0000] sniffing method: upload static tcpdump
INFO[0000] sniffing on pod: 'nginx' [namespace: 'default', container: 'nginx', filter: '', interface: 'any']
INFO[0000] uploading static tcpdump binary from: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump' to: '/tmp/static-tcpdump'
INFO[0000] uploading file: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump' to '/tmp/static-tcpdump' on container: 'nginx'
INFO[0000] executing command: '[/bin/sh -c test -f /tmp/static-tcpdump]' on container: 'nginx', pod: 'nginx', namespace: 'default'
INFO[0000] command: '[/bin/sh -c test -f /tmp/static-tcpdump]' executing successfully exitCode: '0', stdErr :''
INFO[0000] file found: ''
INFO[0000] file was already found on remote pod
INFO[0000] tcpdump uploaded successfully
INFO[0000] spawning wireshark!
INFO[0000] start sniffing on remote container
INFO[0000] executing command: '[/tmp/static-tcpdump -i any -U -w - ]' on container: 'nginx', pod: 'nginx', namespace: 'default'
[ Get this free eBook: Managing your Kubernetes clusters for dummies. ]
Si prefiere quedarse completamente con la interfaz de línea de comandos (por ejemplo, si está en un servidor remoto), también puede enviar la salida de ksniff al programa de terminal tshark:
$ kubectl sniff nginx -o - | tshark -r -
INFO[0000] using tcpdump path at: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump'
INFO[0000] no container specified, taking first container we found in pod.
INFO[0000] selected container: 'nginx'
INFO[0000] sniffing method: upload static tcpdump
INFO[0000] sniffing on pod: 'nginx' [namespace: 'default', container: 'nginx', filter: '', interface: 'any']
INFO[0000] uploading static tcpdump binary from: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump' to: '/tmp/static-tcpdump'
INFO[0000] uploading file: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump' to '/tmp/static-tcpdump' on container: 'nginx'
INFO[0000] executing command: '[/bin/sh -c test -f /tmp/static-tcpdump]' on container: 'nginx', pod: 'nginx', namespace: 'default'
INFO[0000] command: '[/bin/sh -c test -f /tmp/static-tcpdump]' executing successfully exitCode: '0', stdErr :''
INFO[0000] file found: ''
INFO[0000] file was already found on remote pod
INFO[0000] tcpdump uploaded successfully
INFO[0000] output file option specified, storing output in: '-'
INFO[0000] start sniffing on remote container
INFO[0000] executing command: '[/tmp/static-tcpdump -i any -U -w - ]' on container: 'nginx', pod: 'nginx', namespace: 'default'
1 0.000000 10.244.0.1 → 10.244.0.18 TCP 76 29681 → 80 [SYN] Seq=0 Win=65495 Len=0 MSS=65495 SACK_PERM=1 TSval=420487628 TSecr=0 WS=128
2 0.000023 10.244.0.18 → 10.244.0.1 TCP 76 80 → 29681 [SYN, ACK] Seq=0 Ack=1 Win=64260 Len=0 MSS=1440 SACK_PERM=1 TSval=3356168433 TSecr=420487628 WS=128
3 0.000040 10.244.0.1 → 10.244.0.18 TCP 68 29681 → 80 [ACK] Seq=1 Ack=1 Win=65536 Len=0 TSval=420487628 TSecr=3356168433
4 0.000069 10.244.0.1 → 10.244.0.18 HTTP 149 GET / HTTP/1.1
5 0.000072 10.244.0.18 → 10.244.0.1 TCP 68 80 → 29681 [ACK] Seq=1 Ack=82 Win=64256 Len=0 TSval=3356168433 TSecr=420487628
6 0.000160 10.244.0.18 → 10.244.0.1 TCP 306 HTTP/1.1 200 OK [TCP segment of a reassembled PDU]
7 0.000178 10.244.0.1 → 10.244.0.18 TCP 68 29681 → 80 [ACK] Seq=82 Ack=239 Win=65408 Len=0 TSval=420487628 TSecr=3356168433
8 0.000192 10.244.0.18 → 10.244.0.1 HTTP 683 HTTP/1.1 200 OK (text/html)
9 0.000198 10.244.0.1 → 10.244.0.18 TCP 68 29681 → 80 [ACK] Seq=82 Ack=854 Win=64896 Len=0 TSval=420487628 TSecr=3356168433
10 0.000296 10.244.0.1 → 10.244.0.18 TCP 68 29681 → 80 [FIN, ACK] Seq=82 Ack=854 Win=65536 Len=0 TSval=420487628 TSecr=3356168433
11 0.000326 10.244.0.18 → 10.244.0.1 TCP 68 80 → 29681 [FIN, ACK] Seq=854 Ack=83 Win=64256 Len=0 TSval=3356168433 TSecr=420487628
12 0.000354 10.244.0.1 → 10.244.0.18 TCP 68 29681 → 80 [ACK] Seq=83 Ack=855 Win=65536 Len=0 TSval=420487628 TSecr=3356168433
^C⏎
El análisis en tiempo real es útil, pero también es común guardar las capturas de paquetes para un análisis posterior. Esto es especialmente útil si está capturando paquetes en una máquina que no tiene acceso a Wireshark o tshark, como un host de salto. Puede escribir paquetes en un archivo especificando la salida de ksniff. Puede abrir el archivo guardado en un analizador de protocolos como Wireshark:
$ k sniff nginx -o /tmp/nginx_capture.pcap
INFO[0000] using tcpdump path at: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump'
INFO[0000] no container specified, taking first container we found in pod.
INFO[0000] selected container: 'nginx'
INFO[0000] sniffing method: upload static tcpdump
INFO[0000] sniffing on pod: 'nginx' [namespace: 'default', container: 'nginx', filter: '', interface: 'any']
INFO[0000] uploading static tcpdump binary from: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump' to: '/tmp/static-tcpdump'
INFO[0000] uploading file: '/home/acritelli/.krew/store/sniff/v1.6.2/static-tcpdump' to '/tmp/static-tcpdump' on container: 'nginx'
INFO[0000] executing command: '[/bin/sh -c test -f /tmp/static-tcpdump]' on container: 'nginx', pod: 'nginx', namespace: 'default'
INFO[0000] command: '[/bin/sh -c test -f /tmp/static-tcpdump]' executing successfully exitCode: '0', stdErr :''
INFO[0000] file found: ''
INFO[0000] file was already found on remote pod
INFO[0000] tcpdump uploaded successfully
INFO[0000] output file option specified, storing output in: '/tmp/nginx_capture.pcap'
INFO[0000] start sniffing on remote container
INFO[0000] executing command: '[/tmp/static-tcpdump -i any -U -w - ]' on container: 'nginx', pod: 'nginx', namespace: 'default'
^C⏎
$ file /tmp/nginx_capture.pcap
/tmp/nginx_capture.pcap: pcap capture file, microsecond ts (little-endian) - version 2.4 (Linux cooked v1, capture length 262144)
Las capturas de paquetes pueden volverse muy complicadas, especialmente para los pods que ejecutan cargas de trabajo complejas o de alta utilización. La capacidad de aplicar filtros tcpdump es fundamental para simplificar las capturas de paquetes complejos, y ksniff admite esto desde el primer momento:
$ kubectl sniff nginx -f "tcp port 80"
envolver
Este artículo le muestra cómo usar ksniff para capturar paquetes en un pod de Kubernetes en ejecución. Las capturas de paquetes brindan una forma poderosa de observar y solucionar problemas complejos de redes y aplicaciones, y su aplicabilidad se vuelve más importante a medida que los entornos se vuelven más complejos.
Realizar una captura de paquetes también es una excelente manera de mejorar sus habilidades de red y profundizar su comprensión de entornos complejos, por lo que le recomiendo que aproveche una herramienta como ksniff en cada oportunidad disponible. ¡Buena suerte y feliz networking!