En esta página se explica cómo solucionar problemas de conectividad en un clúster de Google Kubernetes Engine (GKE).
Problemas de conectividad relacionados con la captura de paquetes de red en GKE
En esta sección se describe cómo solucionar problemas de conectividad relacionados con la captura de paquetes de red, incluidos síntomas como tiempos de espera de conexión, errores de conexión rechazada o un comportamiento inesperado de la aplicación. Estos problemas de conectividad pueden producirse a nivel de nodo o de pod.
Los problemas de conectividad de la red de tu clúster suelen clasificarse en las siguientes categorías:
- No se puede acceder a los pods: es posible que no se pueda acceder a un pod desde dentro o fuera del clúster debido a errores de configuración de la red.
- Interrupciones del servicio: es posible que un Servicio esté experimentando interrupciones o retrasos.
- Problemas de comunicación entre pods: es posible que los pods no puedan comunicarse entre sí de forma eficaz.
Los problemas de conectividad de tu clúster de GKE pueden deberse a varios motivos, entre los que se incluyen los siguientes:
- Configuraciones de red incorrectas: políticas de red, reglas de cortafuegos o tablas de enrutamiento incorrectas.
- Errores de la aplicación: errores en el código de la aplicación que afectan a las interacciones de red.
- Problemas de infraestructura: congestión de la red, fallos de hardware o limitaciones de recursos.
En la siguiente sección se muestra cómo resolver el problema en los nodos o pods que lo tengan.
Identifica el nodo en el que se está ejecutando el pod problemático con el siguiente comando:
kubectl get pods POD_NAME -o=wide -n NAMESPACE
Haz los cambios siguientes:
POD_NAME
con el nombre del pod.NAMESPACE
con el espacio de nombres de Kubernetes.
Conéctate al nodo:
gcloud compute ssh NODE_NAME \ --zone=ZONE
Haz los cambios siguientes:
NODE_NAME
: nombre del nodo.ZONE
: nombre de la zona en la que se ejecuta el nodo.
Para depurar un pod específico, identifica la interfaz
veth
asociada al pod:ip route | grep POD_IP
Sustituye
POD_IP
por la dirección IP del pod.Ejecuta los comandos de la caja de herramientas.
Comandos de toolbox
toolbox
es una utilidad que proporciona un entorno en contenedores en tus nodos de GKE para depurar y solucionar problemas. En esta sección se describe cómo instalar la utilidad toolbox
y usarla para solucionar problemas del nodo.
Mientras estés conectado al nodo, inicia la herramienta
toolbox
:toolbox
Se descargarán los archivos que facilitan la utilidad
toolbox
.En la petición de raíz
toolbox
, instalatcpdump
:En el caso de los clústeres con direcciones IP externas o Cloud NAT:
apt update -y && apt install -y tcpdump
En el caso de los clústeres privados sin Cloud NAT:
Si tienes un clúster privado sin Cloud NAT, no puedes instalar
tcpdump
conapt
. En su lugar, descarga los archivos de lanzamientolibpcap
ytcpdump
del repositorio oficial y copia los archivos en la VM mediantegcloud compute scp
ogcloud storage cp
. A continuación, instala las bibliotecas manualmente siguiendo estos pasos:# Copy the downloaded packages to a staging area cp /media/root/home/USER_NAME/tcpdump-VERSION.tar.gz /usr/sbin/ cp /media/root/home/USER_NAME/libpcap-VERSION.tar.gz /usr/sbin/ cd /usr/sbin/ # Extract the archives tar -xvzf tcpdump-VERSION.tar.gz tar -xvzf libpcap-VERSION.tar.gz # Build and install libpcap (a dependency for tcpdump) cd libpcap-VERSION ./configure ; make ; make install # Build and install tcpdump cd ../tcpdump-VERSION ./configure ; make ; make install # Verify tcpdump installation tcpdump --version
Haz los cambios siguientes:
USER_NAME
: tu nombre de usuario en el sistema en el que se encuentran los archivos.VERSION
: el número de versión específico de los paquetestcpdump
ylibpcap
.
Inicia la captura de paquetes:
tcpdump -i eth0 -s 100 "port PORT" \ -w /media/root/mnt/stateful_partition/CAPTURE_FILE_NAME
Haz los cambios siguientes:
PORT
: nombre del número de puerto.CAPTURE_FILE_NAME
: nombre del archivo de captura.
Detén la captura de paquetes e interrumpe
tcpdump
.Para salir de la caja de herramientas, escribe
exit
.Lista el archivo de captura de paquetes y comprueba su tamaño:
ls -ltr /mnt/stateful_partition/CAPTURE_FILE_NAME
Copia la captura de paquetes del nodo en el directorio de trabajo actual de tu ordenador:
gcloud compute scp NODE_NAME:/mnt/stateful_partition/CAPTURE_FILE_NAME \ --zone=ZONE
Haz los cambios siguientes:
NODE_NAME
: nombre del nodo.CAPTURE_FILE_NAME
: nombre del archivo de captura.ZONE
: nombre de la zona.
Comandos alternativos
También puedes usar los siguientes métodos para solucionar problemas de conectividad en los pods que dan problemas:
Carga de trabajo de depuración efímera conectada al contenedor del pod.
Ejecuta un shell directamente en el pod de destino con
kubectl exec
y, a continuación, instala y ejecuta el comandotcpdump
.
Problemas de conectividad de la red de pods
Como se ha mencionado en la sección Descripción general de la red, es importante saber cómo se conectan los pods desde sus espacios de nombres de red hasta el espacio de nombres raíz del nodo para solucionar problemas de forma eficaz. En la siguiente conversación, a menos que se indique lo contrario, se presupone que el clúster usa el CNI nativo de GKE en lugar del de Calico. Es decir, no se ha aplicado ninguna política de red.
Los pods de los nodos seleccionados no tienen disponibilidad
Si los pods de determinados nodos no tienen conectividad de red, asegúrate de que el puente Linux esté activo:
ip address show cbr0
Si el puente de Linux está inactivo, actívalo:
sudo ip link set cbr0 up
Comprueba que el nodo esté aprendiendo las direcciones MAC de los pods conectados a cbr0:
arp -an
Los pods de los nodos seleccionados tienen una conectividad mínima
Si los pods de determinados nodos tienen una conectividad mínima, primero debes confirmar si se han perdido paquetes ejecutando tcpdump
en el contenedor de la caja de herramientas:
sudo toolbox bash
Instala tcpdump
en la caja de herramientas si aún no lo has hecho:
apt install -y tcpdump
Ejecuta tcpdump
en cbr0:
tcpdump -ni cbr0 host HOSTNAME and port PORT_NUMBER and [TCP|UDP|ICMP]
Si parece que se están descartando paquetes grandes en sentido descendente desde el puente (por ejemplo, se completa el handshake de TCP, pero no se reciben mensajes de saludo SSL), asegúrate de que el MTU de cada interfaz de pod de Linux esté configurado correctamente con el MTU de la red de VPC del clúster.
ip address show cbr0
Cuando se usan superposiciones (por ejemplo, Weave o Flannel), este MTU debe reducirse aún más para adaptarse a la sobrecarga de encapsulación de la superposición.
MTU de GKE
El valor de MTU seleccionado para una interfaz de Pod depende de la interfaz de red de contenedores (CNI) que usen los nodos del clúster y del valor de MTU de la VPC subyacente. Para obtener más información, consulta Pods.
El valor de MTU de la interfaz de Pod es 1460
o se hereda de la interfaz principal del nodo.
CNI | MTU | GKE Standard |
---|---|---|
kubenet | 1460 | Predeterminado |
kubenet (versión 1.26.1 de GKE y posteriores) |
Heredada | Predeterminado |
Calico | 1460 |
Se habilita mediante Para obtener más información, consulta el artículo Controlar la comunicación entre pods y servicios mediante políticas de red. |
netd | Heredada | Se habilita de una de las siguientes formas: |
GKE Dataplane V2 | Heredada |
Se habilita mediante Para obtener más información, consulta Usar GKE Dataplane V2. |
Errores de conexión intermitentes
iptables reenvía las conexiones a los pods y desde ellos. Los flujos se monitorizan como entradas en la tabla conntrack y, cuando hay muchas cargas de trabajo por nodo, el agotamiento de la tabla conntrack puede manifestarse como un fallo. Estos datos se pueden registrar en la consola serie del nodo. Por ejemplo:
nf_conntrack: table full, dropping packet
Si puedes determinar que los problemas intermitentes se deben al agotamiento de conntrack, puedes aumentar el tamaño del clúster (lo que reduce el número de cargas de trabajo y flujos por nodo) o aumentar nf_conntrack_max
:
new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
&& echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf
También puedes usar NodeLocal DNSCache para reducir las entradas de seguimiento de conexiones.
Se ha informado de "bind: Address already in use " en un contenedor
No se puede iniciar un contenedor en un pod porque, según los registros del contenedor, el puerto al que intenta enlazarse la aplicación ya está reservado. El contenedor está en un bucle de fallos. Por ejemplo, en Cloud Logging:
resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"
2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use
Cuando Docker falla, a veces se queda un contenedor en ejecución y se vuelve obsoleto. El proceso sigue ejecutándose en el espacio de nombres de red asignado al pod y escuchando en su puerto. Como Docker y kubelet no saben que el contenedor está obsoleto, intentan iniciar un contenedor nuevo con un proceso nuevo, que no puede enlazarse al puerto porque se añade al espacio de nombres de red que ya está asociado al pod.
Para diagnosticar este problema, sigue estos pasos:
Necesitará el UUID del pod en el campo
.metadata.uuid
:kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg name UUID ubuntu-6948dd5657-4gsgg db9ed086-edba-11e8-bdd6-42010a800164
Obtén la salida de los siguientes comandos del nodo:
docker ps -a ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
Comprueba los procesos en ejecución de este pod. Como los UUID de los espacios de nombres de cgroup contienen el UUID del pod, puedes buscar el UUID del pod en la salida de
ps
. También puedes buscar la línea anterior para ver los procesosdocker-containerd-shim
que tienen el ID del contenedor en el argumento. Corta el resto de la columna cgroup para obtener un resultado más sencillo:# ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/ 1283089 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 276e173b0846e24b704d4 12: 1283107 1283089 Ss sys_pause 4026532393 pause /pause 12: 1283150 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim ab4c7762f5abf40951770 12: 1283169 1283150 Ss do_wait 4026532393 sh /bin/sh -c echo hello && sleep 6000000 12: 1283185 1283169 S hrtimer_nanosleep 4026532393 sleep sleep 6000000 12: 1283244 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 44e76e50e5ef4156fd5d3 12: 1283263 1283244 Ss sigsuspend 4026532393 nginx nginx: master process nginx -g daemon off; 12: 1283282 1283263 S ep_poll 4026532393 nginx nginx: worker process
En esta lista, puedes ver los IDs de contenedor, que también deberían aparecer en
docker ps
.En ese caso, ocurrirá lo siguiente:
docker-containerd-shim 276e173b0846e24b704d4
para pausardocker-containerd-shim ab4c7762f5abf40951770
para sh con sueño (sleep-ctr)docker-containerd-shim 44e76e50e5ef4156fd5d3
para nginx (echoserver-ctr)
Comprueba los elementos de la salida
docker ps
:# docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3' 44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc "nginx -g 'daemon off;'" 14 hours ago Up 14 hours k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475 ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78 "/bin/sh -c 'echo hello && sleep 6000000'" 14 hours ago Up 14 hours k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327 registry.k8s.io/pause-amd64:3.1
En circunstancias normales, todos los IDs de contenedor de
ps
se muestran endocker ps
. Si no ves alguno, significa que el contenedor está obsoleto y es probable que veas un proceso secundario dedocker-containerd-shim process
escuchando en el puerto TCP que indica que ya está en uso.Para verificarlo, ejecuta
netstat
en el espacio de nombres de red del contenedor. Obtén el PID de cualquier proceso de contenedor (NOdocker-containerd-shim
) del pod.En el ejemplo anterior:
- 1283107 - pause
- 1283169 - sh
- 1283185 - sueño
- 1283263 - nginx master
- 1283282 - nginx worker
# nsenter -t 1283107 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast
También puedes ejecutar
netstat
conip netns
, pero debes vincular manualmente el espacio de nombres de red del proceso, ya que Docker no lo hace:# ln -s /proc/1283169/ns/net /var/run/netns/1283169 gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list 1283169 (id: 2) gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
Solución:
La medida de mitigación a corto plazo consiste en identificar los procesos obsoletos mediante el método descrito anteriormente y finalizar los procesos con el comando kill [PID]
.
La mitigación a largo plazo implica identificar por qué falla Docker y solucionarlo. Se puede deber a los siguientes motivos:
- Se acumulan procesos zombi, por lo que se agotan los espacios de nombres de PID
- Error en Docker
- Presión de recursos/OOM
Siguientes pasos
Para obtener información general sobre cómo diagnosticar problemas de DNS de Kubernetes, consulta Depuración de la resolución de DNS.
Si no encuentras una solución a tu problema en la documentación, consulta la sección Obtener asistencia para obtener más ayuda, incluidos consejos sobre los siguientes temas:
- Abrir un caso de asistencia poniéndose en contacto con el equipo de Atención al Cliente de Cloud.
- Obtener asistencia de la comunidad haciendo preguntas en Stack Overflow
y usando la etiqueta
google-kubernetes-engine
para buscar problemas similares. También puedes unirte al#kubernetes-engine
canal de Slack para obtener más ayuda de la comunidad. - Abrir errores o solicitudes de funciones mediante el seguimiento de problemas público.