Configurer un service Cloud Run pour accéder à la fois à un service Cloud Run interne et à l'Internet public

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 (VCP) sur Google Cloud avec des contrôles de périmètre afin d'empêcher l'exfiltration de 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 (un service frontend, par exemple) puisse accéder au service de backend Cloud Run via un VPC et continuer à disposer d'un accès Internet public.

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. Vous verrez ensuite comment appeler https://curlmyip.org pour récupérer l'adresse IP de votre service de frontend.

Points abordés

  • Autoriser uniquement le trafic provenant d'un VPC vers votre service Cloud Run
  • Comment configurer la sortie sur un service Cloud Run (par exemple, frontend) pour communiquer avec un service Cloud Run interne uniquement (par exemple, un backend), tout en maintenant l'accès Internet public pour le service frontend.

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.

PROJECT_ID=<YOUR_PROJECT_ID>
REGION=<YOUR_REGION, e.g. us-central1>
FRONTEND=frontend-with-internet
BACKEND=backend
SUBNET_NAME=default

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 egress-private-codelab/frontend-w-internet egress-private-codelab/backend && cd egress-private-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éder au répertoire de l'interface

cd ../frontend-w-internet

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",
    "htmx.org": "^1.9.10"
  }
}

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

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

Dans cette section, vous allez vérifier que vous avez correctement déployé deux services Cloud Run.

Ouvrez l'URL du service d'interface dans votre navigateur Web, par exemple https://frontend-your-hash-uc.a.run.app/

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, et non depuis votre navigateur.

Le message "hello world" s'affiche.

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

Vous pouvez exécuter la commande gcloud suivante pour intégrer un service Cloud Run à votre réseau privé.

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

Si vous essayez d'appeler le service de backend à partir du service de frontend, vous obtenez une erreur 404. La connexion sortante (ou sortie) du service Cloud Run de l'interface est d'abord envoyée vers Internet. Google Cloud ne connaît donc pas l'origine de la requête.

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 à votre service Cloud Run frontend pour vous assurer qu'il peut atteindre les adresses IP internes sur le réseau VPC. Ensuite, vous configurerez la sortie de sorte que seules les requêtes adressées à des adresses IP privées soient acheminées vers le VPC. Cette configuration permettra à votre interface d'accéder à l'Internet public. Pour en savoir plus, consultez la documentation sur la réception de requêtes provenant d'autres services Cloud Run.

Configurer la sortie VPC directe

Commencez par exécuter la commande suivante pour utiliser la sortie VPC directe sur votre service d'interface:

gcloud beta run services update $FRONTEND \
--network=$SUBNET_NAME \
--subnet=$SUBNET_NAME  \
--vpc-egress=private-ranges-only \
--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:          private-ranges-only

Activer l'accès privé à Google

Vous allez ensuite activer l'accès privé à Google sur le sous-réseau à l'aide de la commande suivante:

gcloud compute networks subnets update $SUBNET_NAME \
--region=$REGION \
--enable-private-ip-google-access

Vous pouvez vérifier que l'accès privé à Google a bien été activé en exécutant la commande suivante:

gcloud compute networks subnets describe $SUBNET_NAME \
--region=$REGION \
--format="get(privateIpGoogleAccess)"

Créer une zone Cloud DNS pour les URL run.app

Enfin, créez une zone Cloud DNS pour les URL run.app afin que Google Cloud puisse les traiter comme des adresses IP internes.

Lors d'une étape précédente, vous avez configuré la sortie VPC directe sur "private-ranges-only". Cela signifie que les connexions sortantes de votre service de frontend ne sont redirigées vers le réseau VPC que si la destination est une adresse IP interne. Cependant, votre service de backend utilise une URL run.app qui pointe vers une adresse IP publique.

Au cours de cette étape, vous allez créer une zone Cloud DNS dans laquelle les URL run.app seront associées aux plages d'adresses IP private.googleapis.com, qui sont reconnues en tant qu'adresses IP internes. Toutes les requêtes adressées à ces plages seront acheminées via votre réseau VPC.

Pour ce faire, accédez à la page suivante: 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"

Lorsque vous essayez d'accéder au service de backend de votre site Web, le message "hello world" s'affiche. renvoyé.

Et lorsque vous tenterez d'accéder à Internet via https://curlmyip.org/, votre adresse IP s'affichera.

6. Dépannage

Voici quelques messages d'erreur susceptibles de s'afficher si les paramètres n'ont pas été configurés correctement.

  • Si une erreur getaddrinfo ENOTFOUND backend-your-hash-uc.a.run.app s'affiche, vérifiez que vous n'avez pas ajouté "https://". à l'enregistrement DNS A
  • Si vous recevez une erreur 404 lorsque vous tentez d'accéder au backend après avoir configuré la zone, vous pouvez attendre que le cache de l'enregistrement global run.app expire (par exemple, 6 heures) ou créer une nouvelle révision (et effacer le cache) en exécutant la commande suivante: gcloud beta run services update $FRONTEND --network=$SUBNET_NAME --subnet=$SUBNET_NAME --vpc-egress=private-ranges-only --region=$REGION

7. Félicitations !

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

Nous vous recommandons de consulter la documentation sur la mise en réseau privée sur Cloud Run.

Points abordés

  • Autoriser uniquement le trafic provenant d'un VPC vers votre service Cloud Run
  • Comment configurer la sortie sur un service Cloud Run (par exemple, frontend) pour communiquer avec un service Cloud Run interne uniquement (par exemple, un backend), tout en maintenant l'accès Internet public pour le service frontend.

8. Effectuer un nettoyage

Pour éviter des frais accidentels (par exemple, si ce service Cloud Run est appelé par inadvertance plus de fois que l'allocation mensuelle des appels Cloud Run dans la version sans frais), vous pouvez supprimer le service Cloud Run ou le projet que vous avez créé à l'étape 2.

Pour supprimer les services Cloud Run, accédez à la console Cloud Run à l'adresse https://console.cloud.google.com/functions/, puis supprimez les services $FRONTEND et $BACKEND que vous avez créés dans cet atelier de programmation.

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.