crea un servizio Cloud Run con un sidecar

1. Panoramica

Introduzione

In questo codelab, imparerai a eseguire il deployment di un servizio Cloud Run che utilizza più container. Creerai un'app Node.js che verrà utilizzata come container di ingresso Cloud Run e un'app Node.js aggiuntiva che verrà utilizzata come sidecar.

Panoramica tecnica

Quando utilizzi più container all'interno di un'istanza Cloud Run, un container viene utilizzato come container principale per l'ingresso web. Uno o più container aggiuntivi sono chiamati sidecar.

Esistono due modi per consentire a più contenitori di comunicare tra loro:

  1. I container condividono l'interfaccia di rete localhost, quindi tutti i container possono ascoltare una porta, ad esempio localhost:porta.
  2. Puoi anche utilizzare volumi in memoria e montarli sui container per condividere i file.

Casi d'uso

Poiché tutti i container all'interno dell'istanza Cloud Run condividono l'interfaccia di rete localhost, puoi utilizzare un sidecar davanti al container principale per eseguire il proxy delle richieste. Questi proxy possono fornire un ulteriore livello di astrazione per un flusso di traffico più efficiente verso l'applicazione tra client e server intercettando le richieste e inoltrandole all'endpoint appropriato. Ad esempio, puoi utilizzare l'immagine Nginx ufficiale di DockerHub (come mostrato qui).

Poiché più container possono comunicare condividendo file tramite volumi condivisi, puoi aggiungere varie applicazioni sidecar al tuo servizio. Ad esempio, puoi instrumentare il tuo servizio Cloud Run per utilizzare agenti personalizzati come OpenTelemetry per esportare log, metriche e tracce (esempio di OpenTelemetry). Un altro esempio è l'utilizzo di un sidecar per connettersi a un database Cloud Spanner PostgreSQL (esempio di Cloud Spanner Postgress).

Esempi in questo codelab

In questo codelab, prima eseguirai il deployment di un servizio Cloud Run in cui il container in entrata comunica con un sidecar tramite una porta localhost. Poi aggiornerai il container di ingresso e il sidecar per condividere un file tramite un montaggio del volume.

Cosa imparerai a fare

  • Come creare un container che utilizza un sidecar
  • Come un container di ingresso può comunicare con un sidecar utilizzando localhost
  • Come un container di ingresso e un sidecar possono condividere un file tramite un volume montato

2. Configurazione e requisiti

Prerequisiti

Attiva Cloud Shell

  1. Nella console Cloud, fai clic su Attiva Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Se è la prima volta che avvii Cloud Shell, viene visualizzata una schermata intermedia che ne descrive le funzionalità. Se è stata visualizzata una schermata intermedia, fai clic su Continua.

d95252b003979716.png

Bastano pochi istanti per eseguire il provisioning e connettersi a Cloud Shell.

7833d5e1c5d18f54.png

Questa macchina virtuale è caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Gran parte del lavoro per questo codelab, se non tutto, può essere svolto con un browser.

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è autenticato e il progetto è impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui questo comando in Cloud Shell per verificare che il comando gcloud conosca il tuo progetto:
gcloud config list project

Output comando

[core]
project = <PROJECT_ID>

In caso contrario, puoi impostarlo con questo comando:

gcloud config set project <PROJECT_ID>

Output comando

Updated property [core/project].

3. Crea l'app in entrata

Imposta le variabili di ambiente

In questo codelab, creerai alcune variabili di ambiente per migliorare la leggibilità dei comandi gcloud utilizzati.

REGION=<YOUR-REGION>
PROJECT_ID=<YOUR-PROJECT-ID>

SERVICE_NAME=sidecar-codelab
REPO_NAME=sidecar-codelab

Crea un repository Artifact Registry per contenere le immagini container

Puoi creare un repository in Artifact Registry per archiviare le immagini container per questo codelab.

gcloud artifacts repositories create $REPO_NAME --repository-format=docker \
--location=$REGION --description="sidecar codelab"

Quindi, crea un file package.json con il seguente contenuto:

{
  "name": "sidecar-codelab",
  "version": "1.0.0",
  "private": true,
  "description": "demonstrates how to use sidecars in cloud run",
  "main": "index.js",
  "author": "Google LLC",
  "license": "Apache-2.0",
  "scripts": {
    "start": "node ingress.js"
  },
  "dependencies": {
    "axios": "^1.6.2",
    "express": "^4.18.2"
  }
}

Ora crea un file denominato ingress.js con il seguente contenuto:

const express = require('express');
const app = express();
const axios = require("axios");

app.get('/', async (req, res) => {

    let response = await axios.get("http://localhost:5000");

    res.send("The sidecar says: " + response.data);
});

const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () => {
    console.log(`Ingress container listening on port ${port}`);
});

Crea un Dockerfile per il container in entrata

FROM node:20.10.0-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --production

# Copy local code to the container image.
COPY . .

# Run the web service on container startup.
ENV PORT=8080
CMD [ "npm", "start" ]

e crea un file `.dockerignore` per il container di Ingress.

# Exclude locally installed dependencies
node_modules/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore

Ora puoi creare l'immagine per il container Ingress eseguendo questo comando:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest

4. Crea l'app sidecar

In questa sezione, creerai una seconda app Node.js che verrà utilizzata come sidecar nel servizio Cloud Run.

Vai alla directory sidecar.

cd ../sidecar

Crea un file package.json con il seguente contenuto:

{
  "name": "sidecar-codelab",
  "version": "1.0.0",
  "private": true,
  "description": "demonstrates how to use sidecars in cloud run",
  "main": "index.js",
  "author": "Google LLC",
  "license": "Apache-2.0",
  "scripts": {
    "start": "node sidecar.js"
  },
  "dependencies": {
    "axios": "^1.6.2",
    "express": "^4.18.2"
  }
}

Ora crea un file denominato sidecar.js con il seguente contenuto:

const express = require('express');
const app = express();

app.get('/', async (req, res) => {
    res.send("Hello ingress container! I'm the sidecar.");
});

const port = parseInt(process.env.PORT || 5000);
app.listen(port, () => {
    console.log(`Sidecar container listening on port ${port}`);
});

Crea un Dockerfile per il container sidecar

FROM node:20.10.0-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --production

# Copy local code to the container image.
COPY . .

# Run the web service on container startup.
ENV PORT=5000
CMD [ "npm", "start" ]

e crea un file `.dockerignore` per il container sidecar.

# Exclude locally installed dependencies
node_modules/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore

Ora puoi creare l'immagine per il container Ingress eseguendo questo comando:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest

Esegui il deployment del servizio Cloud Run

Esegui il deployment del servizio Cloud Run utilizzando un file YAML.

Vai alla directory principale.

cd ..

Crea un file denominato sidecar-codelab.yaml con i seguenti contenuti:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  annotations:
  name: sidecar-codelab
  labels:
    cloud.googleapis.com/location: "<YOUR_REGION>"
spec:
  template:
    spec:
      containers:
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest"
          ports:
            - containerPort: 8080
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest"
          env:
            - name: PORT
              value: "5000"

Quindi, esegui il deployment del servizio utilizzando il seguente comando. Devi utilizzare gcloud beta perché i volumi montati sono in anteprima pubblica.

gcloud beta run services replace sidecar-codelab.yaml

Una volta eseguito il deployment, salva l'URL del servizio in una variabile di ambiente.

SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --platform managed --region $REGION --format 'value(status.url)') 

5. Chiama il servizio Cloud Run

Ora puoi chiamare il tuo servizio fornendo il token di identità.

curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}

I risultati dovrebbero essere simili a quelli dell'esempio seguente:

The sidecar says: Hello ingress container! I'm the sidecar.

6. Condividere un file tramite un montaggio del volume

In questa sezione aggiornerai i container per condividere un file tramite un montaggio del volume. In questo esempio, il container di ingresso scriverà in un file su un volume condiviso. Il sidecar leggerà il file e restituirà i suoi contenuti al container di ingresso.

Per prima cosa, aggiorna il codice del contenitore di ingresso. Vai alla directory di ingresso.

cd ../ingress

e poi sostituisci i contenuti del file ingress.js con quanto segue:

const express = require('express');
const app = express();
const fs = require('fs');
const axios = require("axios");

const filename = "test.txt"

let path = "/my-volume-mount";
app.use(path, express.static(path));

try {
    fs.writeFileSync(`${path}/${filename}`, "The ingress container created this file.");
} catch (err) {
    console.error(err);
}

app.get('/', async (req, res) => {

    let response = await axios.get("http://localhost:5000");

    res.send("The sidecar says: " + response.data);
});

const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () => {
    console.log(`Ingress container listening on port ${port}`);
});

Crea la nuova immagine per il container Ingress eseguendo questo comando:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest

Ora vai alla directory sidecar:

cd ../sidecar

e aggiorna sidecar.js con i seguenti contenuti:

const express = require('express');
const app = express();
const fs = require('fs');

const filename = "test.txt"

let path = "/my-volume-mount";
app.use(path, express.static(path));

async function readFile() {
    try {
        return await fs.readFileSync(`${path}/${filename}`, { encoding: 'utf8' });
    } catch (err) {
        console.log(err);
    }
}

app.get('/', async (req, res) => {
    let contents = await readFile();
    res.send(contents);
});

const port = parseInt(process.env.PORT || 5000);
app.listen(port, () => {
    console.log(`Sidecar container listening on port ${port}`);
});

Crea la nuova immagine per il container sidecar eseguendo questo comando:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest

Aggiorna sidecar-codelab.yaml con quanto segue per condividere un volume:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  annotations:
  name: sidecar-codelab
  labels:
    cloud.googleapis.com/location: "<YOUR_REGION>"
spec:
  template:
    spec:
      containers:
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest"
          ports:
            - containerPort: 8080
          volumeMounts:
            - mountPath: /my-volume-mount
              name: in-memory-1
        - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest"
          env:
            - name: PORT
              value: "5000"
          volumeMounts:
            - mountPath: /my-volume-mount
              name: in-memory-1
      volumes:
        - emptyDir:
            medium: Memory
          name: in-memory-1

Esegui il deployment del file sidecar-codelab.yaml aggiornato

gcloud beta run services replace sidecar-codelab.yaml

Ora puoi chiamare il tuo servizio fornendo il token di identità.

curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}

I risultati dovrebbero essere simili a quelli dell'esempio seguente:

The sidecar says: the ingress container created this file.

7. Complimenti!

Congratulazioni per aver completato il codelab.

Ti consigliamo di consultare la documentazione su Cloud Run, in particolare su deployment di multicontainer e sull'utilizzo di montaggi di volumi in memoria.

Argomenti trattati

  • Come creare un container che utilizza un sidecar
  • Come un container di ingresso può comunicare con un sidecar utilizzando localhost
  • Come un container di ingresso e un sidecar possono condividere un volume montato

8. Esegui la pulizia

Per evitare addebiti involontari (ad esempio, se questa Cloud Function viene richiamata inavvertitamente più volte rispetto all'allocazione mensile di chiamate di Cloud Run nel livello senza costi), puoi eliminare il servizio Cloud Run o il progetto che hai creato nel passaggio 2.

Per eliminare la Funzione Cloud, vai alla console Cloud di Funzioni Cloud all'indirizzo https://console.cloud.google.com/run/ ed elimina il servizio sidecar-codelab (o $SERVICE_NAME se hai utilizzato un nome diverso).

Se scegli di eliminare l'intero progetto, puoi andare alla pagina https://console.cloud.google.com/cloud-resource-manager, selezionare il progetto che hai creato nel passaggio 2 e scegliere Elimina. Se elimini il progetto, dovrai cambiare progetto in Cloud SDK. Puoi visualizzare l'elenco di tutti i progetti disponibili eseguendo gcloud projects list.