1. Introducción
Puedes usar Flujos de trabajo 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, los productos sin servidores, como Cloud Functions y Cloud Run, y las llamadas a las APIs externas para crear aplicaciones flexibles sin servidores.
Workflows no requiere administración de infraestructura y escala sin problemas con la demanda, incluida la reducción vertical 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. Más específicamente, conectarás dos servicios públicos de Cloud Functions, un servicio privado de Cloud Run y una API de HTTP pública externa en un flujo de trabajo.
Qué aprenderás
- Conceptos básicos de los flujos de trabajo.
- Cómo conectar Cloud Functions públicas con Workflows
- Cómo conectar servicios privados de Cloud Run con Workflows
- Cómo conectar APIs 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 indica cómo cerrar los recursos para que no se te facture 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 está compuesto por una serie de pasos descritos con la sintaxis de Workflows basada en YAML. Esta es la definición del flujo de trabajo. Para obtener una explicación detallada de la sintaxis de YAML de Workflows, consulta la página Referencia de sintaxis.
Cuando se crea un flujo de trabajo, se implementa, lo que lo deja listo para su ejecución. 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 flujos de trabajo son independientes, y el producto admite una gran cantidad de ejecuciones simultáneas.
Cómo habilitar servicios
En este codelab, conectarás Cloud Functions y los servicios de Cloud Run con flujos de trabajo. 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 aleatorios 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 lo muestra en formato JSON al llamador.
La función depende de Flask para el procesamiento de HTTP y debemos agregarlo como una 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 solicitudes no autenticadas permitidas con este comando:
gcloud functions deploy randomgen \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Una vez que se implementa la función, puedes ver la URL de la función en la propiedad url
que se muestra en la consola o con el comando gcloud functions describe
.
También puedes visitar esa URL de la función con el siguiente comando curl
:
curl $(gcloud functions describe randomgen --format='value(url)')
La función está lista para el flujo de trabajo.
5. Implementa la 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 en formato JSON al llamador.
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 solicitudes no autenticadas permitidas con este comando:
gcloud functions deploy multiply \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Una vez que se implemente la función, también podrás visitar esa URL con el siguiente comando curl
:
curl $(gcloud functions describe multiply --format='value(url)') \ -X POST \ -H "content-type: application/json" \ -d '{"input": 5}'
La función está lista para el flujo de trabajo.
6. Cómo conectar dos funciones de 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 aleatorio de la primera función y lo pasas a la segunda. 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 que se ejecute el flujo de trabajo, puedes pasar el ID de ejecución que se proporcionó en el paso anterior para ver el resultado:
gcloud workflows executions describe <your-execution-id> --workflow workflow
El resultado incluirá result
y state
:
result: '{"body":{"multiplied":108},"code":200 ... } ... state: SUCCEEDED
7. Cómo conectar 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 como esta:
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 y, luego, 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 alimenta el resultado de la función multiplicar a una llamada de función de registro en math.js
.
La IU te guiará para editar e implementar el flujo de trabajo. Una vez que se implemente, 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 en 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 pasado.
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 la variable de entorno 0.0.0.0
y PORT
, de ahí el código anterior.
Cuando recibe una solicitud HTTP, esta función extrae el input
del cuerpo JSON, llama a math.floor y 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 que se compile 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
Para poder configurar Workflows para que llame al servicio privado de Cloud Run, debes crear una cuenta de servicio para que la use Workflows:
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}
Actualiza 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, puedes consultar 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 los flujos de trabajo.
- Cómo conectar Cloud Functions públicas con Workflows
- Cómo conectar servicios privados de Cloud Run con Workflows
- Cómo conectar APIs HTTP externas con Workflows