1. Introducción
Puedes usar Workflows para crear flujos de trabajo sin servidores que vinculen una serie de tareas sin servidores en el orden que definas. Puedes combinar la potencia de las APIs de Google Cloud, productos sin servidores como Cloud Functions y Cloud Run, y llamadas a APIs externas para crear aplicaciones flexibles sin servidores.
Los flujos de trabajo no requieren administración de infraestructura y escalan sin problemas con la demanda, incluida la reducción de escala a cero. Con su modelo de precios de pago por uso, solo pagas por el tiempo de ejecución.
En este codelab, aprenderás a conectar varios servicios de Google Cloud y APIs de HTTP externas con Workflows. Específicamente, conectarás dos servicios públicos de Cloud Functions, uno privado de Cloud Run y una API de HTTP externa y pública, a un flujo de trabajo.
Qué aprenderás
- Conceptos básicos de Workflows
- Cómo conectar Cloud Functions públicas con Workflows
- Cómo conectar servicios privados de Cloud Run con Workflows.
- Cómo conectar APIs de HTTP externas con Workflows.
2. Configuración y requisitos
Configuración del entorno de autoaprendizaje
- Accede a la consola de Cloud y crea un proyecto nuevo o reutiliza uno existente. (Si todavía no tienes una cuenta de Gmail o de G Suite, debes crear una).
Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID
.
- A continuación, deberás habilitar la facturación en la consola de Cloud para usar los recursos de Google Cloud recursos.
Ejecutar este codelab no debería costar mucho, tal vez nada. Asegúrate de seguir las instrucciones de la sección “Realiza una limpieza” en la que se aconseja cómo cerrar recursos para no incurrir en facturación más allá de este instructivo. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de $300.
Inicia Cloud Shell
Si bien Google Cloud y Spanner se pueden operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.
En GCP Console, haga clic en el ícono de Cloud Shell en la barra de herramientas superior derecha:
El aprovisionamiento y la conexión al entorno deberían tomar solo unos minutos. Cuando termine el proceso, debería ver algo como lo siguiente:
Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitarás. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Puedes realizar todo tu trabajo en este lab usando simplemente un navegador.
3. Descripción general de los flujos de trabajo
Conceptos básicos
Un flujo de trabajo consta de una serie de pasos descritos mediante la sintaxis basada en YAML de flujos de trabajo. Esta es la definición del flujo de trabajo. Para obtener una explicación detallada de la sintaxis de YAML de los flujos de trabajo, consulta la página Referencia de la sintaxis.
Cuando se crea un flujo de trabajo, se implementa, lo que hace que el flujo de trabajo esté listo para ejecutarse. Una ejecución es una ejecución única de la lógica que se incluye en la definición de un flujo de trabajo. Todas las ejecuciones de los flujos de trabajo son independientes y el producto admite una gran cantidad de ejecuciones simultáneas.
Habilitar servicios
En este codelab, conectarás Cloud Functions y servicios de Cloud Run con Workflows. También usarás Cloud Build y Cloud Storage durante la compilación de servicios.
Habilita todos los servicios necesarios con el siguiente comando:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
En el siguiente paso, conectarás dos Cloud Functions en un flujo de trabajo.
4. Implementa la primera Cloud Function
La primera función es un generador de números al azar en Python.
Crea un directorio para el código de la función y navega hasta él:
mkdir ~/randomgen cd ~/randomgen
Crea un archivo main.py
en el directorio con el siguiente contenido:
import random, json from flask import jsonify def randomgen(request): randomNum = random.randint(1,100) output = {"random":randomNum} return jsonify(output)
Cuando recibe una solicitud HTTP, esta función genera un número aleatorio entre 1 y 100 y le muestra al emisor en formato JSON.
La función se basa en Flask para el procesamiento de HTTP y debemos agregarlo como dependencia. Las dependencias en Python se administran con pip y se expresan en un archivo de metadatos llamado requirements.txt
.
Crea un archivo requirements.txt
en el mismo directorio con el siguiente contenido:
flask>=1.0.2
Implementa la función con un activador HTTP y con las solicitudes no autenticadas permitidas con este comando:
gcloud functions deploy randomgen \ --runtime python37 \ --trigger-http \ --allow-unauthenticated
Una vez que se implemente la función, podrás ver su URL en la propiedad httpsTrigger.url
que se muestra en la consola o con el comando gcloud functions describe
.
También puedes visitar la URL de la función con el siguiente comando curl
:
curl $(gcloud functions describe randomgen --format='value(httpsTrigger.url)')
La función está lista para el flujo de trabajo.
5. Implementa una segunda Cloud Function
La segunda función es un multiplicador. Multiplica la entrada recibida por 2.
Crea un directorio para el código de la función y navega hasta él:
mkdir ~/multiply cd ~/multiply
Crea un archivo main.py
en el directorio con el siguiente contenido:
import random, json from flask import jsonify def multiply(request): request_json = request.get_json() output = {"multiplied":2*request_json['input']} return jsonify(output)
Cuando recibe una solicitud HTTP, esta función extrae el input
del cuerpo JSON, lo multiplica por 2 y lo muestra al emisor en formato JSON.
Crea el mismo archivo requirements.txt
en el mismo directorio con el siguiente contenido:
flask>=1.0.2
Implementa la función con un activador HTTP y con las solicitudes no autenticadas permitidas con este comando:
gcloud functions deploy multiply \ --runtime python37 \ --trigger-http \ --allow-unauthenticated
Una vez que se implementa la función, también puedes visitar esa URL de la función con el siguiente comando curl
:
curl $(gcloud functions describe multiply --format='value(httpsTrigger.url)') \ -X POST \ -H "content-type: application/json" \ -d '{"input": 5}'
La función está lista para el flujo de trabajo.
6. Conecta dos Cloud Functions
En el primer flujo de trabajo, conecta las dos funciones.
Crea un archivo workflow.yaml
con el siguiente contenido.
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - returnResult: return: ${multiplyResult}
En este flujo de trabajo, obtienes un número al azar de la primera función y lo pasas a la segunda función. El resultado es el número aleatorio multiplicado.
Implementa el primer flujo de trabajo:
gcloud workflows deploy workflow --source=workflow.yaml
Ejecuta el primer flujo de trabajo:
gcloud workflows execute workflow
Una vez ejecutado el flujo de trabajo, puedes ver el resultado si pasas el ID de ejecución proporcionado en el paso anterior:
gcloud workflows executions describe <your-execution-id> --workflow workflow
El resultado incluirá result
y state
:
result: '{"body":{"multiplied":108},"code":200 ... } ... state: SUCCEEDED
7. Conecta una API de HTTP externa
A continuación, conectarás math.js como un servicio externo en el flujo de trabajo.
En math.js, puedes evaluar expresiones matemáticas de la siguiente manera:
curl https://api.mathjs.org/v4/?'expr=log(56)'
Esta vez, usarás la consola de Cloud para actualizar nuestro flujo de trabajo. Busca Workflows
en la consola de Google Cloud:
Busca tu flujo de trabajo y haz clic en la pestaña Definition
:
Edita la definición del flujo de trabajo e incluye una llamada a math.js
.
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - returnResult: return: ${logResult}
El flujo de trabajo ahora envía el resultado de la función de multiplicación a una llamada a función de registro en math.js
.
La IU te guiará para editar e implementar el flujo de trabajo. Una vez implementada, haz clic en Execute
para ejecutar el flujo de trabajo. Verás los detalles de la ejecución:
Observa el código de estado 200
y un body
con el resultado de la función de registro.
Acabas de integrar un servicio externo a nuestro flujo de trabajo. ¡Genial!
8. Implementa un servicio de Cloud Run
En la última parte, finaliza el flujo de trabajo con una llamada a un servicio privado de Cloud Run. Esto significa que el flujo de trabajo debe autenticarse para llamar al servicio de Cloud Run.
El servicio de Cloud Run muestra el math.floor
del número que se pasó.
Crea un directorio para el código de servicio y navega hasta él:
mkdir ~/floor cd ~/floor
Crea un archivo app.py
en el directorio con el siguiente contenido:
import json import logging import os import math from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['POST']) def handle_post(): content = json.loads(request.data) input = float(content['input']) return f"{math.floor(input)}", 200 if __name__ != '__main__': # Redirect Flask logs to Gunicorn logs gunicorn_logger = logging.getLogger('gunicorn.error') app.logger.handlers = gunicorn_logger.handlers app.logger.setLevel(gunicorn_logger.level) app.logger.info('Service started...') else: app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run implementa contenedores, por lo que necesitas un Dockerfile
y tu contenedor debe vincularse a las variables de entorno 0.0.0.0
y PORT
. Por eso, se usa el código anterior.
Cuando recibe una solicitud HTTP, esta función extrae el objeto input
del cuerpo JSON, llama a math.floor y le muestra el resultado al llamador.
En el mismo directorio, crea el siguiente Dockerfile
:
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
Compila el contenedor:
export SERVICE_NAME=floor gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
Una vez compilado el contenedor, impleméntalo en Cloud Run. Observa la marca no-allow-unauthenticated
. Esto garantiza que el servicio solo acepte llamadas autenticadas:
gcloud run deploy ${SERVICE_NAME} \ --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \ --platform managed \ --no-allow-unauthenticated
Una vez implementado, el servicio está listo para el flujo de trabajo.
9. Conecta el servicio de Cloud Run
Antes de configurar Workflows para que llame al servicio privado de Cloud Run, debes crear una cuenta de servicio para que Workflows la use:
export SERVICE_ACCOUNT=workflows-sa gcloud iam service-accounts create ${SERVICE_ACCOUNT}
Otorga el rol run.invoker
a la cuenta de servicio. Esto permitirá que la cuenta de servicio llame a los servicios autenticados de Cloud Run:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role "roles/run.invoker"
Actualiza la definición del flujo de trabajo en workflow.yaml
para incluir el servicio de Cloud Run. Observa que también incluyes el campo auth
para asegurarte de que Workflows pase el token de autenticación en sus llamadas al servicio de Cloud Run:
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - floorFunction: call: http.post args: url: https://floor-<random-hash>.run.app auth: type: OIDC body: input: ${logResult.body} result: floorResult - returnResult: return: ${floorResult}
Actualizar el flujo de trabajo Esta vez, pasa la cuenta de servicio:
gcloud workflows deploy workflow \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Ejecuta el flujo de trabajo:
gcloud workflows execute workflow
En unos segundos, podrás observar la ejecución del flujo de trabajo para ver el resultado:
gcloud workflows executions describe <your-execution-id> --workflow workflow
El resultado incluirá un número entero result
y state
:
result: '{"body":"5","code":200 ... } ... state: SUCCEEDED
10. ¡Felicitaciones!
Felicitaciones por completar el codelab.
Temas abordados
- Conceptos básicos de Workflows
- Cómo conectar Cloud Functions públicas con Workflows
- Cómo conectar servicios privados de Cloud Run con Workflows.
- Cómo conectar APIs de HTTP externas con Workflows.