En este instructivo, se muestra cómo un desarrollador de servicios puede solucionar problemas en un servicio dañado de Cloud Run for Anthos mediante herramientas de Stackdriver para el descubrimiento y un flujo de trabajo de desarrollo local con fines de investigación.
En este “caso de éxito” paso a paso complementario a la guía de solución de problemas, se usa un proyecto de muestra que genera errores de entorno de ejecución cuando se implementa a fin de encontrar y solucionar el problema.
Ten en cuenta que no puedes usar este instructivo con Cloud Run for Anthos en VMware debido a las limitaciones de compatibilidad de Google Cloud's operations suite.
Objetivos
- Escribir, compilar e implementar un servicio en Cloud Run for Anthos
- Usar Cloud Logging para identificar un error
- Recuperar la imagen de contenedor de Container Registry para un análisis de causa raíz
- Solucionar el servicio de “producción” y, luego, mejorarlo para mitigar futuros problemas
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Antes de comenzar
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
- Habilita la API de Cloud Run for Anthos
- Instala y, luego, inicializa Google Cloud CLI.
- Instala el componente
kubectl
:gcloud components install kubectl
- Actualiza los componentes, como se indica a continuación:
gcloud components update
- Si usas Cloud Run for Anthos, crea un clúster nuevo según las instrucciones de Configura Cloud Run for Anthos.
- Si usas Cloud Run for Anthos, instala curl para probar el servicio.
- Sigue las instrucciones para instalar Docker de forma local.
Configura los valores predeterminados de gcloud
Si deseas configurar gcloud con la configuración predeterminada para el servicio de Cloud Run for Anthos, haz lo siguiente:
Configura el proyecto predeterminado:
gcloud config set project PROJECT_ID
Reemplaza PROJECT_ID por el nombre del proyecto que creaste para este instructivo.
Configura gcloud para tu clúster:
gcloud config set run/platform gke gcloud config set run/cluster CLUSTER-NAME gcloud config set run/cluster_location REGION
Reemplaza lo siguiente:
- CLUSTER-NAME por el nombre que usaste para el clúster
- REGION por la ubicación de clúster compatible que elijas
Ensambla el código
Compila un nuevo servicio de saludo de Cloud Run for Anthos paso a paso. Te recordamos que este servicio crea un error de entorno de ejecución a propósito para el ejercicio de solución de problemas.
Crea un proyecto nuevo:
Node.js
Crea un proyecto de Node.js mediante la definición del paquete de servicio, las dependencias iniciales y algunas operaciones comunes.Crea un directorio
hello-service
nuevo:mkdir hello-service cd hello-service
Crea un proyecto de Node.js nuevo mediante la generación de un archivo
package.json
:npm init --yes npm install --save express@4
Abre el archivo
package.json
nuevo en tu editor y configura una secuencia de comandosstart
para ejecutarnode index.js
. Cuando termines, el archivo se verá de la siguiente manera:{ "name": "hello-service", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1" } }
Si continúas evolucionando este servicio más allá de este instructivo, considera completar la descripción, agregar el autor y evaluar la licencia. Para obtener más detalles, consulta la documentación de package.json.
Python
Crea un directorio
hello-service
nuevo:mkdir hello-service cd hello-service
Crea un archivo requirements.txt y copia tus dependencias en él:
Comienza a usarlo
Crea un directorio
hello-service
nuevo:mkdir hello-service cd hello-service
Crea un proyecto de Go mediante la inicialización de un módulo de Go nuevo:
go mod init example.com/hello-service
Puedes actualizar el nombre específico según lo desees; debes actualizar el nombre si el código se publica en un repositorio de código accesible en la Web.
Java
Crea un proyecto de Maven nuevo:
mvn archetype:generate \ -DgroupId=com.example \ -DartifactId=hello-service \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false
Copia las dependencias en tu lista de dependencias
pom.xml
(entre los elementos<dependencies>
):Copia la configuración de compilación en tu
pom.xml
(en los elementos<dependencies>
):
Crea un servicio HTTP para controlar las solicitudes entrantes:
Node.js
Python
Comienza a usarlo
Java
Crea un
Dockerfile
a fin de definir la imagen de contenedor que se usa para implementar el servicio:Node.js
Python
Comienza a usarlo
Java
En esta muestra, se usa Jib para compilar imágenes de Docker mediante herramientas de Java comunes. Jib optimiza las compilaciones de contenedores sin la necesidad de tener un Dockerfile o tener Docker instalado. Obtén más información sobre cómo compilar contenedores de Java con Jib.
Envía el código
El código de envío consta de tres pasos: compilar una imagen de contenedor con Cloud Build, subir la imagen de contenedor a Container Registry y, luego, implementar la imagen de contenedor en Cloud Run for Anthos.
Para enviar el código, haz lo siguiente:
Compila el contenedor y publica en Container Registry:
Node.js
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
En el ejemplo anterior, PROJECT_ID es el ID de tu proyecto de GCP. Puedes verificar el ID del proyecto actual con
gcloud config get-value project
.Si la operación se completa de manera correcta, deberías ver 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 puede volver a usarse si así se desea.
Python
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
En el ejemplo anterior, PROJECT_ID es el ID de tu proyecto de GCP. Puedes verificar el ID del proyecto actual con
gcloud config get-value project
.Si la operación se completa de manera correcta, deberías ver 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 puede volver a usarse si así se desea.
Comienza a usarlo
gcloud builds submit --tag gcr.io/PROJECT_ID/hello-service
En el ejemplo anterior, PROJECT_ID es el ID de tu proyecto de GCP. Puedes verificar el ID del proyecto actual con
gcloud config get-value project
.Si la operación se completa de manera correcta, deberías ver 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 puede volver a usarse si así se desea.
Java
mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/hello-service
En el ejemplo anterior, PROJECT_ID es el ID de tu proyecto de GCP. Puedes verificar el ID del proyecto actual con
gcloud config get-value project
.Si se ejecuta de forma correcta, deberías ver un mensaje de COMPILACIÓN EXITOSA. La imagen se almacena en Container Registry y puede volver a usarse si así se desea.
Ejecuta el comando siguiente para implementar tu app:
gcloud run deploy hello-service --image gcr.io/PROJECT_ID/hello-service
Reemplaza PROJECT_ID por el ID del proyecto de GCP.
hello-service
es el nombre de la imagen de contenedor y el nombre del servicio de Cloud Run for Anthos. Ten en cuenta que la imagen de contenedor se implementa en el servicio y en el clúster que configuraste con anterioridad en Configura gcloud.Espera hasta que finalice la implementación; esto puede tomar alrededor de medio minuto. Si la operación se completa de forma correcta, la línea de comandos mostrará la URL de servicio.
Haz una prueba
Prueba el servicio a fin de confirmar que lo implementaste de forma correcta. Las solicitudes deben fallar con un error HTTP 500 o 503 (miembros de la clase Errores de servidor 5xx). En este instructivo, se presenta la solución de problemas de esta respuesta de error.
Si el clúster está configurado con un dominio predeterminado enrutable, omite los pasos anteriores y, en su lugar, copia la URL en el navegador web.
Si no usas certificados TLS automáticos ni la asignación de dominios, no se te proporciona una URL navegable para el servicio.
En su lugar, usa la URL proporcionada y la dirección IP de la puerta de enlace de entrada del servicio para crear un comando curl
que pueda realizar solicitudes a tu servicio:
-
Para obtener la IP externa de la puerta de enlace de entrada de Istio, ejecuta lo siguiente:
kubectl get svc istio-ingress -n gke-system
El resultado se ve de la siguiente manera:NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) istio-ingress LoadBalancer XX.XX.XXX.XX pending 80:32380/TCP,443:32390/TCP,32400:32400/TCP
La EXTERNAL-IP del balanceador de cargas es la dirección IP que debes usar. Ejecuta un comando de
curl
con esta direcciónGATEWAY_IP
en la URL.curl -G -H "Host: SERVICE-DOMAIN" https://EXTERNAL-IP/
Reemplaza SERVICE-DOMAIN por el dominio asignado predeterminado del servicio. Puedes obtenerlo si tomas la URL predeterminada y quitas el protocolo
http://
.Consulta el mensaje de error HTTP 500 o HTTP 503.
Investiga el problema
Supongamos que el error HTTP 5xx que se encontró antes en Haz una prueba surgió como un error de entorno de ejecución de producción. En este instructivo, se presenta un proceso formal para controlarlo. Aunque los procesos de resolución de errores de producción varían mucho, en este instructivo se presenta una secuencia particular de pasos para mostrar la aplicación de herramientas y técnicas útiles.
Para investigar este problema, trabajarás en estas fases:
- Recopilar más detalles sobre el error informado para respaldar una investigación más detallada y establecer una estrategia de mitigación
- Aliviar el impacto en el usuario cuando decidas realizar una corrección o una reversión a una versión que sepas que está en buen estado
- Reproducir el error para confirmar que se recopilaron los detalles correctos y que el error no es una falla única
- Realizar un análisis de causa raíz en el error para encontrar el código, la configuración o el proceso que creó este error
Al comienzo de la investigación, verás una URL, una marca de tiempo y el mensaje “Error interno del servidor”.
Recopila más detalles
Recopila más información sobre el problema para comprender qué sucedió y determinar los próximos pasos.
Usa las herramientas de Stackdriver disponibles para obtener más detalles:
Visualiza los registros para obtener más detalles.
Usa Cloud Logging para revisar la secuencia de operaciones que generaron el problema, incluidos los mensajes de error.
Revierte a una versión en buen estado
Si tienes una revisión que sabes que funciona, puedes revertir tu servicio para usarla. Por ejemplo, no podrás realizar una reversión en el nuevo servicio hello-service
que implementaste en este instructivo porque solo contiene una única revisión.
Para ubicar una revisión y revertir tu servicio, haz lo siguiente:
Reproduce el error
Con los detalles que obtuviste antes, confirma que el problema se produzca de manera coherente en las condiciones de prueba.
Vuelve a hacer una prueba; cuando la realices, envía la misma solicitud HTTP y verifica si se informan los mismos detalles y el mismo error. Es posible que los detalles del error tarden un poco en aparecer.
Debido a que el servicio de muestra de este instructivo es de solo lectura y no genera efectos secundarios complicados, es seguro reproducir errores en la producción. Sin embargo, para muchos servicios reales, este no será el caso: es posible que tengas que reproducir errores en un entorno de prueba o limitar este paso a la investigación local.
Reproducir el error establece el contexto para el trabajo futuro. Por ejemplo, si los desarrolladores no pueden reproducir el error, es posible que se requiera una instrumentación adicional del servicio.
Realiza un análisis de causa raíz
El análisis de la causa raíz es un paso importante en el proceso de solución de problemas eficaz, ya que te aseguras de solucionar el problema en lugar de un síntoma.
En un paso anterior de este instructivo, reprodujiste el problema en Cloud Run for Anthos, que confirma que el problema está activo cuando el servicio se aloja en Cloud Run for Anthos. Ahora, reproduce el problema de forma local para determinar si es un problema aislado del código o si solo aparece en el hosting de producción.
Si no usaste la CLI de Docker de forma local con Container Registry, autentícala con gcloud:
gcloud auth configure-docker
Para conocer enfoques alternativos, consulta Métodos de autenticación de Container Registry.
Si el nombre de la imagen del contenedor que usaste de forma más reciente no está disponible, la descripción del servicio contiene la información de la imagen del contenedor implementado más recientemente:
gcloud run services describe hello-service
Busca el nombre de la imagen del contenedor dentro del objeto
spec
. Con un comando más orientado puedes recuperarlo directamente:gcloud run services describe hello-service \ --format="value(spec.template.spec.containers.image)"
Este comando muestra un nombre de imagen de contenedor, como
gcr.io/PROJECT_ID/hello-service
.Extrae la imagen del contenedor de Container Registry a tu entorno. Este paso puede tomar varios minutos mientras se descarga la imagen del contenedor:
docker pull gcr.io/PROJECT_ID/hello-service
Las actualizaciones posteriores a la imagen del contenedor que vuelven a usar este nombre se pueden recuperar con el mismo comando. Si omites este paso, el comando
docker run
a continuación extrae una imagen de contenedor si no está presente en la máquina local.Realiza una ejecución local para confirmar que el problema no es exclusivo de Cloud Run for Anthos:
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
A continuación, se muestra un desglose de los elementos del comando anterior:
- El servicio usa la variable de entorno
PORT
para determinar el puerto que se escuchará dentro del contenedor. - El comando
run
inicia el contenedor de forma predeterminada con el comando de punto de entrada definido en el Dockerfile o en una imagen de contenedor principal. - La marca
--rm
borra la instancia de contenedor cuando se sale. - 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 al localhost:9000 se enrutarán al contenedor en el puerto 8080. Esto significa que la salida del servicio sobre el número del puerto en uso no coincidirá con la forma en la que se accede al servicio. - El argumento final
gcr.io/PROJECT_ID/hello-service
es una ruta de acceso al repositorio que apunta a la última versión de la imagen de contenedor. Si no está disponible de forma local, Docker intenta recuperar la imagen de un registro remoto.
En tu navegador, abre http://localhost:9000. Verifica la salida de la terminal en busca de mensajes de error que coincidan con los de Google Cloud's operations suite.
Si el problema no se puede reproducir de forma local, puede ser exclusivo del entorno de Cloud Run for Anthos. Revisa la Guía de solución de problemas de Cloud Run for Anthos para conocer las áreas específicas que debes investigar.
En este caso, el error se reproduce de forma local.
- El servicio usa la variable de entorno
Ahora que el error está doblemente confirmado como persistente y provocado por el código de servicio en lugar de la plataforma de hosting, es hora de investigar el código con más detalle.
Para los fines de este instructivo, podemos suponer que el código dentro del contenedor y el código del sistema local son idénticos.
Node.js
Encuentra la fuente del mensaje de error en el archivoindex.js
alrededor del número de línea indicado en el seguimiento de pila que se muestra en los registros:
Python
Encuentra la fuente del mensaje de error en el archivomain.py
alrededor del número de línea indicado en el seguimiento de pila que se muestra en los registros:
Comienza a usarlo
Encuentra la fuente del mensaje de error en el archivo main.go
alrededor del número de línea indicado en el seguimiento de pila que se muestra en los registros:
Java
Encuentra la fuente del mensaje de error en el archivo App.java
alrededor del número de línea indicado en el seguimiento de pila que se muestra en los registros:
Si examinas este código, verás que se realizan las siguientes acciones si no se establece la variable de entorno NAME
:
- Se registra un error en Google Cloud's operations suite
- Se envía una respuesta de error HTTP
El problema se debe a una variable faltante, pero la causa raíz es más específica: el cambio de código que agregó una dependencia excesiva de una variable de entorno no incluyó cambios relacionados con la documentación de requisitos del entorno de ejecución y las secuencias de comandos de implementación.
Corrige la causa raíz
Ahora que recopilamos el código y, también, identificamos la posible causa raíz, podemos tomar medidas para solucionarlo.
Comprueba si el servicio funciona de manera local con el entorno
NAME
disponible:Ejecuta el contenedor de forma local con la variable de entorno agregada:
PORT=8080 && docker run --rm -e PORT=$PORT -p 9000:$PORT \ -e NAME="Local World!" \ gcr.io/PROJECT_ID/hello-service
Dirige tu navegador a http://localhost:9000.
Se mostrará “Hello Local World!” en la página.
Modifica el entorno de servicio de Cloud Run for Anthos en ejecución para incluir esta variable:
Ejecuta el comando de actualización de servicios con el parámetro
--update-env-vars
para agregar una variable de entorno:gcloud run services update hello-service \ --update-env-vars NAME=Override
Espera unos segundos mientras Cloud Run for Anthos crea una revisión nueva basada en la revisión anterior con la variable de entorno nueva agregada.
Confirma que el servicio ya se haya corregido:
- Dirige tu navegador a la URL de servicio de Cloud Run for Anthos.
- Se mostrará “Hello Override!” en la página.
- Verifica que no aparezcan mensajes o errores inesperados en Cloud Logging.
Mejora la velocidad de solución de problemas en el futuro
En este problema de producción de muestra, el error estaba relacionado con la configuración operativa. Hay cambios de código que minimizarán el impacto de este problema en el futuro.
- Mejora el registro de errores para incluir detalles más específicos.
- En lugar de mostrar un error, haz que el servicio vuelva a un valor predeterminado seguro. Si usar un valor predeterminado representa un cambio en la funcionalidad normal, usa un mensaje de advertencia para fines de supervisión.
Analicemos cómo quitar la variable de entorno NAME
como una dependencia excesiva.
Quita el código de control de
NAME
existente:Node.js
Python
Comienza a usarlo
Java
Agrega un código nuevo que establezca un valor de resguardo:
Node.js
Python
Comienza a usarlo
Java
Vuelve a compilar y ejecutar el contenedor en los casos de configuración afectados para realizar pruebas locales:
Node.js
docker build --tag gcr.io/PROJECT_ID/hello-service .
Python
docker build --tag gcr.io/PROJECT_ID/hello-service .
Comienza a usarlo
docker build --tag gcr.io/PROJECT_ID/hello-service .
Java
mvn compile jib:build
Confirma que la variable de entorno
NAME
aún funcione:PORT=8080 && docker run --rm -e $PORT -p 9000:$PORT \ -e NAME="Robust World" \ gcr.io/PROJECT_ID/hello-service
Confirma que el servicio funcione sin la variable
NAME
:PORT=8080 && docker run --rm -e $PORT -p 9000:$PORT \ gcr.io/PROJECT_ID/hello-service
Si el servicio no muestra un resultado, confirma que no se hayan quitado líneas adicionales en la eliminación del código en el primer paso, como las que se usan para escribir la respuesta.
Dirígete de nuevo a la sección Implementa el código para implementarlo.
Con cada implementación en un servicio se crea una revisión nueva y se comienza a entregar tráfico de manera automática cuando está lista.
Para borrar las variables de entorno establecidas antes, haz lo siguiente:
gcloud run services update hello-service --clear-env-vars
Agrega la funcionalidad nueva del valor predeterminado a la cobertura de prueba automática para el servicio.
Encuentra otros problemas en los registros
Es posible que veas otros problemas en el visor de registros de este servicio. Por ejemplo, una llamada al sistema no compatible aparecerá en los registros como “Limitación de la zona de pruebas del contenedor”.
Por ejemplo, los servicios de Node.js a veces dan como resultado 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 el servicio de muestra hello-service.
Realiza una limpieza
Si creaste un proyecto nuevo para este instructivo, bórralo. Si usaste un proyecto existente y deseas conservarlo sin los cambios que se agregaron en este instructivo, borra los recursos creados para el instructivo.
Borra el proyecto
La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.
Para borrar el proyecto, haga lo siguiente:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Borra los recursos del instructivo
Borra el servicio de Cloud Run for Anthos que implementaste en este instructivo:
gcloud run services delete SERVICE-NAME
En el ejemplo anterior, SERVICE-NAME es el nombre del servicio que elegiste.
También puedes borrar los servicios de Cloud Run for Anthos desde la consola de Google Cloud.
Quita las opciones de configuración predeterminadas de gcloud que agregaste durante la configuración del instructivo.
gcloud config unset run/platform gcloud config unset run/cluster gcloud config unset run/cluster_location
Quita la configuración del proyecto:
gcloud config unset project
Borra otros recursos de Google Cloud que creaste en este instructivo:
- Borra la imagen del contenedor llamada
gcr.io/<var>PROJECT_ID</var>/hello-service
de Container Registry. - Si creaste un clúster para este instructivo, bórralo
- Borra la imagen del contenedor llamada
¿Qué sigue?
- Obtén más información sobre cómo usar Cloud Logging a fin de obtener estadísticas sobre el comportamiento de producción.
- Para obtener más información sobre la solución de problemas de Cloud Run for Anthos, consulta (/anthos/run/docs/troubleshooting#sandbox).
- Explora arquitecturas de referencia, diagramas y prácticas recomendadas sobre Google Cloud. Consulta nuestro Cloud Architecture Center.