Configurer un service Cloud Run pour accéder à un service Cloud Run interne à l'aide de la sortie VPC directe

1. Introduction

Présentation

Afin de sécuriser le trafic réseau de leurs services et applications, de nombreuses organisations utilisent un réseau cloud privé virtuel (VPC) sur Google Cloud avec des contrôles de périmètre afin d'empêcher l'exfiltration des données. Un réseau VPC est une version virtuelle d'un réseau physique implémenté au sein du réseau de production de Google. Un réseau VPC fournit une connectivité pour vos instances de machines virtuelles (VM) Compute Engine, propose des équilibreurs de charge réseau passthrough internes natifs et des systèmes proxy pour les équilibreurs de charge d'application internes, se connecte aux réseaux sur site à l'aide de tunnels Cloud VPN et de rattachements de VLAN pour Cloud Interconnect, et répartit le trafic des équilibreurs de charge externes Google Cloud vers les backends.

Contrairement aux VM, les services Cloud Run ne sont associés par défaut à aucun réseau VPC particulier. Cet atelier de programmation explique comment modifier les paramètres d'entrée (connexions entrantes) de sorte que seul le trafic provenant d'un VPC puisse accéder à un service Cloud Run (un service de backend, par exemple). En outre, cet atelier de programmation vous montre comment faire en sorte qu'un deuxième service (par exemple, un service frontend) accède au service Cloud Run de backend via un VPC.

Dans cet exemple, le service de backend Cloud Run renvoie "hello world". Le service Cloud Run d'interface fournit un champ de saisie dans l'interface utilisateur pour collecter une URL. Le service frontend envoie ensuite une requête GET à cette URL (par exemple, le service de backend). Il s'agit donc d'une requête de service à service (au lieu d'une requête de navigateur à service). Lorsque le service de frontend peut atteindre le backend, le message "hello world" s'affiche dans le navigateur.

Points abordés

  • Autoriser uniquement le trafic provenant d'un VPC vers votre service Cloud Run
  • Configurer la sortie sur un service Cloud Run pour communiquer avec un service Cloud Run à entrée interne uniquement

2. Préparation

Prérequis

Activer Cloud Shell

  1. Dans Cloud Console, cliquez sur Activer Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Si vous démarrez Cloud Shell pour la première fois, un écran intermédiaire vous explique de quoi il s'agit. Si un écran intermédiaire s'est affiché, cliquez sur Continuer.

d95252b003979716.png

Le provisionnement et la connexion à Cloud Shell ne devraient pas prendre plus de quelques minutes.

7833d5e1c5d18f54.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute dans Google Cloud, ce qui améliore considérablement les performances du réseau et l'authentification. Une grande partie, voire la totalité, de votre travail dans cet atelier de programmation peut être effectué dans un navigateur.

Une fois connecté à Cloud Shell, vous êtes authentifié et le projet est défini sur votre ID de projet.

  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que vous êtes authentifié :
gcloud auth list

Résultat de la commande

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud connaît votre projet:
gcloud config list project

Résultat de la commande

[core]
project = <PROJECT_ID>

Si vous obtenez un résultat différent, exécutez cette commande :

gcloud config set project <PROJECT_ID>

Résultat de la commande

Updated property [core/project].

3. Créer les services Cloud Run

Configurer des variables d'environnement

Vous pouvez définir les variables d'environnement qui seront utilisées tout au long de cet atelier de programmation.

REGION=<YOUR_REGION, e.g. us-central1>
FRONTEND=frontend
BACKEND=backend

Créer le service Cloud Run de backend

Tout d'abord, créez un répertoire pour le code source et utilisez la commande cd pour y accéder.

mkdir -p internal-codelab/frontend internal-codelab/backend && cd internal-codelab/backend

Ensuite, créez un fichier package.json avec le contenu suivant:

{
    "name": "backend-service",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "node index.js"
    },
    "dependencies": {
        "express": "^4.18.1"
    }
}

Ensuite, créez un fichier source index.js avec le contenu ci-dessous. Ce fichier contient le point d'entrée du service et la logique principale de l'application.

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}`);
});

Enfin, déployez le service Cloud Run en exécutant la commande suivante.

gcloud run deploy $BACKEND --source . --allow-unauthenticated --region $REGION

Créer le service Cloud Run de frontend

Accédez au répertoire de l'interface.

cd ../frontend

Ensuite, créez un fichier package.json avec le contenu suivant:

{
  "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"
  }
}

Ensuite, créez un fichier source index.js avec le contenu ci-dessous. Ce fichier contient le point d'entrée du service et la logique principale de l'application.

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}`);
});

Créer un répertoire public pour le fichier index.html

mkdir public
touch public/index.html

Mettez à jour le fichier index.html pour qu'il contienne les éléments suivants:

<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 Frontend service on the Internet</h1>
      <form hx-trigger="submit" hx-post="/callService" hx-target="#message">
        <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="message" style="white-space: pre-wrap"></div>
        <p></p>
      </form>
    </div>
  </body>
</html>

Enfin, déployez le service Cloud Run en exécutant la commande suivante.

gcloud run deploy $FRONTEND --source . --allow-unauthenticated --region $REGION

Appeler le service de backend

Vérifiez que vous avez correctement déployé deux services Cloud Run.

Ouvrez l'URL du service de frontend dans votre navigateur Web.

Dans la zone de texte, saisissez l'URL du service de backend. Notez que cette requête est acheminée de l'instance frontend Cloud Run vers le service de backend Cloud Run, au lieu d'être acheminée depuis votre navigateur.

"hello world" s'affiche.

4. Définir le service de backend pour l'entrée interne uniquement

Exécutez la commande gcloud suivante pour n'autoriser que le trafic provenant de votre réseau VPC à accéder à votre service de backend.

gcloud run services update $BACKEND --ingress internal --region $REGION

Pour vérifier que votre service de backend ne peut recevoir que le trafic provenant de votre VPC, essayez à nouveau d'appeler votre service de backend à partir de votre service de frontend.

Cette fois, le message "Échec de la requête avec le code d'état 404" s'affiche.

Vous recevez cette erreur, car la requête sortante du service Cloud Run de l'interface (sortie) est d'abord envoyée vers Internet. Google Cloud ne connaît donc pas l'origine de la requête.

Dans la section suivante, vous allez configurer le service de frontend pour accéder au VPC afin que Google Cloud sache que la requête provient du VPC, qui est reconnu en tant que source interne.

5. Configurer le service d'interface pour accéder au VPC

Dans cette section, vous allez configurer votre service Cloud Run d'interface pour qu'il communique avec votre service de backend via un VPC.

Pour ce faire, vous devez ajouter une sortie VPC directe à vos instances Cloud Run frontend pour attribuer à votre service une adresse IP interne à utiliser dans le VPC. Ensuite, vous configurerez le trafic de sortie de sorte que toutes les connexions sortantes du service de frontend soient dirigées vers le VPC.

Commencez par exécuter la commande suivante pour activer la sortie VPC directe:

gcloud beta run services update $FRONTEND \
--network=default \
--subnet=default \
--vpc-egress=all-traffic \
--region=$REGION

Vous pouvez maintenant vérifier que votre service d'interface a accès au VPC:

gcloud beta run services describe $FRONTEND \
--region=$REGION

Vous devriez obtenir un résultat semblable à celui-ci :

VPC access:
    Network:         default
    Subnet:          default
    Egress:          all-traffic

Réessayez maintenant d'appeler votre service de backend à partir de votre service de frontend.

Cette fois, vous verrez "hello world".

Remarque: Votre service d'interface n'a pas accès à Internet, car toute la sortie a été acheminée vers le VPC. Par exemple, votre service d'interface expirera s'il tente d'accéder à https://curlmyip.org/.

6. Félicitations !

Félicitations ! Vous avez terminé cet atelier de programmation.

Nous vous recommandons de consulter la documentation Cloud Run et de découvrir comment configurer un réseau privé pour les services Cloud Run.

Points abordés

  • Autoriser uniquement le trafic provenant d'un VPC vers votre service Cloud Run
  • Configurer la sortie sur un service Cloud Run pour communiquer avec un service Cloud Run à entrée interne uniquement

7. Effectuer un nettoyage

Pour éviter des frais accidentels (par exemple, si les services Cloud Run sont invoqués plus de fois que l'allocation mensuelle des appels Cloud Run dans le niveau sans frais), vous pouvez supprimer Cloud Run ou le projet créé à l'étape 2.

Pour supprimer le service Cloud Run, accédez à la console Cloud Run à l'adresse https://console.cloud.google.com/run et supprimez les services $FRONTEND et $BACKEND.

Si vous choisissez de supprimer l'intégralité du projet, vous pouvez accéder à https://console.cloud.google.com/cloud-resource-manager, sélectionner le projet que vous avez créé à l'étape 2, puis cliquer sur "Supprimer". Si vous supprimez le projet, vous devrez le modifier dans Cloud SDK. Vous pouvez afficher la liste de tous les projets disponibles en exécutant gcloud projects list.