Configurar la salida directa de VPC para funciones de segunda generación

La salida directa de VPC te permite enrutar el tráfico desde tu función de Cloud Run (2.ª gen.) directamente a tu red de VPC.

Limitaciones

  • La salida directa de VPC no está disponible para las funciones de primera generación.
  • No puedes usar la salida directa de VPC y los conectores de acceso a VPC sin servidor al mismo tiempo. Para obtener más información, consulta la sección Comparar la salida de VPC directa y los conectores de VPC.

Antes de empezar

  • Habilita la API Cloud Functions.
  • Instala Google Cloud CLI y, a continuación, inicialízala ejecutando gcloud init.
  • Actualiza los componentes de gcloud a la versión 545.0.0 o a una posterior:

    gcloud components update
    

  • Si aún no tienes una red de VPC en tu proyecto, crea una.

  • Opcional: Si tu función necesita acceder a las APIs y los servicios de Google mediante sus direcciones IP internas, habilita Acceso privado de Google en la subred que uses para la salida directa de VPC.

Configurar permisos de gestión de identidades y accesos

Para autorizar la salida directa de VPC, pide a tu administrador que conceda el rol Invocador de Cloud Run (roles/run.invoker) a la cuenta de servicio de tu función.

Asegúrate de que Cloud Run tenga acceso a la red de VPC mediante uno de los siguientes métodos:

  • Rol Agente de servicio de Cloud Run: de forma predeterminada, el agente de servicio de Cloud Run tiene el rol Agente de servicio de Cloud Run (roles/run.serviceAgent), que contiene los permisos necesarios.

  • Permisos personalizados: para tener un control más granular, concede al agente de servicio de Cloud Run los siguientes permisos adicionales en el proyecto:

    • compute.networks.get
    • compute.subnetworks.get
    • compute.subnetworks.use en el proyecto o en la subred específica
    • compute.addresses.get
    • compute.addresses.list
    • compute.addresses.create (solo es obligatorio para las subredes de pila dual con IPv6 externo)
    • compute.addresses.delete (obligatorio solo para subredes de doble pila con IPv6 externa)
    • compute.addresses.createInternal
    • compute.addresses.deleteInternal
    • compute.regionOperations.get
  • Rol Usuario de red de Compute: si no usas el rol Agente de servicio de Cloud Run predeterminado o los permisos personalizados, asigna el rol Usuario de red de Compute (roles/compute.networkUser) a la cuenta de servicio Agente de servicio de Cloud Run. Las subredes con IPv6 externas también requieren el rol Administrador de IP pública de Compute (roles/compute.publicIpAdmin).

    Por ejemplo, para conceder el rol Usuario de red de Compute, ejecuta el siguiente comando:

    gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:service-PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com" \
    --role "roles/compute.networkUser"

    Haz los cambios siguientes:

    • PROJECT_ID: el ID de tu proyecto.
    • PROJECT_NUMBER: el número de proyecto en el que despliega su función de Cloud Run.

Configurar la salida de VPC directa

Configura la salida de VPC directa para funciones de segunda generación nuevas o ya creadas.

gcloud

  1. Para configurar la salida de VPC directa al desplegar una función, usa el comando gcloud beta functions deploy con las marcas de la configuración de tu red.

    gcloud beta functions deploy FUNCTION_NAME \
        --source . \
        --runtime RUNTIME \
        --trigger-http \
        --region REGION \
        --network=NETWORK \
        --subnet=SUBNET \
        --network-tags=NETWORK_TAG_NAMES \
        --direct-vpc-egress=EGRESS_SETTING
    

    Haz los cambios siguientes:

    • FUNCTION_NAME: el nombre de tu función.
    • RUNTIME: el tiempo de ejecución de tu función. Por ejemplo, nodejs20.
    • REGION: la región en la que despliega la función.
    • Opcional: NETWORK con el nombre de tu red de VPC. Especifica una red VPC o una subred, o ambas. Si solo especificas una red, la subred usará el mismo nombre que la red.
    • Opcional: SUBNET con el nombre de tu subred. Especifica una red VPC, una subred o ambas. Si solo especificas una red, la subred usará el mismo nombre que la red. Puedes desplegar o ejecutar varias funciones en la misma subred.
    • Opcional: NETWORK_TAG_NAMES con los nombres separados por comas de las etiquetas de red que quieras asociar a una función. Cada función puede tener etiquetas de red diferentes, como network-tag-2.
    • EGRESS_SETTING con un valor de ajuste de salida:
      • all: predeterminado. Envía todo el tráfico saliente a través de la red VPC.
      • private-ranges-only: solo envía tráfico a direcciones internas a través de la red de VPC.
  2. Opcional: Para quitar todos los ajustes de salida de VPC directa de una función, vuelve a implementar la función con las marcas --clear-network y --clear-network-tags.

Terraform

Para saber cómo aplicar o quitar una configuración de Terraform, consulta Comandos básicos de Terraform.

Para configurar la salida de VPC directa, usa el proveedor google-beta Terraform.

Partiendo del ejemplo de salida directa de VPC de Cloud Run Functions (2.ª gen.), actualiza los siguientes campos:

  • service_config.network: el nombre de tu red de VPC.
  • service_config.subnetwork: el nombre de la subred de VPC.
  • service_config.direct_vpc_egress: qué tráfico se debe enviar a la red de VPC. VPC_EGRESS_ALL_TRAFFIC envía todo el tráfico saliente a través de la red VPC. VPC_EGRESS_PRIVATE_RANGES_ONLY solo envía tráfico a intervalos de direcciones IP privadas a la red de VPC.

Ejemplo: Llamar a un servicio interno desde una función

En este ejemplo se muestra cómo crear un servicio interno de Cloud Run y, a continuación, llamarlo desde una función de Cloud Run (2.ª gen.) que usa la salida de VPC directa.

Crear el servicio de backend interno

  1. Crea un directorio para el servicio de backend y accede a él:

    mkdir backend-service
    cd backend-service
    
  2. Crea un archivo package.json con el siguiente contenido:

    {
        "name": "backend-service",
        "version": "1.0.0",
        "description": "",
        "scripts": {
            "start": "node index.js"
        },
        "dependencies": {
            "express": "^4.18.1"
        }
    }
    
  3. Crea un archivo index.js con el siguiente contenido:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
        res.send("hello world");
    });
    
    const port = parseInt(process.env.PORT) || 8080;
    app.listen(port, () => {
        console.log(`helloworld: listening on port ${port}`);
    });
    
  4. Despliega el servicio en Cloud Run con el tráfico interno:

    gcloud run deploy backend \
        --source . \
        --no-allow-unauthenticated \
        --region=REGION \
        --ingress internal
    

    Sustituye REGION por tu región (por ejemplo, us-west1).

  5. Guarda la URL del nuevo servicio. Necesitarás estos datos en la siguiente sección.

Crear y desplegar la función

  1. Crea un directorio para la función y accede a él:

    cd ..
    mkdir dvpc-function
    cd dvpc-function
    
  2. Crea un archivo package.json con el siguiente contenido:

    {
      "name": "sample-http",
      "version": "0.0.1",
      "dependencies": {
        "axios": "0.21.1",
        "@google-cloud/functions-framework": "^3.0.0"
      }
    }
    
  3. Crea un archivo index.js con el siguiente contenido. Este código hace una solicitud autenticada al servicio de backend interno.

    const axios = require('axios');
    const functions = require('@google-cloud/functions-framework');
    
    const callVPCService = async (req, res) => {
      const backendUrl = process.env.BACKEND_URL;
    
      if (!backendUrl) {
        console.error('BACKEND_URL environment variable not set.');
        res.status(500).send('BACKEND_URL not configured.');
        return;
      }
    
      try {
        const metadataServerURL = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
        const tokenUrl = metadataServerURL + backendUrl;
    
        const tokenResponse = await axios.get(tokenUrl, {
          headers: {
            'Metadata-Flavor': 'Google',
          },
        });
        const token = tokenResponse.data;
    
        const response = await axios.get(backendUrl, {
          headers: {
            Authorization: `bearer ${token}`,
          },
    });
    
    res.status(200).send(`Response from backend: ${response.data}`);
      } catch (error) {
        console.error(`Error calling backend service: ${error.message}`);
        res.status(500).send(`Error calling backend: ${error.message}`);
      }
    };
    
    functions.http('callVPCService', callVPCService);
    
  4. Despliega la función con la salida de VPC directa configurada para enrutar todo el tráfico a tu red de VPC predeterminada:

    gcloud beta functions deploy my-2ndgen-function \
      --source . \
      --runtime nodejs20 \
      --trigger-http \
      --entry-point callVPCService \
      --network=default \
      --subnet=default \
      --direct-vpc-egress=all \
      --region=REGION \
      --allow-unauthenticated \
      --set-env-vars BACKEND_URL=BACKEND_URL
    

    Haz los cambios siguientes:

    • REGION: la región en la que has desplegado el servicio de backend.
    • BACKEND_URL: la URL del servicio de backend que has creado.
  5. Una vez que se haya implementado la función, invócala visitando su URL. La función llama al servicio de backend interno y devuelve su respuesta.

Siguientes pasos