Sviluppo InnerLoop con NodeJS

1. Panoramica

Questo lab illustra funzionalità e capacità progettate per semplificare il flusso di lavoro di sviluppo per i tecnici del software incaricati di sviluppare applicazioni NodeJS in un ambiente containerizzato. Lo sviluppo tipico dei container richiede che l'utente comprenda i dettagli dei container e del processo di compilazione dei container. Inoltre, gli sviluppatori in genere devono interrompere il flusso, uscendo dal loro IDE per testare ed eseguire il debug delle loro applicazioni in ambienti remoti. Con gli strumenti e le tecnologie citati in questo tutorial, gli sviluppatori possono lavorare in modo efficace con le applicazioni containerizzate senza uscire dall'IDE.

Cosa imparerai a fare

In questo lab imparerai i metodi per lo sviluppo con container in Google Cloud, tra cui:

  • Creazione di un'applicazione Nodejs iniziale
  • Configurazione dell'applicazione Nodejs per lo sviluppo di container in corso...
  • Programmazione di un servizio REST CRUD semplice
  • Deployment in GKE
  • Debug di uno stato di errore
  • Utilizzo di punto di interruzione / log
  • Modifiche al deployment a caldo con ritorno in GKE
  • (Facoltativo) Integrazione di Cloud SQL per la persistenza del backend

2. Configurazione e requisiti

Configurazione dell'ambiente autogestito

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il Nome progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google e può essere aggiornata in qualsiasi momento.
  • L'ID progetto deve essere univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca; di solito non ti importa cosa sia. Nella maggior parte dei codelab, devi fare riferimento all'ID progetto (che solitamente è identificato come PROJECT_ID), quindi, se non ti piace, generane un altro a caso oppure puoi fare un tentativo personalizzato e controllare se è disponibile. Poi c'è "congelato" dopo la creazione del progetto.
  • C'è un terzo valore, il numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare le risorse/le API Cloud. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial, segui eventuali "pulizie" istruzioni riportate alla fine del codelab. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.

Avvia editor Cloudshell

Questo lab è stato progettato e testato per l'utilizzo con l'editor di Google Cloud Shell. Per accedere all'editor,

  1. accedi al tuo progetto Google all'indirizzo https://console.cloud.google.com.
  2. Nell'angolo in alto a destra, fai clic sull'icona dell'editor di Cloud Shell

8560cc8d45e8c112.png

  1. Si aprirà un nuovo riquadro nella parte inferiore della finestra
  2. Fai clic sul pulsante Apri editor

9e504cb98a6a8005.png

  1. L'editor si apre con un Explorer a destra e l'editor nell'area centrale
  2. Nella parte inferiore dello schermo dovrebbe essere disponibile anche un riquadro del terminale
  3. Se il terminale NON è aperto, utilizza la combinazione di tasti "Ctrl+" per aprire una nuova finestra del terminale

Configura gcloud

In Cloud Shell, imposta l'ID progetto e la regione in cui vuoi eseguire il deployment dell'applicazione. Salvale come variabili PROJECT_ID e REGION.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

configura il cluster e il database GKE

  1. Scarica lo script di configurazione e rendilo eseguibile.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup.sh
chmod +x setup.sh

Esegui il provisioning dell'infrastruttura utilizzata in questo lab

In questo lab eseguirai il deployment del codice su GKE e accedi ai dati archiviati in un database Spanner. Lo script di configurazione riportato di seguito prepara l'infrastruttura per te.

  1. Apri il file setup.sh e modifica i valori delle password attualmente impostate su CHANGEME
  2. Esegui lo script di configurazione per creare un cluster GKE e un database Cloud SQL che utilizzerai in questo lab
./setup.sh
  1. In Cloud Shell, crea una nuova directory con il nome mynodejsapp
mkdir mynodejsapp
  1. Passa a questa directory e aprila come spazio di lavoro. L'editor verrà ricaricato mediante la creazione di una configurazione dell'area di lavoro nella cartella appena creata.
cd mynodejsapp && cloudshell workspace .
  1. Installare nodo e NPM utilizzando NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
        
        # This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  

nvm install stable

nvm alias default stable

3. Crea una nuova applicazione iniziale

  1. Inizializza l'applicazione

Crea un file package.json eseguendo questo comando

npm init
    Choose the entry point: (index.js) src/index.js and default values for the rest of the parameters. This will create the file with following contents
{
  "name": "mynodejsapp",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
  1. Aggiungere un punto di ingresso

Modifica questo file per includere il comando start nello script "start": "node src/index.js",. Dopo la modifica, gli script dovrebbero avere l'aspetto dello snippet di codice riportato di seguito:

"scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  1. Aggiungere la dipendenza Express

Il codice che aggiungeremo utilizza anche express, quindi aggiungiamo questa dipendenza a questo file package.json. Dopo tutte le modifiche, il file package.json dovrebbe essere come mostrato di seguito.

​​{
  "name": "mynodejsapp",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Your Name",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}
  1. Crea il file index.js.

Crea una directory di origine denominata src

Crea src/index.js con il seguente codice

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

app.get('/', (req, res) => {
    var message="Greetings from Node";
    res.send({ message: message });
  });

app.listen(PORT, () => {
  console.log(`Server running at: http://localhost:${PORT}/`);

});

Tieni presente che PORT è impostato sul valore 8080

Genera manifest

Skaffold fornisce strumenti integrati per semplificare lo sviluppo dei container. In questo passaggio inizializzarai skaffold, che creerà automaticamente i file YAML di base di Kubernetes. Esegui il comando seguente per iniziare il processo.

Esegui questo comando nel terminale

skaffold init --generate-manifests

Quando richiesto:

  • Inserisci 8080 per la porta.
  • Inserisci y per salvare la configurazione

Alla visualizzazione dell'area di lavoro vengono aggiunti due file, skaffold.yaml e deployment.yaml

Aggiorna il nome dell'app

I valori predefiniti inclusi nella configurazione al momento non corrispondono al nome dell'applicazione. Aggiorna i file in modo che facciano riferimento al nome dell'applicazione anziché ai valori predefiniti.

  1. Modifica le voci nella configurazione Skaffold
  • Apri skaffold.yaml
  • Seleziona il nome dell'immagine attualmente impostato su package-json-image
  • Fai clic con il tasto destro del mouse e scegli Modifica tutte le occorrenze
  • Digita il nuovo nome come mynodejsapp.
  1. Modifica le voci nella configurazione di Kubernetes
  • Apri file deployment.yaml
  • Seleziona il nome dell'immagine attualmente impostato su package-json-image
  • Fai clic con il tasto destro del mouse e scegli Modifica tutte le occorrenze
  • Digita il nuovo nome come mynodejsapp.

Nota che nel file skaffold.yaml, la sezione build utilizza buildpacks per containerizzare l'applicazione. Questo codice non contiene Dockerfile e lo sviluppatore non ha bisogno di alcuna conoscenza di Docker per containerizzare questa applicazione.

Inoltre, la sincronizzazione a caldo viene abilitata automaticamente tra l'editor e il container in esecuzione da questa configurazione skaffold. Non è richiesta alcuna configurazione aggiuntiva per abilitare la sincronizzazione a caldo.

4. Panoramica del processo di sviluppo

In questa sezione analizzerai alcuni passaggi utilizzando il plug-in Cloud Code per apprendere i processi di base e convalidare la configurazione della tua applicazione iniziale.

Cloud Code si integra con skaffold per semplificare il processo di sviluppo. Quando esegui il deployment su GKE nei passaggi seguenti, Cloud Code e Skaffold creano automaticamente l'immagine container, ne eseguono il push a un Container Registry e quindi il deployment dell'applicazione su GKE. Ciò avviene dietro le quinte, astraendo i dettagli dal flusso degli sviluppatori. Cloud Code migliora inoltre il processo di sviluppo fornendo funzionalità tradizionali di debug e sincronizzazione a caldo allo sviluppo basato su container.

Eseguire il deployment in Kubernetes

  1. Nel riquadro nella parte inferiore dell'editor di Cloud Shell, seleziona Cloud Code }.{/

fdc797a769040839.png

  1. Nel riquadro visualizzato in alto, seleziona Esegui su Kubernetes. Se richiesto, seleziona Sì per utilizzare il contesto Kubernetes attuale.

cfce0d11ef307087.png

  1. La prima volta che esegui il comando, nella parte superiore dello schermo viene visualizzato un prompt che chiede se vuoi il contesto attuale di Kubernetes. Seleziona "Sì". per accettare e utilizzare il contesto corrente.

817ee33b5b412ff8.png

  1. A seguire, viene visualizzato un prompt in cui si chiede quale Container Registry utilizzare. Premi Invio per accettare il valore predefinito fornito

eb4469aed97a25f6.png

  1. Seleziona la scheda Output nel riquadro inferiore per visualizzare l'avanzamento e le notifiche

f95b620569ba96c5.png

  1. Seleziona "Kubernetes: Esegui/Debug - Dettagliato" nel menu a discesa del canale a destra per visualizzare ulteriori dettagli e i log trasmessi in live streaming dai container

94acdcdda6d2108.png

  1. Torna alla visualizzazione semplificata selezionando "Kubernetes: Run/Debug" dal menu a discesa
  2. Una volta completati la build e i test, la scheda Output riporta il seguente messaggio: Resource deployment/mynodejsapp status completed successfully e un URL: "Forwarded URL from service demo-app: http://localhost:8080"
  3. Nel terminale Cloud Code, passa il mouse sopra l'URL nell'output (http://localhost:8080), quindi nella descrizione comando visualizzata seleziona Apri anteprima web.

La risposta sarà:

{"message":"Greetings from Node"}

Ricarica a caldo

  1. Vai a src/index.js. Modifica il codice del messaggio di benvenuto in 'Hello from Node'

Nota immediatamente che nella finestra Output, nella visualizzazione Kubernetes: Run/Debug, il visualizzatore sincronizza i file aggiornati con il container in Kubernetes

Update initiated
File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Update succeeded
  1. Se passi alla visualizzazione Kubernetes: Run/Debug - Detailed, noterai che riconosce le modifiche apportate ai file e riavvia il nodo
files modified: [src/index.js]
Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Watching for changes...
[mynodejsapp]
[mynodejsapp]> mynodejsapp@1.0.0 start /workspace
[mynodejsapp]> node src/index.js
[mynodejsapp]
[mynodejsapp]Server running at: http://localhost:8080/
  1. Aggiorna il browser per visualizzare i risultati aggiornati.

Debug

  1. Vai alla visualizzazione debug e interrompi il thread corrente 647213126d7a4c7b.png.
  2. Fai clic su Cloud Code nel menu in basso e seleziona Debug on Kubernetes per eseguire l'applicazione in modalità debug.
  • Nella visualizzazione Kubernetes Run/Debug - Detailed della finestra Output, nota che skaffold eseguirà il deployment di questa applicazione in modalità di debug.
  • La creazione e il deployment dell'applicazione impiegheranno un paio di minuti. Questa volta è presente un debugger.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229
[mynodejsapp]Debugger attached.
  1. La barra di stato in basso cambia colore da blu ad arancione per indicare che è in modalità di debug.
  2. Nella vista Kubernetes Run/Debug, nota che è stato avviato un container di cui è possibile eseguire il debug
**************URLs*****************
Forwarded URL from service mynodejsapp-service: http://localhost:8080
Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default)
Update succeeded
***********************************

Utilizza i punti di interruzione

  1. Apri src/index.js
  2. Individua l'istruzione var message="Greetings from Node";.
  3. Aggiungi un punto di interruzione alla riga facendo clic sullo spazio vuoto a sinistra del numero di riga. Viene visualizzato un indicatore rosso per indicare che il punto di interruzione è impostato
  4. Ricarica il browser e nota che il debugger interrompe il processo in corrispondenza del punto di interruzione e ti consente di esaminare le variabili e lo stato dell'applicazione in esecuzione da remoto in GKE
  5. Fai clic verso il basso nella sezione Variabili finché non trovi la variabile "message".
  6. Esegui la linea premendo su Passaggio successivo 7cfdee4fd6ef5c3a.png
  7. Osserva il valore attuale della variabile "message" cambiato in "Greetings from Node"
  8. Fai doppio clic sul nome della variabile "target" e, nel popup, modifica il valore in modo diverso, ad esempio "Hello from Node".
  9. Fai clic sul pulsante Continua nel pannello di controllo del debug
  10. Esamina la risposta nel browser, che ora mostra il valore aggiornato che hai appena inserito.
  11. Interrompi il "Debug" premendo il pulsante di interruzione 647213126d7a4c7b.png e rimuovere il punto di interruzione facendo di nuovo clic sul punto di interruzione.

5. Sviluppo di un servizio REST CRUD semplice

A questo punto la tua applicazione è completamente configurata per lo sviluppo containerizzato e hai seguito il flusso di lavoro di sviluppo di base con Cloud Code. Nelle sezioni seguenti metterai in pratica ciò che hai imparato aggiungendo endpoint di servizio REST che si connettono a un database gestito in Google Cloud.

Configura le dipendenze

Il codice dell'applicazione utilizza un database per rendere persistenti i dati del servizio rimanenti. Assicurati che le dipendenze siano disponibili aggiungendo quanto segue nel file package.json

  1. Aggiungi altre due dipendenze pg e sequelize al file package.json per creare un'applicazione CRUD Postgres. Il caricamento delle modifiche, la sezione delle dipendenze sarà simile a questa.
    "dependencies": {
    "express": "^4.16.4",
    "pg": "^8.7.3",
    "sequelize": "^6.17.0"
  }

Codifica il servizio REST

  1. Aggiungi il codice dell'applicazione CRUD a questa applicazione
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip

unzip app.zip

Questo codice ha

  • Cartella models con il modello di entità per item
  • Cartella controllers con il codice che esegue le operazioni CRUD
  • La cartella routes che instrada pattern URL specifici a chiamate diverse
  • Cartella config con i dettagli della connettività del database
  1. Tieni presente che la configurazione del database nel file db.config.js si riferisce alle variabili di ambiente che devono essere fornite per connettersi al database. Inoltre, devi analizzare la richiesta in entrata per verificare la codifica dell'URL.
  2. Aggiungi il seguente snippet di codice in src/index.js per poterti connettere al codice CRUD dal file JavaScript principale subito prima dell'ultima sezione che inizia con app.listen(PORT, () => {
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
 bodyParser.urlencoded({
   extended: true,
 })
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
  1. Modifica il deployment nel file deployment.yaml per aggiungere le variabili di ambiente in modo da fornire le informazioni sulla connettività del database.

Aggiorna la voce della specifica alla fine del file in modo che corrisponda alla definizione seguente

    spec:
      containers:
      - name: mynodejsapp
        image: mynodejsapp
        env:
        - name: DB_HOST
          value: ${DB_INSTANCE_IP}        
        - name: DB_PORT
          value: "5432"  
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: database
  1. Sostituisci il valore DB_HOST con l'indirizzo del tuo database
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
    --format=json | jq \
    --raw-output ".ipAddresses[].ipAddress")

envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml

Esegui il deployment e convalida l'applicazione

  1. Nel riquadro nella parte inferiore dell'editor di Cloud Shell, seleziona Cloud Code, quindi Debug on Kubernetes nella parte superiore dello schermo.
  2. Una volta completati la build e i test, la scheda Output riporta il seguente messaggio: Resource deployment/mynodejsapp status completed successfully e un URL: "Forwarded URL from service mynodejsapp: http://localhost:8080"
  3. Aggiungi un paio di elementi.

Dal terminale Cloudshell, esegui i comandi seguenti

URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
  1. Testa il metodo GET eseguendo $URL/items nel browser. Puoi anche eseguire il comando curl dalla riga di comando
curl -X GET $URL/items
  1. Verifica eliminazione: ora prova a eliminare un elemento eseguendo l'operazione. Modifica il valore dell'ID articolo, se necessario.
curl -X DELETE $URL/items/1
    This throws an error message
{"message":"Could not delete Item with id=[object Object]"}

Identifica e risolvi il problema

  1. Riavvia l'applicazione in modalità di debug e individua il problema. Ecco alcuni suggerimenti:
  • Sappiamo che qualcosa non va con DELETE perché non restituisce il risultato desiderato. Devi quindi impostare il punto di interruzione nel metodo itemcontroller.js->exports.delete.
  • Esegui l'esecuzione passo passo e osserva le variabili in ogni passaggio per osservare i valori delle variabili locali nella finestra di sinistra.
  • Per osservare valori specifici come request.params, aggiungi questa variabile alla finestra di visualizzazione.
  1. Tieni presente che il valore assegnato a id è undefined. Modifica il codice per risolvere il problema.

Lo snippet di codice corretto avrà il seguente aspetto.

// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
    const id = req.params.id;
  1. Una volta riavviata l'applicazione, riprova a eliminarla.
  2. Interrompi la sessione di debug facendo clic sul quadrato rosso nella barra degli strumenti di debug 647213126d7a4c7b.png

6. Esegui la pulizia

Complimenti! In questo lab hai creato da zero una nuova applicazione Nodejs e l'hai configurata per funzionare in modalità di deployment a caldo con i container. Hai quindi eseguito il deployment dell'applicazione ed eseguito il debug in un cluster GKE remoto seguendo lo stesso flusso di sviluppatori che si trova negli stack di applicazioni tradizionali.

Per eseguire la pulizia dopo aver completato il lab:

  1. Elimina i file utilizzati nel lab
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
  1. Elimina il progetto per rimuovere tutte le infrastrutture e le risorse correlate