Tutorial de Workflows (1.ª gen.)


En este tutorial se explica cómo usar Workflows para vincular una serie de servicios. Si conectas dos servicios HTTP públicos (mediante funciones de Cloud Run), una API REST externa y un servicio de Cloud Run privado, puedes crear una aplicación flexible y sin servidor.

Objetivos

En este tutorial, usará Google Cloud CLI para crear un solo flujo de trabajo y conectar un servicio cada vez:

  1. Despliega dos servicios de funciones de Cloud Run: la primera función genera un número aleatorio y, a continuación, pasa ese número a la segunda función, que lo multiplica.
  2. Conecta las dos funciones HTTP mediante Workflows. Ejecuta el flujo de trabajo y devuelve un resultado que se envía a una API externa.
  3. Con Workflows, conecta una API HTTP externa que devuelva el log de un número determinado. Ejecuta el flujo de trabajo y devuelve un resultado que se transfiere a un servicio de Cloud Run.
  4. Despliega un servicio de Cloud Run que solo permita el acceso autenticado. El servicio devuelve el math.floor de un número determinado.
  5. Con Workflows, conecta el servicio de Cloud Run, ejecuta todo el flujo de trabajo y devuelve un resultado final.

En el siguiente diagrama se muestra un resumen del proceso y una visualización del flujo de trabajo final:

Visualización de flujos de trabajo

Costes

En este documento, se utilizan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costes basada en el uso previsto, utiliza la calculadora de precios.

Los usuarios nuevos Google Cloud pueden disfrutar de una prueba gratuita.

Antes de empezar

Es posible que las restricciones de seguridad definidas por tu organización te impidan completar los siguientes pasos. Para obtener información sobre cómo solucionar problemas, consulta el artículo Desarrollar aplicaciones en un entorno limitado Google Cloud .

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  4. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  5. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry, Cloud Build, Cloud Run functions, Cloud Run, Cloud Storage, and Workflows APIs:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com run.googleapis.com storage.googleapis.com workflows.googleapis.com
  8. Install the Google Cloud CLI.

  9. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  10. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  11. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Verify that billing is enabled for your Google Cloud project.

  13. Enable the Artifact Registry, Cloud Build, Cloud Run functions, Cloud Run, Cloud Storage, and Workflows APIs:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com run.googleapis.com storage.googleapis.com workflows.googleapis.com
  14. Actualiza los componentes de Google Cloud CLI:
    gcloud components update
  15. Si ejecutas comandos en Cloud Shell, ya te has autenticado con gcloud CLI. De lo contrario, inicia sesión con tu cuenta:
    gcloud auth login
  16. Crea una cuenta de servicio para que la usen los workflows:

    export SERVICE_ACCOUNT=workflows-sa
    gcloud iam service-accounts create ${SERVICE_ACCOUNT}

  17. Para permitir que la cuenta de servicio llame a servicios de Cloud Run autenticados, asigna el rol run.invoker a la cuenta de servicio de Workflows:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com" \
        --role "roles/run.invoker"

    Sustituye PROJECT_ID por el ID de tu proyecto. Google Cloud

  18. Define la ubicación predeterminada que se usará en este tutorial:
    gcloud config set project PROJECT_ID
    export REGION=REGION
    gcloud config set functions/region ${REGION}
    gcloud config set run/region ${REGION}
    gcloud config set workflows/location ${REGION}

    Sustituye REGION por la ubicación de Workflows admitida que quieras.

  19. Desplegar el primer servicio de Cloud Run Functions

    Después de recibir una solicitud HTTP, esta función HTTP genera un número aleatorio entre 1 y 100 y, a continuación, devuelve el número en formato JSON.

    1. Crea un directorio llamado randomgen y accede a él:

      mkdir ~/randomgen
      cd ~/randomgen
    2. Crea un archivo de texto con el nombre main.py que contenga el siguiente código de Python:

      import functions_framework
      import random
      from flask import jsonify
      
      
      @functions_framework.http
      def randomgen(request):
          randomNum = random.randint(1, 100)
          output = {"random": randomNum}
          return jsonify(output)
    3. Para admitir una dependencia de Flask para el procesamiento HTTP, crea un archivo de texto para el gestor de paquetes pip. Asigna el nombre de archivo requirements.txt y añade lo siguiente:

      flask>=1.0.2
      functions-framework==3.0.0
    4. Despliega la función con un activador HTTP y permite el acceso sin autenticar:

      gcloud functions deploy randomgen \
          --runtime python37 \
          --trigger-http \
          --allow-unauthenticated

    La función puede tardar unos minutos en implementarse. También puedes usar la interfaz de funciones de Cloud Run en la Google Cloud consola para desplegar la función.

    1. Una vez que se haya implementado la función, puede confirmar la propiedad httpsTrigger.url:

      gcloud functions describe randomgen
    2. Puedes probar la función con el siguiente comando curl:

      curl $(gcloud functions describe randomgen --format='value(httpsTrigger.url)')

      Se genera y se devuelve un número aleatorio.

    Desplegar el segundo servicio de Cloud Run Functions

    Después de recibir una solicitud HTTP, esta función HTTP extrae input del cuerpo JSON, lo multiplica por 2 y devuelve el resultado en formato JSON.

    1. Crea un directorio llamado multiply y accede a él:

      mkdir ~/multiply
      cd ~/multiply
    2. Crea un archivo de texto con el nombre main.py que contenga el siguiente código de Python:

      import functions_framework
      from flask import jsonify
      
      
      @functions_framework.http
      def multiply(request):
          request_json = request.get_json()
          output = {"multiplied": 2 * request_json['input']}
          return jsonify(output)
    3. Para admitir una dependencia de Flask para el procesamiento HTTP, crea un archivo de texto para el gestor de paquetes pip. Asigna el nombre de archivo requirements.txt y añade lo siguiente:

      flask>=1.0.2
      functions-framework==3.0.0
    4. Despliega la función con un activador HTTP y permite el acceso sin autenticar:

      gcloud functions deploy multiply \
          --runtime python37 \
          --trigger-http \
          --allow-unauthenticated

    La función puede tardar unos minutos en desplegarse.También puedes usar la interfaz de funciones de Cloud Run en la Google Cloud consola para desplegar la función.

    1. Una vez que se haya implementado la función, puede confirmar la propiedad httpsTrigger.url:

      gcloud functions describe multiply
    2. Puedes probar 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}'

      Debería devolver el número 10.

    Conectar los dos servicios de funciones de Cloud Run en un flujo de trabajo

    Un flujo de trabajo se compone de una serie de pasos descritos mediante la sintaxis de Workflows, que se puede escribir en formato YAML o JSON. Esta es la definición del flujo de trabajo. Para obtener una explicación detallada, consulta la página Referencia de sintaxis.

    1. Vuelve a tu directorio principal:

      cd ~
    2. Crea un archivo de texto con el nombre workflow.yaml que contenga lo siguiente:

      - randomgen_function:
          call: http.get
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - return_result:
          return: ${multiply_result}
      

      De esta forma, se vinculan las dos funciones HTTP y se devuelve un resultado final.

      .
    3. Después de crear el flujo de trabajo, puedes implementarlo para que esté listo para ejecutarse.

      gcloud workflows deploy WORKFLOW_NAME --source=workflow.yaml

      Sustituye WORKFLOW_NAME por el nombre que quieras darle al flujo de trabajo.

    4. Ejecuta el flujo de trabajo:

      gcloud workflows run WORKFLOW_NAME

      Una ejecución es una sola vez que se ejecuta la lógica contenida en la definición de un flujo de trabajo. Todas las ejecuciones de flujo de trabajo son independientes y el escalado rápido de Workflows permite un gran número de ejecuciones simultáneas.

      Una vez que se haya ejecutado el flujo de trabajo, la salida debería ser similar a la siguiente:

      result: '{"body":{"multiplied":120},"code":200,"headers":{"Alt-Svc":"h3-29=\":443\";
      ...
      startTime: '2021-05-05T14:17:39.135251700Z'
      state: SUCCEEDED
      ...
      

    Conectar un servicio REST público en el flujo de trabajo

    Actualiza tu flujo de trabajo y conecta una API REST pública (math.js) que pueda evaluar expresiones matemáticas. Por ejemplo, curl https://api.mathjs.org/v4/?'expr=log(56)'.

    Ten en cuenta que, como has desplegado tu flujo de trabajo, también puedes editarlo en la página Flujos de trabajo de la Google Cloud consola.

    1. Edita el archivo de origen de tu flujo de trabajo y sustitúyelo por el siguiente contenido:

      - randomgen_function:
          call: http.get
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - log_function:
          call: http.get
          args:
              url: https://api.mathjs.org/v4/
              query:
                  expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
          result: log_result
      - return_result:
          return: ${log_result}
      

      De esta forma, se vincula el servicio REST externo a los servicios de funciones de Cloud Run y se devuelve un resultado final.

    2. Despliega el flujo de trabajo modificado:

      gcloud workflows deploy WORKFLOW_NAME --source=workflow.yaml

    Desplegar un servicio de Cloud Run

    Despliega un servicio de Cloud Run que, tras recibir una solicitud HTTP, extrae input del cuerpo JSON, calcula su math.floor y devuelve el resultado.

    1. Crea un directorio llamado floor y accede a él:

      mkdir ~/floor
      cd ~/floor
    2. Crea un archivo de texto con el nombre app.py que contenga el siguiente código de Python:

      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)))

    3. En el mismo directorio, crea un archivo Dockerfile con el siguiente contenido:

      # 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

    4. Crea un repositorio estándar de Artifact Registry donde puedas almacenar tu imagen de contenedor Docker:

      gcloud artifacts repositories create REPOSITORY \
          --repository-format=docker \
          --location=${REGION}

      Sustituye REPOSITORY por un nombre único para el repositorio.

    5. Crea la imagen del contenedor:

      export SERVICE_NAME=floor
      gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
    6. Despliega la imagen de contenedor en Cloud Run y asegúrate de que solo acepte llamadas autenticadas:

      gcloud run deploy ${SERVICE_NAME} \
          --image ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}:latest \
          --platform managed \
          --no-allow-unauthenticated

    Cuando veas la URL del servicio, el despliegue se habrá completado. Deberá especificar esa URL al actualizar la definición del flujo de trabajo.

    Conectar el servicio de Cloud Run en el flujo de trabajo

    Actualiza el flujo de trabajo y especifica la URL del servicio de Cloud Run.

    1. Edita el archivo de origen de tu flujo de trabajo y sustitúyelo por el siguiente contenido:

      - randomgen_function:
          call: http.get
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
          result: randomgen_result
      - multiply_function:
          call: http.post
          args:
              url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
              body:
                  input: ${randomgen_result.body.random}
          result: multiply_result
      - log_function:
          call: http.get
          args:
              url: https://api.mathjs.org/v4/
              query:
                  expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
          result: log_result
      - floor_function:
          call: http.post
          args:
              url: CLOUD_RUN_SERVICE_URL
              auth:
                  type: OIDC
              body:
                  input: ${log_result.body}
          result: floor_result
      - create_output_map:
          assign:
            - outputMap:
                randomResult: ${randomgen_result}
                multiplyResult: ${multiply_result}
                logResult: ${log_result}
                floorResult: ${floor_result}
      - return_output:
          return: ${outputMap}
      

      Sustituye CLOUD_RUN_SERVICE_URL por la URL de tu servicio de Cloud Run.

      De esta forma, se conecta el servicio de Cloud Run en el flujo de trabajo. Ten en cuenta que la clave auth asegura que se transmita un token de autenticación en la llamada al servicio de Cloud Run. Para obtener más información, consulta el artículo Hacer solicitudes autenticadas desde un flujo de trabajo.

    2. Despliega el flujo de trabajo modificado:

      gcloud workflows deploy WORKFLOW_NAME \
          --source=workflow.yaml
    3. Ejecuta el flujo de trabajo final:

      gcloud workflows run WORKFLOW_NAME

      La salida debería ser similar a la siguiente:

      result: '{"Floor":{"body":"4","code":200
        ...
        "Log":{"body":"4.02535169073515","code":200
        ...
        "Multiply":{"body":{"multiplied":56},"code":200
        ...
        "Random":{"body":{"random":28},"code":200
        ...
      startTime: '2023-11-13T21:22:56.782669001Z'
      state: SUCCEEDED
      

    ¡Enhorabuena! Has desplegado y ejecutado un flujo de trabajo que conecta una serie de servicios entre sí.

    Para crear flujos de trabajo más complejos con expresiones, saltos condicionales, codificación o decodificación Base64, subflujos de trabajo y más, consulta la referencia de sintaxis de Workflows y la descripción general de la biblioteca estándar.

    Limpieza

    Si has creado un proyecto para este tutorial, elimínalo. Si has usado un proyecto y quieres conservarlo sin los cambios que has añadido en este tutorial, elimina los recursos creados para el tutorial.

    Eliminar el proyecto

    La forma más fácil de evitar que te cobren es eliminar el proyecto que has creado para el tutorial.

    Para ello, sigue las instrucciones que aparecen a continuación:

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Eliminar recursos del tutorial

    Siguientes pasos