Esegui JanusGraph su GKE con Bigtable

I database di grafo possono aiutarti a scoprire informazioni modellando le entità dei dati e le relazioni tra di loro. JanusGraph è un database di grafici che supporta il lavoro con grandi quantità di dati. Questo tutorial mostra come eseguire JanusGraph su Google Cloud con Google Kubernetes Engine come piattaforma di orchestrazione e Bigtable come backend per lo stoccaggio. Il tutorial è rivolto ad architetti di sistema, amministratori di database e professionisti DevOps interessati a eseguire il database grafico JanusGraph su Google Cloud utilizzando un database gestito come backend di archiviazione. Si presume che tu abbia familiarità con Google Kubernetes Engine (GKE), i pod Kubernetes, i grafici Helm, Bigtable e Elasticsearch. La conoscenza del framework di calcolo di Apache TinkerPop e del linguaggio e della macchina di attraversamento dei grafici di Gremlin non è obbligatoria, ma è necessaria per utilizzare Janusgraph oltre gli esempi forniti in questo tutorial.

Panoramica

Nella terminologia dei grafici, le entità sono chiamate nodi o vertici e le relazioni sono chiamate archi. In JanusGraph, sia i vertici sia gli archi possono avere dati associati aggiuntivi resi disponibili tramite le proprietà.

Esempio di grafico delle proprietà.

L'illustrazione precedente è un esempio di grafico delle proprietà.

I database di grafo ti aiutano a modellare una serie di domini e attività:

  • Social network
  • Transazioni finanziarie (per l'analisi delle frodi)
  • Reti di sistema fisiche o virtuali

Quando crei database di grafici, a volte crei milioni o addirittura miliardi di vertici ed elementi. Quando utilizzi JanusGraph con Bigtable come livello di archiviazione sottostante, puoi eseguire query rapide (chiamate percorsi del grafo) e scalare il livello di archiviazione in modo indipendente in base alle dimensioni e al throughput di cui hai bisogno. JanusGraph utilizza anche un backend di indicizzazione pluggable per fornire l'indicizzazione integrale delle proprietà di vertici e archi. In questo tutorial esegui il deployment di un'infrastruttura JanusGraph scalabile su GKE. Utilizzi Elasticsearch come backend di indicizzazione in esecuzione nei pod di un StatefulSet e Bigtable come backend di archiviazione. Al termine, puoi esaminare le relazioni esistenti nei dati del grafico. Il seguente diagramma mostra l'interazione tra questi elementi.

Deployment di JanusGraph con Bigtable su GKE.

Il diagramma seguente mostra il deployment di JanusGraph su GKE con Elasticsearch e Bigtable.

Dati di JanusGraph in Bigtable

I dati del grafico vengono archiviati da JanusGraph come elenco di adiacenze. Ogni riga rappresenta un vertice, eventuali vertici adiacenti (lati) e i metadati della proprietà relativi ai vertici e ai lati. La chiave di riga è l'identificatore univoco del vertice. Ogni relazione tra un vertice e un altro vertice e le eventuali proprietà che definiscono ulteriormente la relazione vengono memorizzate come colonna di un arco o di una proprietà dell'arco. Sia il qualificatore di colonna sia il valore della colonna memorizzano i dati che definiscono l'edge, in conformità con le best practice di Bigtable. Ogni proprietà del vertice viene archiviata come colonna separata, utilizzando ancora il qualificatore di colonna e il valore della colonna per definire la proprietà.

Il seguente diagramma mostra questa struttura di archiviazione.

Struttura di archiviazione dell'elenco di adiacenze di JanusGraph.

Il diagramma mostra la struttura di archiviazione logica per un piccolo frammento di grafico con dettagli logici per due righe di vertici. Nel diagramma, le due righe di esempio rappresentano due vertici. Il primo vertice è etichettato con una singola proprietà vertice ed è collegato ad altri due vertici da due spigoli distinti. Il secondo vertice contiene colonne contenenti due proprietà e un arco.

La seguente illustrazione del modello dei dati logico dell'elemento vertex edge fornisce alcuni dettagli sui valori e sui qualificatori di colonna per una colonna edge o edge-property.

Colonna degli spigoli e delle proprietà degli spigoli di JanusGraph.

Per ogni vertice adiacente, una colonna memorizza i metadati relativi all'elemento adiacente. Il qualificatore di colonna contiene metadati sulla relazione tra gli spigoli e sulla direzione degli spigoli, nonché un puntatore al vertice adiacente. Il valore della colonna contiene l'etichetta dell'arco e eventuali proprietà aggiuntive dell'arco. Poiché le esplorazioni possono essere seguite in entrambe le direzioni, gli spigoli vengono memorizzati due volte, una per ogni estremità della relazione tra gli spigoli. Lo spazio di archiviazione perimetrale bidirezionale aumenta notevolmente le prestazioni di attraversamento, ma comporta alcuni compromessi dovuti alla ridondanza dello spazio di archiviazione aggiuntivo e alle mutazioni dei bordi non atomiche.

Il seguente diagramma mostra il modello dei dati logico di una colonna della proprietà del vertice.

Valori delle colonne JanusGraph per una colonna di proprietà.

L'illustrazione precedente fornisce dettagli sui qualificatori e sugli valori delle colonne per una colonna laterale.

Ogni proprietà del vertice viene archiviata come colonna separata. Il qualificatore di colonna è un identificatore univoco per la chiave della proprietà. Il valore della colonna contiene sia un identificatore per la proprietà sia il valore della proprietà.

JanusGraph si basa anche sull'ordinamento alfabetico di Bigtable delle righe e dei qualificatori di colonna per migliorare le prestazioni delle query.

Obiettivi

  • Crea un'istanza Bigtable.
  • Crea un cluster GKE.
  • Installa Helm.
  • Utilizza un grafico Helm per eseguire il deployment di JanusGraph e Elasticsearch.
  • Utilizza la console Gremlin e connettiti a JanusGraph.
  • Carica ed esegui query sui dati di esempio.

Costi

In questo documento utilizzi i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi basata sull'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud potrebbero essere idonei per una prova gratuita.

Al termine delle attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la sezione Pulizia.

Prerequisiti

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Bigtable, Compute Engine, and GKE APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Bigtable, Compute Engine, and GKE APIs.

    Enable the APIs

prepara l'ambiente

In questo tutorial utilizzerai Cloud Shell per inserire i comandi. Cloud Shell ti consente di accedere alla riga di comando nella console Google Cloud e include Google Cloud CLI e altri strumenti necessari per lo sviluppo in Google Cloud. Cloud Shell viene visualizzato come finestra nella parte inferiore della console Google Cloud. L'inizializzazione può richiedere diversi minuti, ma la finestra viene visualizzata immediatamente.

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  2. In Cloud Shell, imposta le variabili di ambiente per la zona Compute Engine in cui creerai il cluster Bigtable e il cluster GKE, nonché il nome, il tipo di nodo e la versione per il cluster GKE:

    export PROJECT_ID=PROJECT_ID
    export GCP_ZONE=REGION
    export GKE_CLUSTER_NAME=GKE_CLUSTER_NAME
    export GKE_NODE_TYPE=n1-standard-4
    export GKE_VERSION=1.20
    

    Sostituisci quanto segue:

    • PROJECT_ID con l'identificatore del progetto.
    • REGION con la zona in cui verranno creati il cluster Bigtable e il cluster GKE.
    • GKE_CLUSTER_NAME con il nome del cluster GKE.

    Il comando dovrebbe essere simile al seguente esempio:

    export PROJECT_ID=bt-janusgraph-project-id
    export GCP_ZONE=us-central1-f
    export GKE_CLUSTER_NAME=janusgraph-gke
    export GKE_NODE_TYPE=n1-standard-4
    export GKE_VERSION=1.20
    
  3. Crea un cluster GKE in cui verrà eseguito il deployment di JanusGraph:

    gcloud container clusters create ${GKE_CLUSTER_NAME} \
        --zone=${GCP_ZONE} \
        --cluster-version=${GKE_VERSION} \
        --machine-type ${GKE_NODE_TYPE} \
        --scopes "https://www.googleapis.com/auth/cloud-platform"
    

Crea un'istanza Bigtable

Per il backend dello spazio di archiviazione di JanusGraph, questo tutorial utilizza Bigtable, che può scalare rapidamente per soddisfare le tue esigenze. Questo tutorial utilizza un cluster con un solo nodo, che è economico e sufficiente per il tutorial. Puoi iniziare i tuoi progetti con un cluster più piccolo e poi passare a un cluster più grande quando è tutto pronto per lavorare con i dati di produzione. La documentazione di Bigtable include una discussione dettagliata su prestazioni e scalabilità per aiutarti a scegliere le dimensioni del cluster per il tuo lavoro.

  1. In Cloud Shell, imposta la variabile di ambiente per l'identificatore dell'istanza Bigtable:

    export BIGTABLE_INSTANCE_ID=BIGTABLE_INSTANCE_ID
    

    Sostituisci BIGTABLE_INSTANCE_ID con l'identificatore per la tua istanza Bigtable.

  2. Crea l'istanza Bigtable:

    gcloud bigtable instances create ${BIGTABLE_INSTANCE_ID} \
        --cluster-config=id=${BIGTABLE_INSTANCE_ID}-${GCP_ZONE},zone=${GCP_ZONE},nodes=1 \
        --display-name=${BIGTABLE_INSTANCE_ID}-${GCP_ZONE}
    

Installa e configura Helm

Utilizzi Helm per eseguire il deployment delle applicazioni nel cluster Kubernetes. In questo tutorial, utilizzerai Helm per eseguire il deployment dei servizi JanusGraph ed Elasticsearch sul tuo cluster GKE.

  1. In Cloud Shell, installa Helm:

    curl -fsSL -o get_helm.sh \
        https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
    chmod 700 get_helm.sh
    DESIRED_VERSION=v3.5.0 ./get_helm.sh
    
  2. Aggiungi il repository dei grafici elastic in modo che la dipendenza del grafico Elasticsearch possa essere trovata durante il deployment del grafico JanusGraph:

    helm repo add elastic https://helm.elastic.co
    

    Questo repository di grafici è ospitato da Elastic, i creator di Elasticsearch.

Utilizzare Helm per installare JanusGraph ed Elasticsearch

In questa sezione utilizzerai un grafico Helm per eseguire il deployment di JanusGraph e Elasticsearch nel tuo cluster Kubernetes.

Il grafico Helm viene estratto da GitHub. Il deployment incluso nel repository dei grafici Helm esegue il deployment di un insieme di tre pod JanusGraph dietro un servizio che avvierà un bilanciatore del carico delle applicazioni interno. Quando i pod sono in esecuzione, i probe di avvio e di attività inviano richieste HTTP per eseguire controlli di integrità sul server JanusGraph su ogni pod. Inoltre, il grafico include un grafico delle dipendenze fornito da Elastic che consente di eseguire il deployment di tre pod Elasticsearch in un StatefulSet.

  1. In Cloud Shell, imposta le variabili di ambiente per i nomi di Helm e JanusGraph:

    export HELM_REPO=bigtable-janusgraph-helm
    export JANUSGRAPH_VERSION=0.5.3
    export HELM_CHART_RELEASE_VERSION=1
    export HELM_CHART_RELEASE_TAG=${JANUSGRAPH_VERSION}-${HELM_CHART_RELEASE_VERSION}
    export HELM_CHART_RELEASE_TAG_HASH=f8b271a4854d4a553dd5e9ba014d077fb098d9ab
    export HELM_CHART_NAME=janusgraph-bigtable
    
  2. Estrai il grafico Helm da GitHub:

    git clone https://github.com/GoogleCloudPlatform/${HELM_REPO} \
       --branch ${HELM_CHART_RELEASE_TAG}
    
  3. Vai alla directory del grafico Helm:

    cd ${HELM_REPO}
    
  4. Per motivi di sicurezza, verifica utilizzando l'hash del commit:

    HEAD_COMMIT_HASH=$(git rev-parse --verify HEAD)
    if [ _${HEAD_COMMIT_HASH} == _${HELM_CHART_RELEASE_TAG_HASH} ]
    then
        echo "Commit hash verified"
    fi
    

    Se l'output non è simile al seguente, non procedere poiché l'integrità del tag clonato non è stata verificata.

    Commit hash verified
    
  5. Aggiorna le dipendenze del grafico:

    helm dep update
    
  6. Vai alla directory principale:

    cd ..
    
  7. Imposta le variabili di ambiente per i nomi delle entità Helm e JanusGraph:

    export HELM_RELEASE_NAME=janusgraph-bigtable-elastic
    export ELASTICSEARCH_CLUSTER_NAME=${HELM_RELEASE_NAME}-elasticsearch
    export BIGTABLE_JANUSGRAPH_TABLE=janusgraph-table
    
  8. Crea un file values.yaml, che fornisce a Helm le proprietà di configurazione da utilizzare per il deployment del grafico JanusGraph:

    cat > values.yaml << EOF
    
    image:
      repository: docker.io/janusgraph/janusgraph
      tag: 0.5.3
      pullPolicy: IfNotPresent
    
    replicaCount: 3
    
    service:
      type: LoadBalancer
      port: 8182
      serviceAnnotations:
        networking.gke.io/load-balancer-type: "Internal"
    
    elasticsearch:
      deploy: true
      clusterName: ${ELASTICSEARCH_CLUSTER_NAME}
    
    properties:
      storage.backend: hbase
      storage.directory: null
      storage.hbase.ext.google.bigtable.instance.id: ${BIGTABLE_INSTANCE_ID}
      storage.hbase.ext.google.bigtable.project.id: ${PROJECT_ID}
      storage.hbase.ext.hbase.client.connection.impl: com.google.cloud.bigtable.hbase2_x.BigtableConnection
      storage.hbase.short-cf-names: true
      storage.hbase.table: ${BIGTABLE_JANUSGRAPH_TABLE}
      index.search.backend: elasticsearch
      index.search.hostname: ${ELASTICSEARCH_CLUSTER_NAME}-master
      index.search.directory: null
      index.search.elasticsearch.health-request-timeout: 90s
      cache.db-cache: true
      cache.db-cache-clean-wait: 20
      cache.db-cache-time: 180000
      cache.db-cache-size: 0.5
      cluster.max-partitions: 1024
      graph.replace-instance-if-exists: true
    
    persistence:
      enabled: false
    
    debugLevel: INFO
    EOF
    
  9. Esegui il deployment del grafico Helm di JanusGraph utilizzando il file values.yaml che hai creato:

    helm upgrade --install \
                 --wait \
                  --timeout 600s \
                  ${HELM_RELEASE_NAME} \
                  ./${HELM_REPO} \
                  -f values.yaml
    

    Il processo di installazione attende che tutte le risorse siano pronte prima di completarsi. L'operazione potrebbe richiedere diversi minuti.

Verifica il deployment di JanusGraph

Al termine del processo di installazione di Helm, viene visualizzata una sezione NOTES che descrive un'esperienza di inizio. Puoi seguire i passaggi descritti nella sezione NOTES per verificare che l'ambiente JanusGraph funzioni.

  1. In Cloud Shell, verifica che i componenti del grafico Helm siano stati dipiamente in GKE:

    1. Controlla il deployment di JanusGraph:

      kubectl get deployments
      

      Se il deployment è riuscito, l'output è il seguente:

      NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
      janusgraph-bigtable-elastic   3/3     3            3           3m28s
      
    2. Controlla il StatefulSet Elasticsearch:

      kubectl get statefulsets
      

      Se tutto funziona, l'output è il seguente:

      NAME                                               READY   AGE
      janusgraph-bigtable-elastic-elasticsearch-master   3/3     4m13s
      
  2. Imposta una variabile di ambiente sul nome di un pod Kubernetes su cui è in esecuzione il server Gremlin di JanusGraph. L'etichetta app per il pod che esegue il server Gremlin è ricavata dal nome del grafico Helm definito nel file Chart.yaml.

    export APP_LABEL_FROM_CHART_NAME=${HELM_CHART_NAME}
    export POD_NAME=$(kubectl get pods \
                         --namespace default \
                         -l "app=${APP_LABEL_FROM_CHART_NAME}, \
                             release=${HELM_RELEASE_NAME}" \
                         -o jsonpath="{.items[0].metadata.name}")
    
  3. Connettiti al pod ed esegui la console Gremlin, una shell REPL (read eval print loop). Il nome del contenitore è anche dedotto dal nome del diagramma Helm in Chart.yaml.

    export GREMLIN_CONTAINER=${HELM_CHART_NAME}
    kubectl exec \
            -c ${GREMLIN_CONTAINER} \
            -it $POD_NAME \
            -- /opt/janusgraph/bin/gremlin.sh
    
  4. Nella console Gremlin, connettiti al server Apache TinkerPop:

    1. Avvia la sessione:

      :remote connect tinkerpop.server conf/remote.yaml session
      

      L'output è simile al seguente:

      ==>Configured localhost/127.0.0.1:8182-[b08972f2-a2aa-4312-8018-bcd11bc9812c]
      
    2. Connettiti al server:

      :remote console
      

      L'output è simile al seguente:

      ==>All scripts will now be sent to Gremlin Server - [localhost/127.0.0.1:8182]-[b08972f2-a2aa-4312-8018-bcd11bc9812c] - type ':remote console' to return to local mode>
      
  5. Nella console Gremlin, verifica che il server Gremlin funzioni correttamente esaminando la variabile graph che rappresenta l'istanza del grafo:

    graph
    

    L'output indica che il server JanusGraph è in esecuzione con un database compatibile con HBase, in questo caso Bigtable, come backend di archiviazione.

    ==>standardjanusgraph[hbase:[127.0.0.1]]
    
  6. In Gremlin, crea due vertici

    v1 = graph.addVertex(label, 'hello')
    v2 = graph.addVertex(label, 'world')
    

    Se l'output della console è simile al seguente, significa che i due vertici sono stati aggiunti:

    ==>v[4344]
    ==>v[4152]
    
  7. Crea un bordo che colleghi i due vertici:

    v1.addEdge('followedBy', v2)
    

    Se l'output della console è simile al seguente, indica che è stato aggiunto il segmento tra i due vertici:

    ==>e[17j-3co-4fmd-oe054][4344-followedBy->4152]
    
  8. Esegui il commit della transazione:

    graph.tx().commit()
    

    Se l'output della console è null, indica che le operazioni sono state committate:

    ==>null
    

    Il seguente diagramma illustra il grafico creato dai comandi.

    Esempi di vertici ed spigoli di JanusGraph.

    Il vertice etichettato hello è collegato da un bordo diretto etichettato followedBy al vertice etichettato world.

  9. Esegui una query Gremlin per vedere qual è l'etichetta del vertice che segue un bordo etichettato followedBy dal vertice etichettato hello:

    g.V().has(label, 'hello').out('followedBy').label()
    

    La sintassi delle query è spiegata nella sezione successiva. Per il momento, viene visualizzata la parola world come output della query:

    ==>world
    

Carica ed esegui query su un set di dati di esempio

Ora che hai eseguito il deployment di JanusGraph e puoi connetterti utilizzando Gremlin, puoi iniziare a caricare e eseguire query sui tuoi dati. Per capire come funziona questa procedura, carica il set di dati di esempio fornito in bundle con JanusGraph, ovvero il Graph of the Gods, che raffigura le divinità mitologiche del pantheon romano e le relative proprietà di posizione.

  1. In Gremlin, carica il grafo creato in precedenza:

    GraphOfTheGodsFactory.load(graph)
    

    L'output è il seguente:

    ==>null
    
  2. Esegui una query di attraversamento del grafo che trovi tutti i fratelli di Giove:

    g.V().has('name', 'jupiter').out('brother').values('name')
    

    La seguente tabella spiega i passaggi attraversati dalla query.

    Passaggio di attraversamento Spiegazione
    g.V() Inizia con la raccolta dei vertici.
    has('name', 'jupiter') Trova una proprietà name con il valore jupiter.
    out('brother') Da qui, segui gli spigoli etichettati come brother.
    values('name') Per i vertici a cui portano questi spigoli, recupera la proprietà name.
    L'output è il seguente:

    ==>neptune
    ==>pluto
    

    Per acquisire familiarità con le query di attraversamento possibili in questo set di dati Graph of the Gods, prova altre query di esempio riportate nella documentazione di JanusGraph.

Verificare che i dati siano archiviati in Bigtable

Ora che hai creato alcuni dati di esempio nel tuo cluster JanusGraph, puoi verificare che Bigtable sia stato utilizzato come backend di archiviazione.

  1. Chiudi la console Gremlin:

    :q
    
  2. In Cloud Shell, verifica che i dati siano stati mantenuti nella tabella janusgraph in Bigtable:

    cbt -project=${PROJECT_ID} \
        -instance=${BIGTABLE_INSTANCE_ID} \
         count ${BIGTABLE_JANUSGRAPH_TABLE}
    

    L'output è simile al seguente.

    2021/03/02 02:32:19 -creds flag unset, will use gcloud credential
    101
    

    Il valore 101 nell'output rappresenta il numero di righe in janusgraph table e potrebbe essere diverso per te.

Verifica la creazione dell'indice di ricerca in Elasticsearch

  1. In Cloud Shell, imposta le variabili per l'indice e il nome del pod Elasticsearch:

    export ELASTICSEARCH_POD_ORDINAL=0
    export ELASTICSEARCH_POD_NAME_ROOT=${ELASTICSEARCH_CLUSTER_NAME}-master
    export ELASTICSEARCH_POD=${ELASTICSEARCH_POD_NAME_ROOT}-0
    

    I nomi dei pod Elasticsearch sono definiti dalle dipendenze Helm di Elasticsearch. I nomi dei pod sono costituiti dal nome del cluster fornito nel file values.yaml che hai creato, dalla parola master e da un numero ordinale con indice zero, il tutto separato da trattini. Per questo passaggio, scegli il primo pod, rappresentato come zero (0).

  2. Utilizza l'API REST Elasticsearch Aliases per ispezionare gli indici:

    kubectl exec \
            -c elasticsearch \
            -it ${ELASTICSEARCH_POD} \
            --  \
            curl -XGET "127.0.0.1:9200/_aliases?pretty=true";
    

    L'output mostra che JanusGraph ha creato due indici, janusgraph_vertices e janusgraph_edges, per fornire ricerche efficienti utilizzando le proprietà dei vertici e degli archi:

    {
      "janusgraph_vertices" : {
        "aliases" : {
          "janusgraph" : { }
        }
      },
      "janusgraph_edges" : {
        "aliases" : {
          "janusgraph" : { }
        }
      }
    }
    
  3. Esegui query sui valori di uno degli indici utilizzando l'API REST di Elasticsearch Search:

    kubectl exec \
           -c elasticsearch \
           -it ${ELASTICSEARCH_POD} \
           --  \
           curl -XGET "127.0.0.1:9200/janusgraph_edges/_search?pretty=true&q=*";
    

    I risultati di ricerca mostrano che ci sono voci negli indici creati da JanusGraph. L'output visualizzato è simile ai seguenti risultati troncati, che mostrano che sono presenti voci nell'indice janusgraph_edges.

    {
     "took" : 94,
     "timed_out" : false,
     "_shards" : {
       "total" : 1,
       "successful" : 1,
       "skipped" : 0,
       "failed" : 0
     },
     "hits" : {
       "total" : {
         "value" : 6,
         "relation" : "eq"
       },
       "max_score" : 1.0,
       "hits" : [
         {
           "_index" : "janusgraph_edges",
           "_type" : "_doc",
           "_id" : "6bvp-5ovc-b2t-2yko",
           "_score" : 1.0,
           "_source" : {
             "reason" : "loves waves"
           }
         },
         {
    …
    

Elimina il progetto

Per evitare che al tuo Account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Passaggi successivi