Cómo combinar todo: Situación de ejemplo para solucionar problemas

Comprender las herramientas individuales de solución de problemas de Google Kubernetes Engine (GKE) es útil, pero ver cómo se usan juntas para resolver un problema del mundo real puede ayudarte a consolidar tus conocimientos.

Sigue un ejemplo guiado que combina el uso de la Google Cloud consola, la kubectl herramienta de línea de comandos, Cloud Logging y Cloud Monitoring juntos para identificar la causa raíz de un error OutOfMemory (OOMKilled).

Este ejemplo es beneficioso para cualquier persona que desee ver una aplicación práctica de las técnicas de solución de problemas que se describen en esta serie, en particular, los operadores y administradores de plataformas, y los desarrolladores de aplicaciones. Para obtener más información sobre los roles comunes y las tareas de ejemplo a las que hacemos referencia en Google Cloud el contenido, consulta Roles y tareas comunes del usuario de GKE.

Situación hipotética

Eres el ingeniero de guardia de una app web llamada product-catalog que se ejecuta en GKE.

Tu investigación comienza cuando recibes una alerta automatizada de Cloud Monitoring:

Alert: High memory utilization for container 'product-catalog' in 'prod' cluster.

Esta alerta te indica que existe un problema y que está relacionado con la carga de trabajo product-catalog.

Confirma el problema en la Google Cloud consola de Cloud

Comienza con una vista de alto nivel de tus cargas de trabajo para confirmar el problema.

  1. En la Google Cloud consola de Cloud, navega a la página Cargas de trabajo y filtra por tu carga de trabajo product-catalog.
  2. Observa la columna de estado de Pods. En lugar de 3/3 en buen estado, ves que el valor muestra constantemente un estado no saludable: 2/3. Este valor te indica que uno de los Pods de tu app no tiene el estado Ready.
  3. Para investigar más, haz clic en el nombre de la carga de trabajo product-catalog para ir a su página de detalles.
  4. En la página de detalles, consulta la sección Pods administrados. Identificas de inmediato un problema: la columna Restarts de tu Pod muestra 14, un número inusualmente alto.

Este alto recuento de reinicios confirma que el problema está causando inestabilidad en la app y sugiere que un contenedor no está pasando sus verificaciones de estado o se está fallando.

Encuentra el motivo con los comandos kubectl

Ahora que sabes que tu app se reinicia de forma repetida, debes averiguar por qué. El comando kubectl describe es una buena herramienta para esto.

  1. Obtén el nombre exacto del Pod inestable:

    kubectl get pods -n prod
    

    Esta es la salida:

    NAME                             READY  STATUS            RESTARTS  AGE
    product-catalog-d84857dcf-g7v2x  0/1    CrashLoopBackOff  14        25m
    product-catalog-d84857dcf-lq8m4  1/1    Running           0         2h30m
    product-catalog-d84857dcf-wz9p1  1/1    Running           0         2h30m
    
  2. Describe el Pod inestable para obtener el historial de eventos detallado:

    kubectl describe pod product-catalog-d84857dcf-g7v2x -n prod
    
  3. Revisa el resultado y busca pistas en las secciones Last State y Events:

    Containers:
      product-catalog-api:
        ...
        State:          Waiting
          Reason:       CrashLoopBackOff
        Last State:     Terminated
          Reason:       OOMKilled
          Exit Code:    137
          Started:      Mon, 23 Jun 2025 10:50:15 -0700
          Finished:     Mon, 23 Jun 2025 10:54:58 -0700
        Ready:          False
        Restart Count:  14
    ...
    Events:
      Type     Reason     Age                           From                Message
      ----     ------     ----                          ----                -------
      Normal   Scheduled  25m                           default-scheduler   Successfully assigned prod/product-catalog-d84857dcf-g7v2x to gke-cs-cluster-default-pool-8b8a777f-224a
      Normal   Pulled     8m (x14 over 25m)             kubelet             Container image "us-central1-docker.pkg.dev/my-project/product-catalog/api:v1.2" already present on machine
      Normal   Created    8m (x14 over 25m)             kubelet             Created container product-catalog-api
      Normal   Started    8m (x14 over 25m)             kubelet             Started container product-catalog-api
      Warning  BackOff    3m (x68 over 22m)             kubelet             Back-off restarting failed container
    

    El resultado te da dos pistas fundamentales:

    • En primer lugar, la sección Last State muestra que el contenedor se cerró con Reason: OOMKilled, lo que te indica que se quedó sin memoria. Este motivo se confirma con Exit Code: 137, que es el código de salida estándar de Linux para un proceso que se cerró debido al consumo excesivo de memoria.
    • En segundo lugar, la sección Events muestra un evento Warning: BackOff con el mensaje Back-off restarting failed container. Este mensaje confirma que el contenedor está en un bucle de fallas, que es la causa directa del estado CrashLoopBackOff que viste antes.

Visualiza el comportamiento con métricas

El comando kubectl describe te indicó lo que sucedió, pero Cloud Monitoring puede mostrarte el comportamiento de tu entorno a lo largo del tiempo.

  1. En la Google Cloud consola de Cloud, ve al Explorador de métricas.
  2. Selecciona la métrica container/memory/used_bytes.
  3. Filtra el resultado hasta tu clúster, espacio de nombres y nombre de Pod específicos.

El gráfico muestra un patrón distinto: el uso de memoria aumenta de manera constante y, luego, cae abruptamente a cero cuando el contenedor se cierra por falta de memoria y se reinicia. Esta evidencia visual confirma una fuga de memoria o un límite de memoria insuficiente.

Encuentra la causa raíz en los registros

Ahora sabes que el contenedor se está quedando sin memoria, pero aún no sabes exactamente por qué. Para descubrir la causa raíz, usa el Explorador de registros.

  1. En la Google Cloud consola de Cloud, navega al Explorador de registros.
  2. Escribe una consulta para filtrar los registros de tu contenedor específico justo antes del momento de la última falla (que viste en el resultado del comando kubectl describe):

    resource.type="k8s_container"
    resource.labels.cluster_name="example-cluster"
    resource.labels.namespace_name="prod"
    resource.labels.pod_name="product-catalog-d84857dcf-g7v2x"
    timestamp >= "2025-06-23T17:50:00Z"
    timestamp < "2025-06-23T17:55:00Z"
    
  3. En los registros, encuentras un patrón repetitivo de mensajes justo antes de cada falla:

    {
      "message": "Processing large image file product-image-large.jpg",
      "severity": "INFO"
    },
    {
      "message": "WARN: Memory cache size now at 248MB, nearing limit.",
      "severity": "WARNING"
    }
    

Estas entradas de registro te indican que la app intenta procesar archivos de imagen grandes cargándolos por completo en la memoria, lo que, finalmente, agota el límite de memoria del contenedor.

Los hallazgos

Si usas las herramientas juntas, tendrás una imagen completa del problema:

  • La alerta de supervisión te notificó que había un problema.
  • La Google Cloud consola de Cloud te mostró que el problema afectaba a los usuarios (reinicios).
  • Los comandos kubectl señalaron el motivo exacto de los reinicios (OOMKilled).
  • El Explorador de métricas visualizó el patrón de fuga de memoria a lo largo del tiempo.
  • El Explorador de registros reveló el comportamiento específico que causa el problema de memoria.

Ya está todo listo para implementar una solución. Puedes optimizar el código de la app para controlar archivos grandes de manera más eficiente o, como solución a corto plazo, aumentar el límite de memoria del contenedor (específicamente, el valor spec.containers.resources.limits.memory) en el manifiesto YAML de la carga de trabajo.

¿Qué sigue?