En este tutorial se muestra cómo puede solucionar problemas de un servicio de Cloud Run que no funciona un desarrollador de servicios mediante las herramientas de Google Cloud Observability para la detección y un flujo de trabajo de desarrollo local para la investigación.
Esta guía detallada, que complementa la guía para solucionar problemas, utiliza un proyecto de ejemplo que genera errores de tiempo de ejecución al implementarse. Tu tarea será solucionar estos errores para encontrar y corregir el problema.
Configurar los valores predeterminados de gcloud
Para configurar gcloud con los valores predeterminados de tu servicio de Cloud Run, sigue estos pasos:
Configura tu proyecto predeterminado:
gcloud config set project PROJECT_ID
Sustituye PROJECT_ID por el nombre del proyecto que has creado para este tutorial.
Configura gcloud para la región que hayas elegido:
gcloud config set run/region REGION
Sustituye REGION por la región de Cloud Run compatible que quieras.
Ubicaciones de Cloud Run
Cloud Run es regional, lo que significa que la infraestructura que ejecuta tus servicios de Cloud Run se encuentra en una región específica y Google la gestiona para que esté disponible de forma redundante en todas las zonas de esa región.
Cumplir tus requisitos de latencia, disponibilidad o durabilidad son factores primordiales para seleccionar la región en la que se ejecutan tus servicios de Cloud Run.
Por lo general, puedes seleccionar la región más cercana a tus usuarios, pero debes tener en cuenta la ubicación de los otros Google Cloudproductos que utiliza tu servicio de Cloud Run.
Usar Google Cloud productos juntos en varias ubicaciones puede afectar a la latencia y al coste de tu servicio.
Cloud Run está disponible en las siguientes regiones:
Con sujeción a los precios del nivel 1
asia-east1
(Taiwán)asia-northeast1
(Tokio)asia-northeast2
(Osaka)asia-south1
(Bombay, la India)europe-north1
(Finlandia)CO2 bajo
europe-north2
(Estocolmo)CO2 bajo
europe-southwest1
(Madrid)CO2 bajo
europe-west1
(Bélgica)CO2 bajo
europe-west4
(Países Bajos)CO2 bajo
europe-west8
(Milán)europe-west9
(París)CO2 bajo
me-west1
(Tel Aviv)northamerica-south1
(México)us-central1
(Iowa)CO2 bajo
us-east1
(Carolina del Sur)us-east4
(Norte de Virginia)us-east5
(Columbus)us-south1
(Dallas)CO2 bajo
us-west1
(Oregón)CO2 bajo
Con sujeción a los precios del nivel 2
africa-south1
(Johannesburgo)asia-east2
(Hong Kong)asia-northeast3
(Seúl, Corea del Sur)asia-southeast1
(Singapur)asia-southeast2
(Yakarta)asia-south2
(Delhi, la India)australia-southeast1
(Sídney)australia-southeast2
(Melbourne)europe-central2
Varsovia (Polonia)europe-west10
(Berlín)europe-west12
(Turín)europe-west2
(Londres, Reino Unido)CO2 bajo
europe-west3
(Fráncfort, Alemania)europe-west6
(Zúrich, Suiza)Bajas emisiones de CO2
me-central1
(Doha)me-central2
(Dammam)northamerica-northeast1
(Montreal)CO2 bajo
northamerica-northeast2
(Toronto)CO2 bajo
southamerica-east1
(São Paulo, Brasil)CO2 bajo
southamerica-west1
(Santiago, Chile)CO2 bajo
us-west2
(Los Ángeles)us-west3
(Salt Lake City)us-west4
(Las Vegas)
Si ya has creado un servicio de Cloud Run, puedes ver la región en el panel de control de Cloud Run de la Google Cloud consola.
Ensamblar el código
Crea paso a paso un nuevo servicio de saludo de Cloud Run. Te recordamos que este servicio crea un error de tiempo de ejecución a propósito para el ejercicio de solución de problemas.
Para crear un proyecto:
Node.js
Crea un proyecto de Node.js definiendo el paquete de servicio, las dependencias iniciales y algunas operaciones comunes.Para crear un directorio de
hello-service
, sigue estos pasos:mkdir hello-service cd hello-service
Crea un proyecto de Node.js generando un archivo
package.json
:npm init --yes npm install express@4
Abre el nuevo archivo
package.json
en tu editor y configura unastart
secuencia de comandos para ejecutarnode index.js
. Cuando haya terminado, el archivo tendrá este aspecto:
Si sigues desarrollando este servicio más allá del tutorial inmediato, te recomendamos que rellenes la descripción y el autor, y que evalúes la licencia. Para obtener más información, consulta la documentación de package.json.
Python
Para crear un directorio de
hello-service
, sigue estos pasos:mkdir hello-service cd hello-service
Crea un archivo requirements.txt y copia tus dependencias en él:
Go
Para crear un directorio de
hello-service
, sigue estos pasos:mkdir hello-service cd hello-service
Crea un proyecto de Go inicializando un nuevo módulo de Go:
go mod init example.com/hello-service
Puedes actualizar el nombre específico como quieras. Debes actualizar el nombre si el código se publica en un repositorio de código accesible a través de la Web.
Java
Crea un proyecto de Maven:
mvn archetype:generate \ -DgroupId=com.example.cloudrun \ -DartifactId=hello-service \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false
Copia las dependencias en la lista de dependencias
pom.xml
(entre los elementos<dependencies>
):Copia el ajuste de compilación en tu
pom.xml
(en los elementos<dependencies>
):
Crea un servicio HTTP para gestionar las solicitudes entrantes:
Node.js
Python
Go
Java
Crea un
Dockerfile
para definir la imagen de contenedor que se usará para desplegar el servicio:Node.js
Python
Go
Java
En este ejemplo se usa Jib para crear imágenes de Docker con herramientas comunes de Java. Jib optimiza las compilaciones de contenedores sin necesidad de usar un Dockerfile ni de tener Docker instalado. Más información sobre cómo crear contenedores Java con Jib
Envío del código
El envío de código consta de tres pasos: compilar una imagen de contenedor con Cloud Build, subir la imagen de contenedor a Container Registry y desplegar la imagen de contenedor en Cloud Run.
Para enviar tu código, sigue estos pasos:
Crea el contenedor y publícalo en Container Registry:
Node.js
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
Donde PROJECT_ID es el ID de tu proyecto de Google Cloud. Puedes consultar el ID de tu proyecto actual con
gcloud config get-value project
.Si el proceso se completa correctamente, verás un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Container Registry y se puede volver a usar si quieres.
Python
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
Donde PROJECT_ID es el ID de tu proyecto de Google Cloud. Puedes consultar el ID de tu proyecto actual con
gcloud config get-value project
.Si el proceso se completa correctamente, verás un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Container Registry y se puede volver a usar si quieres.
Go
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
Donde PROJECT_ID es el ID de tu proyecto de Google Cloud. Puedes consultar el ID de tu proyecto actual con
gcloud config get-value project
.Si el proceso se completa correctamente, verás un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Container Registry y se puede volver a usar si quieres.
Java
- Usa el asistente de credenciales de gcloud para autorizar a Docker a enviar contenido a tu Container Registry.
gcloud auth configure-docker
- Usa el complemento Jib Maven para compilar y enviar el contenedor a Container Registry.
mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/hello-service
Donde PROJECT_ID es el ID de tu proyecto de Google Cloud. Puedes consultar el ID de tu proyecto actual con
gcloud config get-value project
.Si todo va bien, debería aparecer el mensaje BUILD SUCCESS. La imagen se almacena en Container Registry y se puede volver a usar si quieres.
- Usa el asistente de credenciales de gcloud para autorizar a Docker a enviar contenido a tu Container Registry.
Ejecuta el siguiente comando para implementar tu aplicación:
gcloud run deploy hello-service --image gcr.io/PROJECT_ID/hello-service
Sustituye PROJECT_ID por el ID de tu proyecto de Google Cloud.
hello-service
es el nombre de la imagen de contenedor y el nombre del servicio de Cloud Run. Ten en cuenta que la imagen del contenedor se despliega en el servicio y la región que configuraste anteriormente en Configurar gcloud.Responde
y
("Sí") a la petición permitir sin autenticar. Consulta Gestionar el acceso para obtener más información sobre la autenticación basada en IAM.Espera a que se complete el despliegue, que puede tardar aproximadamente medio minuto. Si la acción se realiza correctamente, la línea de comandos mostrará la URL del servicio.
Probar la función
Prueba el servicio para confirmar que lo has implementado correctamente. Las solicitudes deben fallar con un error HTTP 500 o 503 (miembros de la clase 5xx Server errors). En el tutorial se explica cómo solucionar este error.
Al servicio se le asigna automáticamente una URL navegable.
Ve a esta URL con tu navegador web:
Abrir un navegador web
Busca la URL del servicio que ha generado el comando de implementación anterior.
Si el comando de implementación no ha proporcionado una URL, significa que algo ha ido mal. Revisa el mensaje de error y actúa en consecuencia. Si no hay ninguna guía práctica, consulta la guía para solucionar problemas y, si es necesario, vuelve a intentar ejecutar el comando de implementación.
Para ir a esta URL, cópiala en la barra de direcciones del navegador y pulsa INTRO.
Consulta el error HTTP 500 o HTTP 503.
Si recibes un error HTTP 403, es posible que hayas rechazado
allow unauthenticated invocations
en la solicitud de implementación. Concede acceso público al servicio para solucionar este problema:gcloud run services add-iam-policy-binding hello-service \ --member="allUsers" \ --role="roles/run.invoker"
Para obtener más información, consulta Permitir el acceso público (sin autenticación).
Investigar el problema
Imagina que el error HTTP 5xx que se ha producido en la sección Probar de arriba se ha producido como un error de tiempo de ejecución en producción. En este tutorial se explica un proceso formal para gestionarlo. Aunque los procesos para resolver errores de producción varían mucho, en este tutorial se presenta una secuencia de pasos concreta para mostrar la aplicación de herramientas y técnicas útiles.
Para investigar este problema, tendrás que completar las siguientes fases:
- Recoge más detalles sobre el error notificado para poder investigar más a fondo y definir una estrategia de mitigación.
- Reduce el impacto en los usuarios decidiendo si quieres seguir adelante con una corrección o volver a una versión que funcione correctamente.
- Reproduce el error para confirmar que se han recogido los detalles correctos y que no se trata de un fallo puntual.
- Realiza un análisis de la causa raíz del error para encontrar el código, la configuración o el proceso que lo ha provocado.
Al principio de la investigación, tienes una URL, una marca de tiempo y el mensaje "Error interno del servidor".
Gathering further details
Recaba más información sobre el problema para saber qué ha ocurrido y determinar los pasos siguientes.
Usa las herramientas de Google Cloud Observability disponibles para obtener más detalles:
Usa la consola Error Reporting, que proporciona un panel de control con detalles y seguimiento de la recurrencia de los errores con un rastreo de pila reconocido.
Ir a la consola Error Reporting
Lista de errores registrados. Los errores se agrupan por mensaje en las revisiones, los servicios y las plataformas. Haz clic en el error para ver los detalles del seguimiento de pila y anota las llamadas de función que se han hecho justo antes del error.
La sección "Ejemplo de rastreo de la pila" de la página de detalles del error muestra una sola instancia del error. Puedes revisar cada una de las instancias. Usa Cloud Logging para revisar la secuencia de operaciones que han llevado al problema, incluidos los mensajes de error que no se incluyen en la consola Error Reporting porque no se ha reconocido ningún seguimiento de pila de errores:
Ir a la consola de Cloud Logging
Selecciona Revisión de Cloud Run > hello-service en el primer cuadro desplegable. De esta forma, se filtrarán las entradas de registro para mostrar solo las que ha generado tu servicio.
Consulta más información sobre cómo ver registros en Cloud Run.
Restaurar una versión correcta
Si se trata de un servicio establecido que funciona, habrá una revisión anterior del servicio en Cloud Run. En este tutorial se usa un servicio nuevo sin versiones anteriores, por lo que no puedes restaurar una versión anterior.
Sin embargo, si tienes un servicio con versiones anteriores a las que puedes volver, sigue los pasos que se indican en Ver los detalles de una revisión para extraer el nombre del contenedor y los detalles de configuración necesarios para crear una nueva implementación operativa de tu servicio.
Reproducir el error
Con los detalles que has obtenido anteriormente, confirma que el problema se produce de forma constante en condiciones de prueba.
Envía la misma solicitud HTTP probándola de nuevo y comprueba si se informa del mismo error y los mismos detalles. Los detalles del error pueden tardar un poco en aparecer.
Como el servicio de ejemplo de este tutorial es de solo lectura y no activa ningún efecto secundario que complique las cosas, es seguro reproducir errores en producción. Sin embargo, en muchos servicios reales no será así: es posible que tengas que reproducir errores en un entorno de prueba o limitar este paso a una investigación local.
Reproducir el error establece el contexto para seguir trabajando. Por ejemplo, si los desarrolladores no pueden reproducir el error, es posible que se necesite una instrumentación adicional del servicio para investigar más a fondo.
Llevar a cabo un análisis de causas
El análisis de la causa raíz es un paso importante para solucionar problemas de forma eficaz y asegurarte de que resuelves el problema en lugar de un síntoma.
Anteriormente en este tutorial, has reproducido el problema en Cloud Run, lo que confirma que el problema está activo cuando el servicio está alojado en Cloud Run. Ahora, reproduce el problema de forma local para determinar si se limita al código o si solo se produce en el alojamiento de producción.
Si no has usado Docker CLI de forma local con Container Registry, autentícalo con gcloud:
gcloud auth configure-docker
Para ver otras opciones, consulta Métodos de autenticación de Container Registry.
Si el nombre de la imagen de contenedor usada más recientemente no está disponible, la descripción del servicio tiene la información de la imagen de contenedor implementada más recientemente:
gcloud run services describe hello-service
Busca el nombre de la imagen del contenedor en el objeto
spec
. Un comando más específico puede obtenerlo directamente:gcloud run services describe hello-service \ --format="value(spec.template.spec.containers.image)"
Este comando muestra el nombre de una imagen de contenedor, como
gcr.io/PROJECT_ID/hello-service
.Extrae la imagen de contenedor de Container Registry a tu entorno. Este paso puede tardar varios minutos, ya que se descarga la imagen de contenedor:
docker pull gcr.io/PROJECT_ID/hello-service
Las actualizaciones posteriores de la imagen de contenedor que reutilicen este nombre se podrán recuperar con el mismo comando. Si te saltas este paso, el comando
docker run
de abajo extraerá una imagen de contenedor si no hay ninguna en la máquina local.Ejecuta el código localmente para confirmar que el problema no es exclusivo de Cloud Run:
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
Desglosando los elementos del comando anterior,
- El servicio usa la variable de entorno
PORT
para determinar el puerto en el que debe escuchar dentro del contenedor. - El comando
run
inicia el contenedor. De forma predeterminada, se usa el comando de punto de entrada definido en el Dockerfile o en una imagen de contenedor principal. - La marca
--rm
elimina la instancia del contenedor al salir. - La marca
-e
asigna un valor a una variable de entorno.-e PORT=$PORT
propaga la variablePORT
del sistema local al contenedor con el mismo nombre de variable. - La marca
-p
publica el contenedor como un servicio disponible en localhost en el puerto 9000. Las solicitudes a localhost:9000 se enrutarán al contenedor en el puerto 8080. Esto significa que la salida del servicio sobre el número de puerto en uso no coincidirá con la forma en que se accede al servicio. - El último argumento,
gcr.io/PROJECT_ID/hello-service
, es una imagen de contenedortag
, una etiqueta legible por humanos para el identificador de hash sha256 de una imagen de contenedor. Si no está disponible localmente, Docker intenta obtener la imagen de un registro remoto.
En el navegador, abre http://localhost:9000. Comprueba la salida del terminal para ver si hay mensajes de error que coincidan con los de {ops_name}}.
Si el problema no se puede reproducir de forma local, puede que sea exclusivo del entorno de Cloud Run. Consulta la guía de solución de problemas de Cloud Run para ver áreas específicas que puedes investigar.
En este caso, el error se reproduce de forma local.
- El servicio usa la variable de entorno
Ahora que se ha confirmado que el error persiste y que lo provoca el código de servicio en lugar de la plataforma de alojamiento, es el momento de investigar el código más a fondo.
Para los fines de este tutorial, es seguro asumir que el código del contenedor y el código del sistema local son idénticos.
Vuelve a consultar el rastreo de pila del informe de errores y compáralo con el código para encontrar las líneas específicas que fallan.
Node.js
Busca el origen del mensaje de error en el archivoindex.js
alrededor del número de línea que se indica en el seguimiento de pila que se muestra en los registros:
Python
Busca el origen del mensaje de error en el archivomain.py
alrededor del número de línea que se indica en el seguimiento de pila que se muestra en los registros:
Go
Busca el origen del mensaje de error en el archivo main.go
alrededor del número de línea que se indica en el seguimiento de pila que se muestra en los registros:
Java
Busca el origen del mensaje de error en el archivo App.java
en torno al número de línea indicado en el seguimiento de pila que se muestra en los registros:
Al examinar este código, se llevan a cabo las siguientes acciones cuando no se define la variable de entorno NAME
:
- Se registra un error en Google Cloud Observability
- Se envía una respuesta de error HTTP
El problema se debe a que falta una variable, pero la causa principal es más específica: el cambio de código que añade la dependencia fija de una variable de entorno no incluye los cambios relacionados en los scripts de implementación ni en la documentación de los requisitos de tiempo de ejecución.
Corregir la causa principal
Ahora que hemos recogido el código y hemos identificado la posible causa principal, podemos tomar medidas para solucionarlo.
Comprueba si el servicio funciona localmente con el entorno
NAME
disponible:Ejecuta el contenedor de forma local con la variable de entorno añadida:
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ -e NAME="Local World!" \ gcr.io/PROJECT_ID/hello-service
En el navegador, ve a http://localhost:9000.
Verás el mensaje "Hello Local World!" en la página.
Modifica el entorno del servicio de Cloud Run en ejecución para incluir esta variable:
Ejecuta el comando de actualización de servicios para añadir una variable de entorno:
gcloud run services update hello-service \ --set-env-vars NAME=Override
Espera unos segundos mientras Cloud Run crea una nueva revisión basada en la revisión anterior con la nueva variable de entorno añadida.
Confirma que el servicio ya funciona:
- En el navegador, ve a la URL del servicio de Cloud Run.
- Verás el mensaje "Hello Override!" en la página.
- Comprueba que no aparezcan mensajes ni errores inesperados en Cloud Logging o Error Reporting.
Mejorar la velocidad de solución de problemas en el futuro
En este ejemplo de problema de producción, el error estaba relacionado con la configuración operativa. Se han realizado cambios en el código para minimizar el impacto de este problema en el futuro.
- Mejorar el registro de errores para que incluya detalles más específicos.
- En lugar de devolver un error, haz que el servicio vuelva a un valor predeterminado seguro. Si el uso de un valor predeterminado representa un cambio en la funcionalidad normal, utiliza un mensaje de advertencia para monitorizarlo.
Vamos a eliminar la variable de entorno NAME
como dependencia obligatoria.
Quita el código de gestión de
NAME
:Node.js
Python
Go
Java
Añade un código nuevo que defina un valor alternativo:
Node.js
Python
Go
Java
Prueba de forma local volviendo a compilar y ejecutar el contenedor en los casos de configuración afectados:
Node.js
docker build --tag gcr.io/PROJECT_ID/hello-service .
Python
docker build --tag gcr.io/PROJECT_ID/hello-service .
Go
docker build --tag gcr.io/PROJECT_ID/hello-service .
Java
mvn compile jib:build
Comprueba que la variable de entorno
NAME
sigue funcionando:PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ -e NAME="Robust World" \ gcr.io/PROJECT_ID/hello-service
Confirma que el servicio funciona sin la variable
NAME
:PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
Si el servicio no devuelve ningún resultado, confirma que al eliminar el código en el primer paso no se han eliminado líneas adicionales, como las que se usan para escribir la respuesta.
Para ello, vuelve a la sección Implementar el código.
Cada despliegue en un servicio crea una revisión nueva y empieza a servir tráfico automáticamente cuando está listo.
Para borrar las variables de entorno definidas anteriormente, sigue estos pasos:
gcloud run services update hello-service --clear-env-vars
Añade la nueva función del valor predeterminado a la cobertura de pruebas automatizadas del servicio.
Buscar otros problemas en los registros
Es posible que veas otros problemas en el visualizador de registros de este servicio. Por ejemplo, una llamada al sistema no compatible aparecerá en los registros como "Container Sandbox Limitation".
Por ejemplo, los servicios de Node.js a veces generan este mensaje de registro:
Container Sandbox Limitation: Unsupported syscall statx(0xffffff9c,0x3e1ba8e86d88,0x0,0xfff,0x3e1ba8e86970,0x3e1ba8e86a90). Please, refer to https://gvisor.dev/c/linux/amd64/statx for more information.
En este caso, la falta de compatibilidad no afecta al servicio de ejemplo hello-service.
Solución de problemas de Terraform
Si tienes alguna duda o necesitas ayuda para solucionar problemas relacionados con Terraform, consulta la sección Solución de problemas de validación de políticas de Terraform o ponte en contacto con el equipo de Asistencia de Terraform.