Soluciona problemas de observabilidad de la red de GKE

En este documento, se proporcionan instrucciones y procedimientos de diagnóstico para identificar problemas de redes en clústeres de Google Kubernetes Engine (GKE) con la observabilidad de GKE Dataplane V2, Hubble y Cloud Monitoring.

Para obtener una descripción general de la arquitectura y las prácticas recomendadas conceptuales, consulta Prácticas recomendadas para la observabilidad de la red.

Árbol de decisión para la solución de problemas y conceptos básicos

Antes de revisar los procedimientos, usa la siguiente matriz de decisiones para identificar qué nivel de la pila de redes de GKE probablemente esté causando el problema y navega a la sección correspondiente.

Síntoma o pregunta de diagnóstico Nivel sospechado Procedimiento recomendado
Los Pods no pueden resolver dominios externos ni servicios internos de Kubernetes (tiempos de espera de DNS, NXDOMAIN, SERVFAIL). Nivel 1: Pod y servicio (DNS) Diagnostica fallas en la resolución de DNS
Los servicios no se pueden comunicar; se agota el tiempo de espera de la conexión o se descartan paquetes entre los Pods. Nivel 1: Pod y Service (pérdida de paquetes o políticas) Diagnostica las pérdidas de paquetes y los bloqueos de NetworkPolicy
Las réplicas de la carga de trabajo tienen una carga de tráfico desigual, o bien los Pods registran tasas altas de restablecimientos de TCP (RST). Nivel 1: Pod y servicio (balanceo de cargas o transporte) Diagnostica el desequilibrio del tráfico y los restablecimientos de TCP
Latencia general, tiempos de espera intermitentes o reinicios de CNI en los nodos Nivel 2: Nodo y CNI (kernel) Triaje para la latencia a nivel del nodo y los cuellos de botella de la CNI
Los Pods no pueden acceder a recursos fuera de GKE (Cloud SQL, APIs externas o otras VPC). Nivel 3: VPC y enrutamiento Aísla los problemas de conectividad de GKE en comparación con los de VPC o externos
Necesitas una simulación de ruta automatizada para verificar si las reglas de firewall, las rutas o las políticas de red bloquean el tráfico. Nivel 3: VPC y enrutamiento (simulación) Diagnostica la conectividad con las pruebas de conectividad
Necesitas identificar qué cargas de trabajo envían tráfico a Internet y se someten a NAT. Nivel 4: Puerta de enlace y costo externos Identifica el tráfico de NAT (salida a Internet)
Altos costos de transferencia de datos entre zonas o necesidad de visualizar los principales comunicadores sin escribir consultas en SQL Nivel 4: Puerta de enlace y costo externos Analiza el rendimiento y los costos del tráfico del clúster con Flow Analyzer

Conceptos básicos de redes

Si no tienes experiencia en Kubernetes o Google Cloud redes, ten en cuenta estos conceptos básicos:

  • eBPF (Extended Berkeley Packet Filter): Es una tecnología de sistema operativo que permite ejecutar programas seguros de supervisión y enrutamiento directamente dentro del kernel de Linux. GKE Dataplane V2 usa eBPF para enrutar paquetes y aplicar NetworkPolicies con una sobrecarga de rendimiento mínima.
  • Enmascaramiento de IP (SNAT): Es el proceso de reescritura de la dirección IP de origen de un paquete. Cuando un Pod de GKE (que tiene una dirección IP privada) se comunica con Internet o con recursos de VPC externos, GKE enmascara (reescribe) la dirección IP del Pod a la dirección IP del nodo para que los sistemas externos sepan cómo enrutar la respuesta.
  • Seguimiento de conexión (Conntrack): Es una función del kernel que realiza un seguimiento de todas las conexiones de red activas. En los clústeres de GKE Dataplane V2, este seguimiento se divide entre dos tablas: la tabla conntrack estándar del kernel de Linux (que usa ip-masq-agent) y una tabla conntrack administrada por Cilium y GKE Dataplane V2 que se almacena en un mapa de eBPF. Si un nodo controla demasiadas conexiones simultáneas, cualquiera de estas tablas de seguimiento puede llenarse (agotamiento de conntrack), lo que provoca que el nodo descarte silenciosamente los paquetes nuevos.
  • Hubble: Es el motor de observabilidad de GKE Dataplane V2. Se ejecuta sobre eBPF y proporciona visibilidad en tiempo real de los flujos de tráfico, las pérdidas de paquetes y la evaluación de NetworkPolicy.

Nivel 1: Observabilidad del Pod y el servicio (aplicación)

El nivel de Pod y Service abarca la comunicación de red entre Pods, Services y DNS del clúster. Los problemas en este nivel suelen manifestarse como tiempos de espera agotados de conexión de la aplicación, fallas en la resolución de nombres o distribución desigual de la carga.

Diagnostica las fallas en la resolución de DNS

Antes de solucionar problemas de DNS, revisa el alcance del diagnóstico y los requisitos previos:

  • Área de enfoque: Comunicación entre Pods y CoreDNS o NodeLocal DNSCache, latencia de DNS, tiempos de espera de resolución de DNS ascendente y validación de NetworkPolicy de FQDN.
  • Requisitos previos: Métricas de GKE Dataplane V2 habilitadas; acceso a kubectl
  • Compatibilidad con CNI: GKE Dataplane V2 (ruta de datos avanzada) y CNI de GKE estándar.
  • Síntoma: Los Pods registran dial tcp: lookup <domain>: i/o timeout, NXDOMAIN o latencia intermitente en las llamadas a la API salientes.
  • Objetivo: Determinar si la falla de DNS se origina dentro del clúster (saturación de kube-dns o NodeLocal DNSCache), si una NetworkPolicy bloquea el puerto UDP o TCP 53, o si hay una degradación de la red upstream.

Paso 1: Verificación básica de accesibilidad

Antes de solucionar problemas relacionados con las capas de DNS, verifica si se puede acceder al destino directamente usando su dirección IP desde el Pod afectado:

# 1. Test raw IP reachability (bypasses DNS entirely)
kubectl exec -it my-pod -n default -- curl -v --connect-timeout 5 http://10.240.0.10:8080

# 2. Test domain resolution
kubectl exec -it my-pod -n default -- curl -v --connect-timeout 5 http://my-service.default.svc.cluster.local:8080
Verifica la precarga de DNS de FQDN NetworkPolicy

Si tu clúster usa NetworkPolicies basadas en FQDN (FQDNNetworkPolicy), verifica que el nombre de dominio esté permitido de forma explícita. Si un Pod consulta un dominio externo que no se propagó previamente en la caché del proxy de DNS de GKE Dataplane V2 o que no está permitido por la política, GKE Dataplane V2 bloquea el tráfico de salida a la dirección IP resuelta:

# Verify whether UDP or TCP port 53 egress is permitted in the Pod's namespace
kubectl get networkpolicy -n default -o yaml | grep -A 5 -B 2 "port: 53"

Paso 2: Verifica las métricas de DNS en Cloud Monitoring

GKE expone métricas de DNS integradas en Cloud Monitoring con el prefijo kubernetes.io/networking/dns/.

Para verificar las métricas de DNS en Cloud Monitoring, haz lo siguiente:

  1. En la consola de Google Cloud , navega a Cloud Monitoring > Paneles.
  2. Selecciona el panel predefinido GKE DNS Observability - Cluster View (o navega al Explorador de métricas y filtra por kubernetes.io/networking/dns/).
  3. Evalúa los siguientes indicadores principales (para NodeLocal DNSCache, reemplaza kubedns por node_local_dns en la ruta de la métrica):
Nombre de la métrica Umbral de advertencia Causa principal
kubernetes.io/networking/dns/kubedns/max_concurrent_rejected_request_count >0 Se alcanzó el límite de consultas simultáneas. kube-dns o NodeLocal DNSCache descartan consultas.
kubernetes.io/networking/dns/kubedns/dns_request_latencies p99 > 100 ms Alta latencia de resolución de DNS de extremo a extremo en kube-dns o NodeLocal DNSCache
kubernetes.io/networking/dns/kubedns/forwarding_request_latencies p99 > 100 ms Latencia o saturación del servidor DNS upstream
Secuencia de clasificación de rendimiento y tiempo de espera de DNS

Sigue esta secuencia de clasificación para diagnosticar la latencia de DNS, las fallas de caché y los tiempos de espera ascendentes:

  1. Verifica la tasa de aciertos de caché: Consulta kubernetes.io/networking/dns/kubedns/dns_cache_request_count (o node_local_dns/dns_cache_request_count) agrupada por la etiqueta cache_status. Si cache_status="hit" es bajo y cache_status="miss" es alto, es posible que las aplicaciones emitan consultas que no son FQDN (como my-service en lugar de my-service.default.svc.cluster.local), lo que provoca el salto de directorio en todas las entradas de /etc/resolv.conf.
  2. Evalúa la latencia upstream: Una latencia alta de forwarding_request_latencies indica problemas con el servidor DNS upstream (por ejemplo, el DNS local corporativo al que se accede a través de Cloud Interconnect o Cloud VPN, o bien límites de Cloud DNS).
  3. Audita las anulaciones de DNS personalizadas: Inspecciona los ConfigMaps kube-dns personalizados en busca de stubs mal configurados o reenvíos ascendentes:

    kubectl get configmap kube-dns -n kube-system -o yaml
    

Paso 3: Transmite tráfico de DNS en vivo con la CLI de Hubble

Usa el alias de ayuda de la CLI de Hubble para inspeccionar las solicitudes y respuestas de DNS en vivo transmitidas desde el kernel del nodo:

# 1. Ensure the helper alias is set in your terminal session
alias gke-hubble="kubectl exec -it -n gke-managed-dpv2-observability deployment/hubble-relay -c hubble-cli -- hubble"

# 2. Observe live DNS (Port 53) traffic for a specific Pod
gke-hubble observe --pod default/my-pod --port 53

Paso 4: Valida la corrección

Si se produjeron rechazos de consultas simultáneas, aplica NodeLocal DNSCache para absorber las búsquedas de DNS de alta frecuencia directamente en el nodo sin alcanzar los límites de kube-dns en todo el clúster:

# Verify NodeLocal DNSCache DaemonSet is running
kubectl get daemonset node-local-dns -n kube-system

Diagnostica las pérdidas de paquetes y los bloqueos de NetworkPolicy

Revisa el alcance del diagnóstico y los requisitos previos antes de investigar las pérdidas de paquetes y los rechazos de políticas:

  • Área de enfoque: Pérdidas de tráfico entre objetos Pod o entre objetos Pod y Service, aplicación de NetworkPolicy, motivos de pérdida de eBPF del kernel.
  • Requisitos previos: Observabilidad de flujo de GKE Dataplane V2 habilitada y registro de NetworkPolicy configurado.
  • Compatibilidad con CNI: Solo GKE Dataplane V2.
  • Síntoma: Los intentos de conexión de la aplicación fallan con Connection timed out o Connection reset by peer.
  • Objetivo: Identificar el motivo exacto por el que NetworkPolicy o eBPF descartan paquetes sin realizar cambios de prueba y error en las políticas de seguridad.

Paso 1: Supervisa las métricas de abandono de Hubble

Cuando GKE Dataplane V2 descarta un paquete, emite la métrica hubble_drop_total etiquetada con el motivo del descarte y los metadatos de origen y destino. Para supervisar las métricas de caída de Hubble, haz lo siguiente:

  1. Si aún no lo configuraste, implementa un recurso PodMonitoring de Google Cloud Managed Service para Prometheus para recopilar métricas de Hubble:

    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: hubble-metrics
      namespace: gke-managed-dpv2-observability
    spec:
      selector:
        matchLabels:
          k8s-app: cilium
      endpoints:
      - port: hubble-metrics
        interval: 30s
    
  2. Ejecuta la siguiente consulta en Cloud Monitoring > Explorador de métricas para ver las bajas por motivo:

    sum by (reason) (rate(hubble_drop_total[5m])) > 0
    
  3. Interpreta los códigos reason comunes:

    • Policy denied: Una NetworkPolicy de Kubernetes bloquea la conexión de forma explícita o implícita.
    • CT: Map insertion failed: Se agotó la tabla de seguimiento de conexiones (conntrack).
    • Unsupported L3 protocol: Paquete que no es IPv4 o IPv6, o encabezado dañado.

Paso 2: Revisa los registros de NetworkPolicy en Cloud Logging

El registro de NetworkPolicy exporta registros JSON estructurados para todas las decisiones de políticas. Para consultar los registros de NetworkPolicy en Cloud Logging, haz lo siguiente:

  1. En la consola de Google Cloud , navega a Cloud Logging > Explorador de registros.
  2. Ejecute la siguiente consulta:

    resource.type="k8s_node"
    log_name:"projects/PROJECT_ID/logs/events"
    jsonPayload.connection.verdict="DENY"
    jsonPayload.src.pod_name="my-source-pod"
    
  3. Inspecciona la carga útil de JSON:

    • jsonPayload.drop_reason: Muestra por qué se descartó el paquete.
    • jsonPayload.policies: Enumera las NetworkPolicies que se evaluaron. Si se devuelve una lista vacía con un veredicto DENY, el espacio de nombres está funcionando en modo de denegación predeterminado y ninguna política permitió el tráfico.

Si no aparecen registros de NetworkPolicy, verifica que el registro esté habilitado en el recurso personalizado NetworkLogging del clúster. Por ejemplo, verifica que el campo spec.cluster.deny.log esté establecido en true:

kubectl get networklogging default -o yaml

Paso 3: Haz un seguimiento de las entregas en vivo con la CLI de Hubble

Transmite lanzamientos en vivo directamente con la CLI de Hubble para inspeccionar paquetes en tiempo real:

gke-hubble observe --verdict DROPPED --namespace default --follow

Resultado de ejemplo:

TIMESTAMP             SOURCE               DESTINATION          TYPE     VERDICT
10:14:22.102          default/frontend     default/backend:80   to-stack DROPPED (Policy denied by NetworkPolicy: backend-deny-all)

El resultado indica la NetworkPolicy exacta que bloquea el tráfico (backend-deny-all).

Paso 4: Comprueba si hay agotamiento de conntrack

Si el motivo de la baja indica CT: Map insertion failed, haz lo siguiente:

  1. Inspecciona el registro del agente de GKE Dataplane V2 para detectar la saturación de la tabla de conntrack:

    kubectl logs -n kube-system daemonset/anetd -c cilium-agent --tail=100 | grep "Conntrack table full"
    
  2. Verifica el tamaño máximo de la tabla de conntrack en el nodo afectado:

    kubectl exec -it -n kube-system daemonset/anetd -c cilium-agent -- cilium status --all-controllers | grep -i conntrack
    

    Si la tabla de conntrack está llena, escala horizontalmente tus cargas de trabajo en más nodos o reduce la tasa de conexión de los Pods cliente.


Diagnostica el desequilibrio del tráfico y los restablecimientos de TCP

Revisa el alcance del diagnóstico y los requisitos previos antes de solucionar problemas relacionados con el desequilibrio del tráfico y los restablecimientos de conexión:

  • Área de enfoque: Desequilibrio en el balanceo de cargas, fallas en el handshake de TCP y finalización repentina de la conexión.
  • Requisitos previos: Métricas de GKE Dataplane V2 habilitadas.
  • Compatibilidad con CNI: GKE Dataplane V2.
  • Síntoma: Ciertas réplicas de Pod reciben tráfico excesivo, mientras que otras permanecen inactivas; las aplicaciones cliente registran connection reset by peer o broken pipe.
  • Objetivo: Determinar si el desequilibrio del tráfico se debe a la persistencia de la conexión en la capa de transporte (capa 4 del modelo OSI, TCP) en comparación con la capa de aplicación (capa 7 del modelo OSI, HTTP/2 o gRPC) y, luego, identificar la fuente de los paquetes RST de TCP.

Paso 1: Compara el flujo de tráfico a nivel del Pod

Para determinar si el tráfico se distribuye de manera uniforme entre tus réplicas, haz lo siguiente:

  1. En Cloud Monitoring, consulta el recuento de flujos de entrada en todos los Pods de una Deployment:

    sum by (pod) (rate(pod_flow_ingress_flows_count{destination_workload="my-service"}[5m]))
    
  2. Evalúa la distribución del tráfico entre los Pods. Si un solo Pod recibe la mayoría del tráfico, investiga la reutilización de conexiones o las sesiones persistentes:

    • gRPC o HTTP/2: Las conexiones TCP de larga duración hacen que todas las solicitudes atraviesen un solo flujo de TCP hacia un Pod de backend. El enrutamiento de servicios de Kubernetes de capa de transporte (capa 4 del modelo OSI, TCP) no puede balancear las solicitudes dentro de una conexión HTTP/2 establecida.
    • Afinidad de sesión de ClientIP: Verifica si el servicio está configurado con sessionAffinity: ClientIP.
    • Services sin interfaz gráfica: Es posible que los clientes resuelvan el DNS una vez y almacenen en caché la única dirección IP de forma permanente.

Paso 2: Analiza las métricas de restablecimiento de TCP

Los restablecimientos de TCP (RST) finalizan las conexiones de inmediato. El kernel del sistema operativo los emite cuando un extremo recibe un paquete para un puerto desconocido o cuando una aplicación cierra una conexión con datos no leídos en el búfer.

Ejecuta la siguiente consulta de MQL en Cloud Monitoring:

fetch prometheus_target
| metric 'prometheus.googleapis.com/hubble_tcp_flags_total/counter'
| filter (metric.flag == 'RST')
| align rate(1m)
| every 1m
| group_by [metric.source, metric.destination, metric.traffic_direction], sum(val())

Revisa los resultados de la consulta para determinar la fuente del restablecimiento:

  • RST saliente (traffic_direction=egress): El Pod local genera el restablecimiento. Verifica si la aplicación del Pod falla, alcanza su límite de conexión o rechaza activamente la conexión.
  • RST entrante (traffic_direction=ingress): El par remoto (base de datos externa, API o Pod remoto) envió el restablecimiento. Verifica el estado del servidor de destino y los estados del firewall.

Paso 3: Transmite restablecimientos de TCP en vivo

Usa la CLI de Hubble para capturar el handshake de restablecimiento en vivo:

gke-hubble observe --type trace --verdict FORWARDED --tcp-flags RST --namespace default

Paso 4: Corrección y soluciones prácticas

Aplica los siguientes pasos de corrección según la causa del desequilibrio del tráfico o los restablecimientos de TCP:

  • Para la permanencia de la conexión a nivel de la aplicación (capa 7 del modelo OSI) o de gRPC, haz lo siguiente:
    • Implementa Cloud Service Mesh para habilitar el balanceo de cargas a nivel de la solicitud (capa 7 del modelo OSI) en la capa de aplicación.
    • Configura límites de conexión del cliente o tiempos de espera de keep-alive (por ejemplo, gRPC MAX_CONNECTION_AGE y MAX_CONNECTION_AGE_GRACE) para forzar el restablecimiento periódico de la conexión.
  • Para la afinidad de IP de Service: Quita service.spec.sessionAffinity, a menos que el estado de la aplicación lo requiera estrictamente.
  • Para el almacenamiento en caché de DNS de Service sin interfaz gráfica: Asegúrate de que los tiempos de ejecución de la aplicación (como JVM networkaddress.cache.ttl) no almacenen en caché los resultados de DNS de forma indefinida.
  • Para el desbordamiento de la cola de backlog de la aplicación: Cuando una cola de escucha de la aplicación está llena, el kernel de Linux descarta los paquetes SYN entrantes o envía un RST de TCP. Escala horizontalmente las réplicas de Pod o aumenta la cantidad de elementos pendientes de escucha de la aplicación (somaxconn).

Nivel 2: Observabilidad de nodos y CNI (kernel)

El nivel de nodo y CNI abarca el kernel de Linux del host, los programas eBPF y las interfaces de red del nodo. Los cuellos de botella en este nivel afectan todas las cargas de trabajo que se ejecutan en el nodo afectado.

Verificación de integridad del sistema: Detecta parches no autorizados de anetd

GKE Dataplane V2 se ejecuta como un DaemonSet administrado (anetd) en el espacio de nombres kube-system. En Cloud Logging, puedes consultar los registros de auditoría de Kubernetes para detectar si usuarios no autorizados o secuencias de comandos automatizadas aplicaron parches o reiniciaron anetd:

protoPayload.methodName="io.k8s.core.v1.daemonsets.patch" OR
protoPayload.methodName="io.k8s.core.v1.daemonsets.update"
protoPayload.resourceName="namespaces/kube-system/daemonsets/anetd"

Si se detecta una aplicación de parches no autorizada, revierte el DaemonSet a la configuración predeterminada o activa una recreación del grupo de nodos para restablecer el estado administrado.


Triaje para la latencia a nivel del nodo y los cuellos de botella de la CNI

Revisa el alcance del diagnóstico y los requisitos previos antes de diagnosticar la latencia a nivel del nodo y los cuellos de botella del kernel:

  • Área de enfoque: Latencia del kernel del host, pérdida de paquetes en la interfaz de la VM, saturación del agente eBPF de GKE Dataplane V2 y agotamiento de conntrack.
  • Requisitos previos: Métricas de VM de Compute Engine habilitadas; acceso de kubectl.
  • Compatibilidad con CNI: GKE Dataplane V2 y CNI de GKE estándar.
  • Síntoma: El tráfico entre nodos experimenta aumentos repentinos de latencia o caídas aleatorias, mientras que el tráfico dentro del nodo permanece en buen estado.
  • Objetivo: Diferenciar entre la limitación de la red de la VM host, las pérdidas del kernel de Linux y los cuellos de botella a nivel del CNI.

Paso 1: Diferencia los problemas fuera de GKE de los problemas dentro de GKE

Ejecuta la prueba de referencia de la VM de Compute Engine: Implementa una VM de Compute Engine independiente en la misma subred de VPC que los nodos del clúster de GKE. Prueba la conectividad de la VM al destino.

  • Si la VM independiente experimenta la misma pérdida de paquetes o latencia: El problema se encuentra fuera de GKE (firewalls de VPC, Cloud NAT, Cloud Interconnect o el servidor externo). Continúa con Aislamiento de problemas de conectividad externa, de VPC o de GKE.
  • Si la VM independiente se comunica normalmente, pero fallan los Pods de GKE, el problema está dentro de GKE (eBPF a nivel del nodo, conntrack o CNI). Continúa con el paso 2.

Paso 2: Diferencia los problemas de la aplicación de los problemas de nivel de CNI y nodos

Para determinar si la latencia se origina en la aplicación o en el nodo y el nivel de CNI, haz lo siguiente:

  1. Verifica la saturación de recursos de la aplicación: Verifica que el nodo no experimente limitaciones de CPU ni presión de memoria, lo que retrasa el procesamiento de paquetes en el espacio del usuario:

    kubectl top nodes
    kubectl top pods -n default
    
  2. Inspecciona el recuento de conntrack del kernel de Linux: Verifica el recuento de conntrack activo en el host:

    # On a node where you have debugging access
    cat /proc/sys/net/netfilter/nf_conntrack_count
    cat /proc/sys/net/netfilter/nf_conntrack_max
    

    Si nf_conntrack_count se acerca a nf_conntrack_max, el kernel del host descarta los paquetes SYN de TCP nuevos.

Paso 3: Verifica las pérdidas de paquetes a nivel de la VM con la telemetría de Compute Engine

Google Cloud Compute Engine exporta métricas de la interfaz de red a nivel de la VM a Cloud Monitoring.

En Cloud Monitoring > Explorador de métricas, ejecuta la siguiente consulta:

sum by (drop_reason) (rate(compute_googleapis_com:instance_network_dropped_packets_count[5m]))
  • FQ_CODEL_DROP: Paquete descartado debido a la saturación de la fila de Fair Queuing o CoDel (se excedió el límite de ancho de banda de salida de la VM).
  • FIREWALL_RULE_DROP: Paquete descartado por una regla de firewall de VPC.
  • RATE_LIMIT_DROP: Se descartó el paquete porque la VM superó su cuota máxima de paquetes por segundo (PPS) de la interfaz de red.

Paso 4: Investiga las pérdidas a nivel del kernel con eBPF

Si las métricas a nivel de la VM muestran cero pérdidas, pero los Pods de GKE siguen perdiendo paquetes, inspecciona el agente de GKE Dataplane V2 (anetd) para detectar pérdidas de mapas de eBPF:

kubectl logs -n kube-system daemonset/anetd -c cilium-agent --tail=200 | grep -i "drop"

Busca ct-map-insertion-failed o fib-lookup-failed.


Nivel 3: Observabilidad de la VPC y el enrutamiento (red de Cloud)

El nivel de enrutamiento de VPC y de nube conecta los nodos de GKE a otros Google Cloud servicios, redes locales y a Internet. Los errores aquí suelen deberse a reglas de firewall de VPC, rutas personalizadas o configuraciones de puerta de enlace.

Aislamiento de problemas de conectividad externos, de VPC o de GKE

Revisa el alcance del diagnóstico y los requisitos previos antes de aislar los problemas de red externos de las fallas en el clúster:

  • Área de enfoque: Aislamiento de límites entre el enrutamiento interno de Kubernetes y el enrutamiento de Cloud de la VPC.
  • Requisitos previos: gcloud CLI y permisos para crear pruebas de conectividad.
  • Compatibilidad con CNI: Todos los clústeres.
  • Síntoma: Los Pods no se pueden conectar a un recurso externo (por ejemplo, Cloud SQL, una API local o un extremo de terceros).
  • Objetivo: Determinar rápidamente si la pérdida ocurre dentro del nodo de GKE o dentro de la VPC Google Cloud o la red externa.

Paso 1: La prueba de referencia de la VM de Compute Engine

Para implementar una VM de referencia y evaluar si el problema persiste fuera de GKE, haz lo siguiente:

  1. Implementa una instancia de VM de Compute Engine temporal en la misma subred y zona de VPC que tu grupo de nodos de GKE:

    gcloud compute instances create gke-baseline-tester \
        --zone=us-central1-a \
        --subnet=gke-subnet \
        --machine-type=e2-micro
    
  2. Conéctate a la instancia con SSH y prueba la conectividad con el destino:

    curl -v --connect-timeout 5 https://api.example.com
    
  3. Evalúa el resultado:

    • Si la VM de Compute Engine no se puede conectar: El problema se encuentra en la VPC o en la red externa (reglas de firewall, tablas de enrutamiento, agotamiento de la IP de Cloud NAT o inclusión en la lista de entidades permitidas de la IP externa).
    • Si la VM de Compute Engine se conecta correctamente: El problema está dentro de GKE (NetworkPolicy que bloquea el tráfico de salida, CIDR del Pod sin enmascarar o DNS a nivel del contenedor).

Paso 2: Ejecuta una prueba de conectividad a pedido

Ejecuta una prueba de Google Cloud Connectivity Tests desde la VM del nodo hasta el destino:

gcloud network-management connectivity-tests create test-node-to-dest \
    --source-instance=projects/PROJECT_ID/zones/us-central1-a/instances/gke-baseline-tester \
    --destination-ip-address=203.0.113.10 \
    --destination-port=443 \
    --protocol=TCP

Verifica el resultado en la consola de Google Cloud para identificar si una regla de firewall o una ruta de VPC están descartando el tráfico.


Diagnostica la conectividad con las pruebas de conectividad

Las pruebas de conectividad simulan las rutas de paquetes en los recursos de GKE y VPC sin enviar tráfico en vivo. Esta simulación evalúa la resolución de DNAT de ClusterIP de Service a Pod, las reglas de entrada y salida de NetworkPolicy de GKE Dataplane V2, y el enmascaramiento de IP de nodo (SNAT). Revisa el alcance del diagnóstico y los requisitos previos antes de ejecutar simulaciones de rutas automatizadas:

  • Área de enfoque: Simulación automatizada de rutas estáticas para Pods, Services, NetworkPolicies y rutas de VPC de GKE.
  • Requisitos previos: Network Intelligence Center habilitado y API de Management de red habilitada
  • Compatibilidad con CNI: GKE Dataplane V2 (análisis mejorado).
  • Síntoma: Se producen interrupciones inexplicables de la conectividad en las que todos los parámetros de configuración parecen válidos tras una inspección manual.
  • Objetivo: Simular y rastrear de forma estática toda la ruta de paquetes desde una fuente de Pod hasta el destino, e identificar la línea exacta de la política que causa una caída.

Situación A: Verifica si una NetworkPolicy de GKE bloquea la recopilación de métricas

Cuando se recopilan métricas de Pods en un espacio de nombres seguro, es posible que los recopiladores de Google Cloud Managed Service para Prometheus se bloqueen con una NetworkPolicy de rechazo predeterminado:

gcloud network-management connectivity-tests create test-gmp-to-pod \
    --source-ip-address=10.0.0.15 \
    --destination-gke-pod=projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME/k8s/namespaces/prod/pods/backend-pod \
    --destination-port=8080 \
    --protocol=TCP

Inspecciona el registro de la prueba en Google Cloud console. Si la prueba finaliza en el paso GKE Network Policy evaluation con DROP, se debe agregar una regla de entrada para permitir el tráfico de los Pods del recopilador.

Situación B: Verifica la accesibilidad a un servicio de GKE

Simula la accesibilidad desde una VM cliente a un servicio interno de Kubernetes:

gcloud network-management connectivity-tests create test-vm-to-service \
    --source-instance=projects/PROJECT_ID/zones/us-central1-a/instances/client-vm \
    --destination-ip-address=10.96.0.100 \
    --destination-port=80 \
    --protocol=TCP

El registro simulado muestra lo siguiente:

  1. Coincidencia de ruta de VPC.
  2. Permiso de entrada y salida del firewall de VPC
  3. Llegada al nodo de GKE.
  4. DNAT del servicio a la dirección IP del Pod de backend.
  5. Evaluación de Ingress NetworkPolicy en el Pod de backend.

Situación C: Diagnostica problemas de salida de Pod a Internet

Cuando los Pods no pueden acceder a una API externa en Internet, sucede lo siguiente:

  1. Crea una prueba desde el Pod hasta la dirección IP pública externa (como 8.8.8.8):

    gcloud network-management connectivity-tests create test-pod-to-internet \
        --source-gke-pod=projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME/k8s/namespaces/prod/pods/app-pod \
        --destination-ip-address=8.8.8.8 \
        --destination-port=53 \
        --protocol=UDP
    
  2. Examina el punto de entrega:

    • Descartado en NetworkPolicy: El Pod no tiene una política de red de salida que permita el tráfico a 0.0.0.0/0.
    • Se descartó en el firewall de VPC: Una regla de firewall de VPC deniega el tráfico saliente de la subred del nodo.
    • Se descartó en Cloud NAT o en la ruta: La subred no tiene una ruta predeterminada a la puerta de enlace de Internet, o bien Cloud NAT no está configurado para la subred.

Nivel 4: Observabilidad de la puerta de enlace externa y el costo (Internet y NAT)

El nivel de puerta de enlace externa administra el tráfico saliente a destinos de Internet públicos a través de Cloud NAT o puertas de enlace externas. La observabilidad en este nivel ayuda a identificar las cargas de trabajo con una salida alta y a controlar los costos de transferencia de datos.

Identifica el tráfico de NAT (salida a Internet)

Revisa el alcance del diagnóstico y los requisitos previos antes de analizar el tráfico saliente de Internet y NAT:

  • Área de enfoque: Tráfico saliente de Internet, utilización de puertos de Cloud NAT y costos de transferencia de datos externos
  • Requisitos previos: Observabilidad de flujo de GKE Dataplane V2 habilitada.
  • Compatibilidad con CNI: GKE Dataplane V2.
  • Síntoma: Errores de agotamiento de puertos de Cloud NAT o costos de salida a Internet inesperadamente altos.
  • Objetivo: Identificar qué objetos Pod y Service específicos de GKE transmiten tráfico a extremos externos de Internet.

Paso 1: Comprende los conceptos de "pila" y "mundo" en GKE Dataplane V2

En GKE Dataplane V2, sucede lo siguiente:

  • world: Representa cualquier destino fuera del clúster de GKE y fuera de la VPC (Internet pública).
  • to-stack: Representa los paquetes que realizan la transición desde la interfaz veth del contenedor eBPF a la pila de redes de Linux del host para someterse al enmascaramiento de IP (SNAT) antes de llegar a Cloud NAT.

Paso 2: Transmite y filtra el tráfico de NAT con la CLI de Hubble

Transmite en vivo los flujos de Internet salientes que se originan en tu clúster:

# Stream egress flows heading to external internet ("world")
gke-hubble observe \
    --traffic-direction egress \
    --verdict FORWARDED \
    --to-identity world \
    --follow

Resultado de ejemplo:

TIMESTAMP             SOURCE               DESTINATION          TYPE     VERDICT
10:25:01.120          default/worker-pod   142.250.190.46:443   to-stack FORWARDED

Para identificar los principales comunicadores externos, también puedes canalizar la salida JSON de Hubble a jq para contar los flujos de salida externos por Pod:

timeout 60s gke-hubble observe \
    --traffic-direction egress \
    --verdict FORWARDED \
    --to-identity world \
    -o json | jq -r '.flow.source.namespace + "/" + .flow.source.pod_name' | sort | uniq -c | sort -nr | head -n 10

Paso 3: Supervisa el tráfico externo con métricas

En Cloud Monitoring, haz un seguimiento del volumen de flujos externos:

fetch prometheus_target
| metric 'prometheus.googleapis.com/pod_flow_egress_flows_count/counter'
| filter (metric.destination_identity == 'world')
| align rate(1m)
| every 1m
| group_by [metric.source_workload, metric.source_namespace], sum(val())

Analiza el rendimiento y los costos del tráfico del clúster con Flow Analyzer

Revisa el alcance del diagnóstico y los requisitos previos antes de visualizar los flujos de tráfico y los costos entre zonas:

  • Área de enfoque: Costos de transferencia de datos entre zonas, principales comunicadores y visibilidad del tráfico entre nodos sin consultas en SQL
  • Requisitos previos: Registros de flujo de VPC habilitados con INCLUDE_ALL_METADATA; visibilidad dentro de los nodos habilitada; Observability Analytics habilitado en el bucket de registros.
  • Compatibilidad con CNI: Todos los clústeres.
  • Síntoma: Cargos elevados por transferencia de datos entre zonas en las facturas mensualesGoogle Cloud .
  • Objetivo: Identificar visualmente qué cargas de trabajo de GKE generan tráfico entre zonas y optimizar la colocación sin consultar registros sin procesar.

Requisitos previos

Para usar Flow Analyzer en GKE, haz lo siguiente:

  1. Los registros de flujo de VPC deben estar habilitados en la subred del clúster con metadata="INCLUDE_ALL_METADATA".
  2. Visibilidad dentro de los nodos: Debe estar habilitada en el clúster para que el tráfico de Pod a Pod se exponga a la canalización de registros de flujo de VPC.
  3. Análisis de registros: El bucket _Default en Cloud Logging debe actualizarse para usar el Análisis de observabilidad.

Paso 1: Identifica los flujos que generan la mayor cantidad de tráfico en GKE con Flow Analyzer

Para ver cargas de trabajo de gran volumen en Flow Analyzer, haz lo siguiente:

  1. En la consola de Google Cloud , ve a la página Flow Analyzer.
  2. Haz clic en Bucket de origen y selecciona el bucket de registros que contiene tus registros de flujo. A menos que los hayas enrutado a otro lugar, este es el bucket _Predeterminado.
  3. En Agregación de tráfico, selecciona Origen -> destino.
  4. Establece el período de tu ventana de análisis.
  5. En Organizar flujos por, selecciona los campos de Pod o carga de trabajo de GKE.
  6. Haz clic en Ejecutar consulta nueva. El gráfico Highest data flows muestra qué cargas de trabajo transfieren la mayor cantidad de datos.

Paso 2: Analiza los costos del tráfico entre zonas

El tráfico entre zonas genera cargos por transferencia de datos. Para ubicar las cargas de trabajo que se transmiten entre zonas, haz lo siguiente:

  1. En Organizar flujos por, selecciona los campos de zona de origen y zona de destino.
  2. Haz clic en Ejecutar consulta nueva y lee la tabla Todos los flujos de datos. Las filas en las que las zonas de origen y destino difieren representan tu tráfico entre zonas. Los filtros de Flow Analyzer coinciden con los valores, por lo que no puedes filtrar por "no es igual"; en su lugar, compara los pares de zonas en los resultados.
  3. Expande un par de zonas con un volumen alto para ver las cargas de trabajo de GKE subyacentes de origen y destino.

Corrección:

  • Implementa topologySpreadConstraints o podAffinity de Kubernetes para ubicar los servicios que se comunican en la misma zona de disponibilidad.
  • Habilita el enrutamiento compatible con la topología (service.kubernetes.io/topology-mode: Auto) en el servicio para mantener el tráfico dentro de la zona de origen.

Paso 3: Explora en detalle Estadísticas de observabilidad (para consultas en SQL avanzadas)

En Flow Analyzer, haz clic en Ver en el Análisis de registros para ejecutar consultas en SQL en los datos del flujo.

La siguiente consulta en SQL calcula los principales comunicadores de Pods entre zonas:

SELECT
  JSON_VALUE(json_payload.src_gke_details.pod.workload.workload_name) AS src_workload,
  JSON_VALUE(json_payload.dest_gke_details.pod.workload.workload_name) AS dest_workload,
  JSON_VALUE(json_payload.src_instance.zone) AS src_zone,
  JSON_VALUE(json_payload.dest_instance.zone) AS dest_zone,
  SUM(CAST(JSON_VALUE(json_payload.bytes_sent) AS INT64)) / 1024 / 1024 / 1024 AS total_gb_sent
FROM
  `PROJECT_ID.global._Default._AllLogs`
WHERE
  log_name LIKE '%vpc_flows%'
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  AND JSON_VALUE(json_payload.src_instance.zone) != JSON_VALUE(json_payload.dest_instance.zone)
GROUP BY
  1, 2, 3, 4
ORDER BY
  total_gb_sent DESC
LIMIT 20;

Hoja de referencia y consulta de la CLI de Hubble

La CLI de Hubble transmite y filtra datos de flujo de red en vivo directamente desde el búfer de anillo del kernel de GKE Dataplane V2.

Configuración: Crea un alias auxiliar

Como Hubble se ejecuta dentro del plano de control del clúster, configura un alias de shell para ejecutar comandos de Hubble sin implementar archivos binarios locales:

alias gke-hubble="kubectl exec -it -n gke-managed-dpv2-observability deployment/hubble-relay -c hubble-cli -- hubble"

Recetas de filtrado comunes

Objetivo de solución de problemas Comando de la CLI de Hubble
Observa todos los paquetes descartados en tiempo real en todo el clúster gke-hubble observe --verdict DROPPED --follow
Transmite todo el tráfico de un Pod específico en cualquier espacio de nombres gke-hubble observe --pod default/my-pod --follow
Filtrar el tráfico entre dos espacios de nombres específicos gke-hubble observe --from-namespace frontend --to-namespace backend
Aísla el tráfico en un puerto específico (como el puerto 80). gke-hubble observe --port 80
Inspecciona las preguntas y respuestas de DNS en vivo gke-hubble observe --port 53
Cómo ver los restablecimientos de TCP en vivo (paquetes RST) gke-hubble observe --type trace --verdict FORWARDED --tcp-flags RST
Transmite todo el tráfico saliente que se dirige a Internet pública gke-hubble observe --traffic-direction egress --to-identity world
Inspecciona el tráfico de la capa de aplicación HTTP (capa 7 del modelo OSI) gke-hubble observe --protocol http

Filtrado avanzado con negación (--not)

Puedes excluir el tráfico conocido de gran volumen o el tráfico normal para enfocarte en las anomalías:

# Observe drops, but exclude internal kube-system health probes and DNS
gke-hubble observe \
    --verdict DROPPED \
    --not --namespace kube-system \
    --not --port 53

Formato de salida e integración de jq

Para procesar registros de flujo de forma programática, genera el resultado en formato JSON:

# Extract only source, destination, and drop reason from the last 100 flows
gke-hubble observe --verdict DROPPED -o json --last 100 | \
    jq -r '[.time, .flow.source.pod_name, .flow.destination.pod_name, .flow.drop_reason_desc] | @tsv'

Limitaciones

Cuando uses la CLI de Hubble para solucionar problemas en vivo, ten en cuenta las siguientes limitaciones técnicas:

  • Búfer de anillo efímero local del nodo: Los flujos de Hubble se almacenan en un búfer de anillo en la memoria de cada nodo individual. Durante los eventos de tráfico alto, los registros de flujo más antiguos se reemplazan en segundos. Para el análisis histórico, confía en el registro de NetworkPolicy y los registros de flujo de VPC en Cloud Logging.
  • No hay una opción lógica OR integrada: Las marcas de la CLI de Hubble evalúan varios argumentos con la opción lógica AND. Para buscar varias condiciones (como el puerto 80 O el puerto 443), ejecuta comandos separados o filtra el resultado JSON con jq.

¿Qué sigue?