Instructivo para usar flujos de trabajo con Cloud Run y Cloud Run Functions

En este instructivo, se muestra cómo usar Workflows para vincular una serie de servicios. Si conectas dos servicios de HTTP públicos con Cloud Run Functions, una API de REST externa y un servicio privado de Cloud Run, puedes crear una aplicación flexible y sin servidores.

Objetivos

En este instructivo, usarás Google Cloud CLI para crear un solo flujo de trabajo y conectar un servicio a la vez.

  1. Implementa dos Cloud Run Functions: la primera función genera un número aleatorio y, luego, lo pasa a la segunda función, que lo multiplica.
  2. Con Workflows, conecta las dos funciones de HTTP. Ejecuta el flujo de trabajo para que se devuelva un resultado que, luego, se pasa a una API externa.
  3. Con Workflows, conecta una API de HTTP externa que devuelva el log de un número determinado. Ejecuta el flujo de trabajo para que se devuelva un resultado que, luego, se pasa a un servicio de Cloud Run.
  4. Implementa 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 una descripción general del proceso y una visualización del flujo de trabajo final:

Visualización de los flujos de trabajo

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.

Es posible que los usuarios nuevos de Google Cloud cumplan con los requisitos para acceder a una prueba gratuita.

Antes de comenzar

Es posible que las restricciones de seguridad que define tu organización no te permitan completar los siguientes pasos. Para obtener información sobre la solución de problemas, consulta Desarrolla aplicaciones en un entorno de Google Cloud restringido.

  1. Accede a tu cuenta de Google Cloud . Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. Instala Google Cloud CLI.

  3. Si usas un proveedor de identidad externo (IdP), primero debes acceder a la gcloud CLI con tu identidad federada.

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

    gcloud init
  5. Crea o selecciona un Google Cloud proyecto.

    Roles necesarios para seleccionar o crear un proyecto

    • Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
    • Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (roles/resourcemanager.projectCreator), que contiene el permiso resourcemanager.projects.create. Obtén más información para otorgar roles.
    • Crea un proyecto de Google Cloud :

      gcloud projects create PROJECT_ID

      Reemplaza PROJECT_ID por un nombre para el proyecto Google Cloud que estás creando.

    • Selecciona el proyecto Google Cloud que creaste:

      gcloud config set project PROJECT_ID

      Reemplaza PROJECT_ID por el nombre de tu Google Cloud proyecto.

  6. Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .

  7. Habilita las APIs de Artifact Registry, Cloud Build, Cloud Run, Cloud Run Functions, Cloud Storage y Workflows:

    Roles necesarios para habilitar las APIs

    Para habilitar las APIs, necesitas el rol de IAM de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin), que contiene el permiso serviceusage.services.enable. Obtén más información para otorgar roles.

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

  9. Si usas un proveedor de identidad externo (IdP), primero debes acceder a la gcloud CLI con tu identidad federada.

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

    gcloud init
  11. Crea o selecciona un Google Cloud proyecto.

    Roles necesarios para seleccionar o crear un proyecto

    • Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
    • Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (roles/resourcemanager.projectCreator), que contiene el permiso resourcemanager.projects.create. Obtén más información para otorgar roles.
    • Crea un proyecto de Google Cloud :

      gcloud projects create PROJECT_ID

      Reemplaza PROJECT_ID por un nombre para el proyecto Google Cloud que estás creando.

    • Selecciona el proyecto Google Cloud que creaste:

      gcloud config set project PROJECT_ID

      Reemplaza PROJECT_ID por el nombre de tu Google Cloud proyecto.

  12. Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .

  13. Habilita las APIs de Artifact Registry, Cloud Build, Cloud Run, Cloud Run Functions, Cloud Storage y Workflows:

    Roles necesarios para habilitar las APIs

    Para habilitar las APIs, necesitas el rol de IAM de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin), que contiene el permiso serviceusage.services.enable. Obtén más información para otorgar roles.

    gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.googleapis.com
  14. Actualiza los componentes de la CLI de Google Cloud:
    gcloud components update
  15. Si ejecutas comandos dentro de Cloud Shell, ya estás autenticado con gcloud CLI, de lo contrario, accede con tu cuenta:
    gcloud auth login
  16. Establece la ubicación predeterminada que se usa en este instructivo:
    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}

    Reemplaza REGION por la ubicación de Workflows compatible que prefieras.

  17. Si eres el creador del proyecto, se te otorga el rol de propietario básico (roles/owner). De forma predeterminada, este rol de Identity and Access Management (IAM) incluye los permisos necesarios para obtener acceso completo a la mayoría de los recursos de Google Cloud y puedes omitir este paso.

    Si no eres el creador del proyecto, se deben otorgar los permisos necesarios en el proyecto a la principal correspondiente. Por ejemplo, una principal puede ser una Cuenta de Google (para usuarios finales) o una cuenta de servicio (para aplicaciones y cargas de trabajo de procesamiento). Para obtener más información, consulta la página Roles y permisos para el destino del evento.

    Permisos necesarios

    Si quieres obtener los permisos que necesitas para completar el instructivo, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:

    Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

    También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

  18. Cuando implementas tu flujo de trabajo, lo asocias a una cuenta de servicio especificada. Crea una cuenta de servicio para que Workflows la use:
    export SERVICE_ACCOUNT=workflows-sa
    gcloud iam service-accounts create ${SERVICE_ACCOUNT}
  19. Todos los servicios de Cloud Run se implementan de forma privada de forma predeterminada y solo pueden llamarlos los propietarios del proyecto, los editores del proyecto, los administradores de Cloud Run y los invocadores de Cloud Run. Para permitir que la cuenta de servicio llame a un servicio autenticado de Cloud Run, otorga 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"

Implementa la primera Cloud Run Function

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

  1. Crea un directorio llamado randomgen y cámbialo, como se indica a continuación:

    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. Si deseas admitir una dependencia en Flask para el procesamiento de HTTP, crea un archivo de texto destinado al administrador de paquetes pip. Asígnale el nombre requirements.txt y agrega lo siguiente:

    flask>=1.0.2
    functions-framework==3.0.0
  4. Implementa la función con un activador de HTTP y permite el acceso no autenticado:

    gcloud functions deploy randomgen-function \
        --gen2 \
        --runtime python310 \
        --entry-point=randomgen \
        --trigger-http \
        --allow-unauthenticated

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

  5. Una vez que se implementa la función randomgen, puedes confirmar la propiedad httpsTrigger.url:

    gcloud functions describe randomgen-function \
        --gen2 \
        --format="value(serviceConfig.uri)"
  6. Guarda la URL. Deberás agregarlo a tu archivo fuente de flujo de trabajo en ejercicios posteriores.

  7. Puedes probar la función con el siguiente comando curl:

    curl $(gcloud functions describe randomgen-function \
        --gen2 \
        --format="value(serviceConfig.uri)")

    Se genera y se devuelve un número de forma aleatoria.

Implementa la segunda Cloud Run Function

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

  1. Regresa al directorio principal:

    cd ~
  2. Crea un directorio llamado multiply y cámbialo como se indica a continuación:

    mkdir ~/multiply
    cd ~/multiply
  3. 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)
  4. Si deseas admitir una dependencia en Flask para el procesamiento de HTTP, crea un archivo de texto destinado al administrador de paquetes pip. Asígnale el nombre requirements.txt y agrega lo siguiente:

    flask>=1.0.2
    functions-framework==3.0.0
  5. Implementa la función con un activador de HTTP y permite el acceso no autenticado:

    gcloud functions deploy multiply-function \
        --gen2 \
        --runtime python310 \
        --entry-point=multiply \
        --trigger-http \
        --allow-unauthenticated

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

  6. Una vez que se implementa la función multiply, puedes confirmar la propiedad httpsTrigger.url:

    gcloud functions describe multiply-function \
        --gen2\
        --format="value(serviceConfig.uri)"
  7. Guarda la URL. Deberás agregarlo a tu archivo fuente de flujo de trabajo en ejercicios posteriores.

  8. Puedes probar la función con el siguiente comando curl:

    curl -X POST MULTIPLY_FUNCTION_URL \
        -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
        -H "Content-Type: application/json" \
        -d '{"input": 5}'

    Se debería devolver el número 10.

Conecta las dos funciones de Cloud Run en un flujo de trabajo

Un flujo de trabajo está compuesto por una serie de pasos descritos con la sintaxis de Workflows, que se pueden 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. Regresa al directorio principal.

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

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - return_result:
        return: ${multiply_result}
    

    Este archivo fuente vincula las dos funciones de HTTP y muestra un resultado final.

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

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml \
        --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com

    Reemplaza WORKFLOW_NAME por un nombre para tu flujo de trabajo.

  4. Ejecuta el flujo de trabajo:

    gcloud workflows run WORKFLOW_NAME

    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 escalamiento rápido de Workflows permite una gran cantidad de ejecuciones simultáneas.

    Una vez que se ejecuta el flujo de trabajo, el resultado debería ser similar al siguiente:

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

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

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

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

  1. Edita el archivo fuente de tu flujo de trabajo y reemplázalo por el siguiente contenido:

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            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}
    

    Esto vincula el servicio de REST externo a las funciones de Cloud Run y devuelve un resultado final.

  2. Implementa el flujo de trabajo modificado:

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml \
        --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com

Implementa un servicio de Cloud Run

Implementa 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 cámbialo, como se indica a continuación:

    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 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 en el que puedas almacenar la imagen del contenedor de Docker:

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

    Reemplaza REPOSITORY por un nombre único para el repositorio.

  5. Compila la imagen del contenedor:

    export SERVICE_NAME=floor
    gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
  6. Implementa 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 \
        --no-allow-unauthenticated

Cuando veas la URL del servicio, se completará la implementación. Deberás especificar esa URL cuando actualices la definición del flujo de trabajo.

Conecta el servicio de Cloud Run en el flujo de trabajo

Actualiza tu flujo de trabajo existente y especifica la URL para el servicio de Cloud Run.

  1. Regresa al directorio principal.

    cd ~
  2. Edita el archivo fuente de tu flujo de trabajo y reemplázalo por el siguiente contenido:

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            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}
    
    • Reemplaza RANDOMGEN_FUNCTION_URL por la URL de tu función randomgen.
    • Reemplaza MULTIPLY_FUNCTION_URL por la URL de tu función multiply.
    • Reemplaza CLOUD_RUN_SERVICE_URL por la URL de servicio de Cloud Run.

    Esto conecta el servicio de Cloud Run en el flujo de trabajo. Ten en cuenta que la clave auth garantiza que se transmita un token de autenticación en la llamada al servicio de Cloud Run. Para obtener más información, consulta Realiza solicitudes autenticadas desde un flujo de trabajo.

  3. Implementa el flujo de trabajo modificado:

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml \
        --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com
  4. Ejecuta el flujo de trabajo final:

    gcloud workflows run WORKFLOW_NAME

    El resultado debe parecerse al siguiente:

    result: '{"floorResult":{"body":"4","code":200
      ...
      "logResult":{"body":"4.02535169073515","code":200
      ...
      "multiplyResult":{"body":{"multiplied":56},"code":200
      ...
      "randomResult":{"body":{"random":28},"code":200
      ...
    startTime: '2023-11-13T21:22:56.782669001Z'
    state: SUCCEEDED
    

¡Felicitaciones! Implementaste y ejecutaste un flujo de trabajo que conecta una serie de servicios.

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

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, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Elimina recursos de instructivos

¿Qué sigue?