1. Introducción
Descripción general
Para proteger el tráfico de red de sus servicios y aplicaciones, muchas organizaciones usan una red de nube privada virtual (VCP) en Google Cloud con controles perimetrales para evitar el robo de datos. Una red de VPC es una versión virtual de una red física que se implementa dentro de la red de producción de Google. Una red de VPC proporciona conectividad para tus instancias de máquina virtual (VM) de Compute Engine, ofrece balanceadores de cargas de red de transferencia internos nativos y sistemas proxy para balanceadores de cargas de aplicaciones internos, se conecta a redes locales usando túneles de Cloud VPN y adjuntos de VLAN para Cloud Interconnect, y distribuye el tráfico de balanceadores de cargas externos de Google Cloud a backends.
A diferencia de las VMs, los servicios de Cloud Run no están asociados con ninguna red de VPC en particular de forma predeterminada. En este codelab, se muestra cómo cambiar la configuración de entrada (conexiones entrantes) para que solo el tráfico proveniente de una VPC pueda acceder a un servicio de Cloud Run (p.ej., un servicio de backend). Además, en este codelab, se muestra cómo hacer que un segundo servicio (p.ej., un servicio de frontend) acceda al servicio de backend de Cloud Run a través de una VPC y, además, seguir teniendo acceso público a Internet.
En este ejemplo, el servicio de backend de Cloud Run muestra Hello World. El servicio de frontend de Cloud Run proporciona un campo de entrada en la IU para recopilar una URL. Luego, el servicio de frontend realiza una solicitud GET a esa URL (p.ej., el servicio de backend), por lo que se convierte en una solicitud de servicio a servicio (en lugar de una solicitud de navegador a servicio). Cuando el servicio de frontend llega correctamente al backend, se muestra el mensaje Hello World en el navegador. Luego, verás cómo puedes llamar a https://curlmyip.org para recuperar la dirección IP de tu servicio Frontend.
Qué aprenderás
- Cómo permitir solo el tráfico de una VPC al servicio de Cloud Run
- Cómo configurar la salida en un servicio de Cloud Run (p.ej., frontend) para comunicarse con un servicio de Cloud Run de solo entrada interna (p.ej., backend) y, al mismo tiempo, mantener el acceso público a Internet para el servicio de frontend.
2. Configuración y requisitos
Requisitos previos
- Accediste a la consola de Cloud.
- Ya implementaste una función de 2a gen. Por ejemplo, puedes seguir la implementación de una guía de inicio rápido de Cloud Function 2nd gen para comenzar.
Activar Cloud Shell
- En la consola de Cloud, haz clic en Activar Cloud Shell
.
Si es la primera vez que inicias Cloud Shell, verás una pantalla intermedia que describe en qué consiste. Si apareció una pantalla intermedia, haz clic en Continuar.
El aprovisionamiento y la conexión a Cloud Shell solo tomará unos minutos.
Esta máquina virtual está cargada con todas las herramientas de desarrollo necesarias. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que mejora considerablemente el rendimiento de la red y la autenticación. Gran parte de tu trabajo en este codelab, si no todo, se puede hacer con un navegador.
Una vez que te conectes a Cloud Shell, deberías ver que estás autenticado y que el proyecto está configurado con tu ID del proyecto.
- En Cloud Shell, ejecuta el siguiente comando para confirmar que tienes la autenticación:
gcloud auth list
Resultado del comando
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Ejecuta el siguiente comando en Cloud Shell para confirmar que el comando de gcloud conoce tu proyecto:
gcloud config list project
Resultado del comando
[core] project = <PROJECT_ID>
De lo contrario, puedes configurarlo con el siguiente comando:
gcloud config set project <PROJECT_ID>
Resultado del comando
Updated property [core/project].
3. Crea los servicios de Cloud Run
Configura variables de entorno
Puedes establecer variables de entorno que se usarán en este codelab.
PROJECT_ID=<YOUR_PROJECT_ID> REGION=<YOUR_REGION, e.g. us-central1> FRONTEND=frontend-with-internet BACKEND=backend SUBNET_NAME=default
Crea el servicio de backend de Cloud Run
Primero, crea un directorio para el código fuente y desplázate a ese directorio con el comando cd.
mkdir -p egress-private-codelab/frontend-w-internet egress-private-codelab/backend && cd egress-private-codelab/backend
Luego, 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" } }
A continuación, crea un archivo fuente index.js
con el siguiente contenido. Este archivo contiene el punto de entrada del servicio y la lógica principal de la app.
const express = require('express'); const app = express(); app.use(express.urlencoded({ extended: true })); app.get('/', function (req, res) { res.send("hello world"); }); const port = parseInt(process.env.PORT) || 8080; app.listen(port, () => { console.log(`helloworld: listening on port ${port}`); });
Por último, implementa el servicio de Cloud Run ejecutando el siguiente comando.
gcloud run deploy $BACKEND --source . --allow-unauthenticated --region $REGION
Crea el servicio de Cloud Run de frontend
Navega al directorio de frontend
cd ../frontend-w-internet
Luego, crea un archivo package.json
con el siguiente contenido:
{ "name": "frontend", "version": "1.0.0", "description": "", "scripts": { "start": "node index.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "axios": "^1.6.6", "express": "^4.18.2", "htmx.org": "^1.9.10" } }
A continuación, crea un archivo fuente index.js
con el siguiente contenido. Este archivo contiene el punto de entrada del servicio y la lógica principal de la app.
const express = require("express"); const app = express(); const port = 8080; const path = require('path'); const axios = require('axios'); // serve static content (index.html) using // built-in middleware function in Express app.use(express.static('public')); app.use(express.urlencoded({ extended: true })); // this endpoint receives a URL in the post body // and then makes a get request to that URL // results are sent back to the caller app.post('/callService', async (req, res) => { const url = req.body.url; let message = ""; try { console.log("url: ", url); const response = await axios.get(url); message = response.data; } catch (error) { message = error.message; console.error(error.message); } res.send(` ${message} <p> </p> `); }); app.listen(port, () => { console.log(`Example app listening on port ${port}`); });
Crea un directorio público para el archivo index.html
mkdir public touch public/index.html
Además, actualiza index.html
para que contenga lo siguiente:
<html> <script src="https://unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous" ></script> <body> <div style="margin-top: 100px; margin-left: 100px"> <h1>I'm the Request Tester service on the Internet</h1> <form hx-trigger="submit" hx-post="/callService" hx-target="#zen"> <label for="url"> URL:</label> <input style="width: 308px" type="text" id="url" name="url" placeholder="The backend service URL" required /> <button hx-indicator="#loading" type="submit">Submit</button> <p></p> <span class="htmx-indicator" id="loading"> Loading... </span> <div id="zen" style="white-space: pre-wrap"></div> <p></p> </form> </div> </body> </html>
Por último, implementa el servicio de Cloud Run ejecutando el siguiente comando.
gcloud run deploy $FRONTEND --source . --allow-unauthenticated --region $REGION
Llama al servicio de backend
En esta sección, verificarás si implementaste correctamente dos servicios de Cloud Run.
Abre la URL del servicio de frontend en tu navegador web, p.ej., https://frontend-your-hash-uc.a.run.app/
En el cuadro de texto, ingresa la URL del servicio de backend. Ten en cuenta que esta solicitud se enruta desde la instancia de frontend de Cloud Run hasta el servicio de backend de Cloud Run, y no desde tu navegador.
Verás “Hello World”
4. Configurar el servicio de backend solo para entrada interna
Puedes ejecutar el siguiente comando de gcloud para incorporar un servicio de Cloud Run en tu red privada.
gcloud run services update $BACKEND --ingress internal --region $REGION
Si intentaras llamar al servicio de backend desde el servicio de frontend, recibirías un error 404. La conexión saliente (o salida) del servicio de frontend de Cloud Run primero se dirige a Internet, por lo que Google Cloud no sabe el origen de la solicitud.
5. Configurar el servicio de frontend para acceder a la VPC
En esta sección, configurarás tu servicio de frontend de Cloud Run para que se comunique con tu servicio de backend a través de una VPC.
Para ello, deberás agregar una salida de VPC directa a tu servicio de frontend de Cloud Run para asegurarte de que pueda acceder a las direcciones IP internas en la red de VPC. Luego, configurarás la salida para que solo las solicitudes a IP privadas se enruten a la VPC. Esta configuración permitirá que el frontend siga accediendo a la Internet pública. Puedes obtener más información en la documentación sobre cómo recibir solicitudes de otros servicios de Cloud Run.
Configura la salida de VPC directa
Primero, ejecuta este comando para usar la salida de VPC directa en tu servicio de frontend:
gcloud beta run services update $FRONTEND \ --network=$SUBNET_NAME \ --subnet=$SUBNET_NAME \ --vpc-egress=private-ranges-only \ --region=$REGION
Ahora puedes confirmar que tu servicio de frontend tenga acceso a la VPC:
gcloud beta run services describe $FRONTEND \ --region=$REGION
Deberías ver un resultado similar al siguiente
VPC access: Network: default Subnet: default Egress: private-ranges-only
Habilite el Acceso privado a Google
A continuación, habilitarás el Acceso privado a Google en la subred ejecutando el siguiente comando:
gcloud compute networks subnets update $SUBNET_NAME \ --region=$REGION \ --enable-private-ip-google-access
Para verificar que se habilitó el Acceso privado a Google, ejecuta este comando:
gcloud compute networks subnets describe $SUBNET_NAME \ --region=$REGION \ --format="get(privateIpGoogleAccess)"
Crea una zona de Cloud DNS para las URLs de run.app
Por último, crea una zona de Cloud DNS para las URLs de run.app de modo que Google Cloud pueda tratarlas como direcciones IP internas.
En un paso anterior, en el que configuraste la salida de VPC directa para solo rangos privados. Esto significa que las conexiones salientes de tu servicio de frontend solo irán a la red de VPC si el destino es una IP interna. Sin embargo, tu servicio de backend usa una URL run.app que se resuelve en una IP pública.
En este paso, crearás una zona de Cloud DNS para que las URLs de run.app se resuelvan en los rangos de direcciones IP private.googleapis.com, que se reconocen como direcciones IP internas. Cualquier solicitud a estos rangos se enrutará a través de tu red de VPC.
Para ello, sigue estos pasos: https://cloud.google.com/run/docs/securing/private-networking#from-other-services
# do not include the https:// in your DNS Name # for example: backend-<hash>-uc.a.run.app DNS_NAME=<your backend service URL without the https://> gcloud dns --project=$PROJECT_ID managed-zones create codelab-backend-service \ --description="" \ --dns-name="a.run.app." \ --visibility="private" \ --networks=$SUBNET_NAME gcloud dns --project=$PROJECT_ID record-sets create $DNS_NAME. \ --zone="codelab-backend-service" \ --type="A" \ --ttl="60" \ --rrdatas="199.36.153.8,199.36.153.9,199.36.153.10,199.36.153.11"
Ahora, cuando intentes acceder al servicio de backend de tu sitio web, verás “Hello World”. que se devuelven.
Y cuando intentes acceder a Internet usando https://curlmyip.org/, verás tu dirección IP.
6. Soluciona problemas
Estos son algunos mensajes de error que podrían aparecer si los parámetros no se establecieron correctamente.
- Si recibes un mensaje de error
getaddrinfo ENOTFOUND backend-your-hash-uc.a.run.app
, asegúrate de no haber agregado “https://”. al registro A del DNS - Si recibes un error 404 cuando intentas acceder al backend después de configurar la zona, puedes esperar a que venza la caché en el registro global run.app (p.ej., 6 horas) o puedes crear una revisión nueva (por lo tanto, borrar la caché) ejecutando el siguiente comando:
gcloud beta run services update $FRONTEND --network=$SUBNET_NAME --subnet=$SUBNET_NAME --vpc-egress=private-ranges-only --region=$REGION
7. ¡Felicitaciones!
¡Felicitaciones por completar el codelab!
Te recomendamos que revises la documentación sobre Herramientas de redes privadas en Cloud Run.
Temas abordados
- Cómo permitir solo el tráfico de una VPC al servicio de Cloud Run
- Cómo configurar la salida en un servicio de Cloud Run (p.ej., frontend) para comunicarse con un servicio de Cloud Run de solo entrada interna (p.ej., backend) y, al mismo tiempo, mantener el acceso público a Internet para el servicio de frontend.
8. Limpia
Para evitar cargos involuntarios (por ejemplo, si este servicio de Cloud Run se invoca de forma involuntaria más veces que tu asignación mensual de invocación de Cloud Run en el nivel gratuito), puedes borrar el servicio de Cloud Run o borrar el proyecto que creaste en el paso 2.
Para borrar los servicios de Cloud Run, ve a la consola de Cloud Run en https://console.cloud.google.com/functions/ y borra los servicios de $FRONTEND y $BACKEND que creaste en este codelab.
Si decides borrar el proyecto completo, puedes ir a https://console.cloud.google.com/cloud-resource-manager, seleccionar el proyecto que creaste en el paso 2 y elegir Borrar. Si borras el proyecto, deberás cambiar los proyectos en tu SDK de Cloud. Para ver la lista de todos los proyectos disponibles, ejecuta gcloud projects list
.