Esegui il deployment di un database vettoriale PostgreSQL su GKE


Questo tutorial mostra come eseguire il deployment di un file PostgreSQL di database vettoriale su Google Kubernetes Engine (GKE).

PostgreSQL include una serie di moduli ed estensioni che estendono le funzionalità del database. In questo tutorial installerai l'estensione pgvector su un cluster PostgreSQL esistente di cui è stato eseguito il deployment su GKE. La L'estensione Pgvector consente di archiviare i vettori nelle tabelle del database aggiungendo il vettore a PostgreSQL. Pgvector fornisce anche ricerche di somiglianza eseguendo query SQL.

Semplifichiamo il deployment dell'estensione PGvector eseguendo prima il deployment di CloudnativePG , in quanto l'operatore fornisce una versione in bundle dell'estensione.

Questo tutorial è destinato ad amministratori e architetti di piattaforme cloud, ML engineer e MLOps Professionisti (DevOps) interessati a eseguire il deployment di PostgreSQL cluster di database su GKE.

Obiettivi

In questo tutorial imparerai a:

  • Esegui il deployment dell'infrastruttura GKE per PostgreSQL.
  • Installa l'estensione pgvector sul cluster PostgreSQL di cui è stato eseguito il deployment con GKE.
  • Esegui il deployment e la configurazione dell'operatore PostgreSQL di CloudnativePG con Helm.
  • Carica un set di dati demo ed esegui query di ricerca con il blocco note Jupyter.

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.

Prima di iniziare

In questo tutorial utilizzerai Cloud Shell per . Cloud Shell è un ambiente shell per la gestione di risorse ospitate su Google Cloud. È preinstallato Google Cloud CLI, kubectl, Helm e Terraform a riga di comando. Se non utilizzi Cloud Shell, devi installare Google Cloud CLI.

  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. Install the Google Cloud CLI.
  3. To initialize the gcloud CLI, run the following command:

    gcloud init
  4. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

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

  6. Enable the Cloud Resource Manager, Compute Engine, GKE, and IAM Service Account Credentials APIs:

    gcloud services enable cloudresourcemanager.googleapis.com compute.googleapis.com container.googleapis.com iamcredentials.googleapis.com
  7. Install the Google Cloud CLI.
  8. To initialize the gcloud CLI, run the following command:

    gcloud init
  9. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

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

  11. Enable the Cloud Resource Manager, Compute Engine, GKE, and IAM Service Account Credentials APIs:

    gcloud services enable cloudresourcemanager.googleapis.com compute.googleapis.com container.googleapis.com iamcredentials.googleapis.com
  12. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/compute.securityAdmin, roles/compute.viewer, roles/container.clusterAdmin, roles/container.admin, roles/iam.serviceAccountAdmin, roles/iam.serviceAccountUser

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

Configura l'ambiente

Per configurare l'ambiente con Cloud Shell, segui questi passaggi:

  1. Imposta le variabili di ambiente per il progetto, la regione e un cluster Kubernetes prefisso risorsa cluster:

    export PROJECT_ID=PROJECT_ID
    export KUBERNETES_CLUSTER_PREFIX=postgres
    export REGION=us-central1
    
    • Sostituisci PROJECT_ID con il tuo Google Cloud dell'ID progetto.

    Questo tutorial utilizza la regione us-central1.

  2. Clona il repository di codice campione da GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  3. Vai alla directory postgres-pgvector:

    cd kubernetes-engine-samples/databases/postgres-pgvector
    

Crea l'infrastruttura del tuo cluster

In questa sezione eseguirai uno script Terraform per creare un cluster privato, cluster GKE a livello di regione per il deployment del database PostgreSQL.

Puoi scegliere di eseguire il deployment di PostgreSQL utilizzando un Cluster Standard o Autopilot. Ognuno di essi ha i suoi vantaggi e i propri modelli di determinazione dei prezzi.

Autopilot

Per eseguire il deployment dell'infrastruttura del cluster Autopilot, esegui questi comandi in Cloud Shell:

export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=../postgresql-cloudnativepg/terraform/gke-autopilot init
terraform -chdir=../postgresql-cloudnativepg/terraform/gke-autopilot apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}

GKE sostituisce le seguenti variabili in fase di runtime:

  • GOOGLE_OAUTH_ACCESS_TOKEN utilizza gcloud auth print-access-token per recuperare un token di accesso che autentica le interazioni con varie API Google Cloud
  • PROJECT_ID, REGION e KUBERNETES_CLUSTER_PREFIX sono l'ambiente definite nella sezione Configurare l'ambiente e assegnate alle nuove variabili pertinenti per il cluster Autopilot che stai creando.

Quando richiesto, digita yes.

Terraform crea le seguenti risorse:

  • Una rete VPC personalizzata e una subnet privata per i nodi Kubernetes.
  • Un router Cloud per accedere a internet tramite Network Address Translation (NAT).
  • Un cluster GKE privato nella regione us-central1.
  • Un elemento ServiceAccount con autorizzazioni di logging e monitoraggio per il cluster.
  • Configurazione di Google Cloud Managed Service per Prometheus per il monitoraggio e gli avvisi del cluster.

L'output è simile al seguente:

...
Apply complete! Resources: 11 added, 0 changed, 0 destroyed.
...

Standard

Per eseguire il deployment dell'infrastruttura del cluster Standard, esegui questi comandi in Cloud Shell:

export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=../postgresql-cloudnativepg/terraform/gke-standard init
terraform -chdir=../postgresql-cloudnativepg/terraform/gke-standard apply \
-var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}

GKE sostituisce le seguenti variabili in fase di runtime:

  • GOOGLE_OAUTH_ACCESS_TOKEN utilizza gcloud auth print-access-token per recuperare un token di accesso che autentica le interazioni con di varie API Google Cloud.
  • PROJECT_ID, REGION e KUBERNETES_CLUSTER_PREFIX sono le variabili di ambiente definita nella sezione Configurare l'ambiente e assegnata al nuovo e variabili pertinenti per il cluster standard che stai creando.

Quando richiesto, digita yes. Potrebbero essere necessari diversi minuti prima che questi comandi completata e affinché il cluster mostri lo stato Pronto.

Terraform crea le seguenti risorse:

  • Una rete VPC personalizzata e una subnet privata per i nodi Kubernetes.
  • Un router Cloud per accedere a internet tramite Network Address Translation (NAT).
  • Un cluster GKE privato nella regione us-central1 con scalabilità automatica abilitata (da uno a due nodi per zona).
  • Un elemento ServiceAccount con autorizzazioni di logging e monitoraggio per il cluster.
  • Configurazione di Google Cloud Managed Service per Prometheus per il monitoraggio e gli avvisi dei cluster.

L'output è simile al seguente:

...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...

Connettiti al cluster

Configura kubectl per recuperare le credenziali e comunicare con il nuovo cluster GKE:

gcloud container clusters get-credentials \
    ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION} --project ${PROJECT_ID}

Esegui il deployment dell'operatore Cloud NativePG

Esegui il deployment di Cloud NativePG nel tuo cluster Kubernetes utilizzando un grafico Helm:

  1. Controlla la versione di Helm:

    helm version
    

    Aggiorna la versione se è precedente alla 3.13:

    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
    
  2. Aggiungi il repository Helm Chart dell'operatore Cloud NativePG:

    helm repo add cnpg https://cloudnative-pg.github.io/charts
    
  3. Esegui il deployment dell'operatore Cloud NativePG utilizzando lo strumento a riga di comando Helm:

    helm upgrade --install cnpg \
        --namespace cnpg-system \
        --create-namespace \
        cnpg/cloudnative-pg
    

    L'output è simile al seguente:

    Release "cnpg" does not exist. Installing it now.
    NAME: cnpg
    LAST DEPLOYED: Fri Oct 13 13:52:36 2023
    NAMESPACE: cnpg-system
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    ...
    

Esegui il deployment del database vettoriale PostgreSQL

In questa sezione eseguirai il deployment del database vettoriale PostgreSQL.

  1. Crea uno spazio dei nomi pg-ns per il database:

    kubectl create ns pg-ns
    
  2. Applica il manifest per eseguire il deployment del cluster PostgreSQL. Il manifest del cluster abilita l'estensione pgvector.

    kubectl apply -n pg-ns -f manifests/01-basic-cluster/postgreSQL_cluster.yaml
    

    Il manifest postgreSQL_cluster.yaml descrive il deployment:

    apiVersion: postgresql.cnpg.io/v1
    kind: Cluster
    metadata:
      name: gke-pg-cluster
    spec:
      description: "Standard GKE PostgreSQL cluster"
      imageName: ghcr.io/cloudnative-pg/postgresql:16.2
      enableSuperuserAccess: true
      instances: 3
      startDelay: 300
      primaryUpdateStrategy: unsupervised
      postgresql:
        pg_hba:
          - host all all 10.48.0.0/20 md5
      bootstrap:
        initdb:
          postInitTemplateSQL:
            - CREATE EXTENSION IF NOT EXISTS vector;
          database: app
      storage:
        storageClass: premium-rwo
        size: 2Gi
      resources:
        requests:
          memory: "1Gi"
          cpu: "1000m"
        limits:
          memory: "1Gi"
          cpu: "1000m"
      affinity:
        enablePodAntiAffinity: true
        tolerations:
        - key: cnpg.io/cluster
          effect: NoSchedule
          value: gke-pg-cluster
          operator: Equal
        additionalPodAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app.component
                  operator: In
                  values:
                  - "pg-cluster"
              topologyKey: topology.kubernetes.io/zone
      monitoring:
        enablePodMonitor: true
  3. Controlla lo stato del cluster:

    kubectl get cluster -n pg-ns --watch
    

    Attendi che l'output mostri lo stato Cluster in healthy state prima di andare al passaggio successivo.

Carica il set di dati demo ed esegui query di ricerca con il blocco note Jupyter

In questa sezione, caricherai i vettori in una tabella PostgreSQL ed eseguirai query di ricerca semantiche utilizzando la sintassi SQL.

Nell'esempio seguente, usi un set di dati di un file CSV contenente un elenco di libri di generi diversi. Pgvector funge da motore di ricerca e il pod che crei serve un client che esegue query sul database PostgreSQL.

  1. Attendi che il pod PostgreSQL leader sia stato creato e pronto:

    while [[ $(kubectl get pod -l cnpg.io/cluster=gke-pg-cluster,role=primary -n pg-ns -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}') != "True" ]]; do
    sleep 5
    done
    
  2. Crea la ConfigMap con books-dataset ed esegui il pod Jupyter per interagire con il tuo cluster PostgreSQL:

    kubectl create -n pg-ns configmap books-dataset --from-file=manifests/02-notebook/dataset.csv
    kubectl create -n pg-ns configmap notebook --from-file=manifests/02-notebook/vector-database.ipynb
    kubectl apply -n pg-ns -f manifests/02-notebook/jupyter.yaml
    
    • Il secret denominato gke-pg-cluster-superuser creato da Cloud NativePG dell'operatore è montato il pod del client come variabili di ambiente denominate CLIENTUSERNAMEandCLIENTPASSWORD.
    • Il ConfigMap books-dataset contiene un file csv con i dati dei libri per PostgreSQL standard.
    • Il ConfigMap demo-app contiene codice Python per creare la tabella PostgreSQL da books-dataset.

    Il manifest jupyter.yaml descrive il deployment notebook e il relativo servizio:

    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels: &labels
        app: jupyter-notebook
      name: notebook
    spec:
      ports:
      - port: 8888
      selector: *labels
      type: LoadBalancer
      # type: ClusterIP
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: notebook
      labels: &labels
        app: jupyter-notebook
    spec:
      selector:
        matchLabels: *labels
      template:
        metadata: 
          labels: *labels
        spec:
          containers:
          - name: jupyter
            image: tensorflow/tensorflow:2.15.0-jupyter
            resources:
              requests:
                memory: "4500Mi"
                cpu: "1"
              limits:
                memory: "4500Mi"
                cpu: "1"
            ports:
            - containerPort: 8888
            env:
            - name: CLIENTPASSWORD
              valueFrom:
                secretKeyRef:
                  name: gke-pg-cluster-superuser
                  key: password
            - name: CLIENTUSERNAME
              valueFrom:
                secretKeyRef:
                  name: gke-pg-cluster-superuser
                  key: username
            volumeMounts:
            - name: books-dataset
              mountPath: /usr/local/dataset
            - name: notebook
              mountPath: /tf
          volumes:
          - name: books-dataset
            configMap:
              name: books-dataset
          - name: notebook
            configMap:
              name: notebook
  3. Attendi che GKE avvii il pod Jupyter:

    kubectl wait pods -l app=jupyter-notebook --for condition=Ready --timeout=300s -n pg-ns
    
  4. Ottieni l'URL con il token di accesso per connetterti a Jupyter:

    export EXTERNAL_IP=$(kubectl -n pg-ns get svc notebook --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
    kubectl logs deploy/notebook -n pg-ns| grep '^ .*http://127'|sed "s|127.0.0.1|${EXTERNAL_IP}|"
    

    L'output è simile al seguente:

    http://34.123.21.1:8888/tree?token=a1d48d3531c48328695d6901004c94060aa0aa3554ff7463
    
  5. Apri questo URL e fai clic sul file vector-database.ipynb.

  6. Fai clic su Esegui > Esegui tutte le celle. Jupyter esegue il codice ed esegue una query di ricerca per il testo drama about people and unhappy love.

    Questa query esegue una ricerca semantica sulla tabella documents in PostgreSQL, recuperando un massimo di due risultati con il punteggio di corrispondenza più alto pertinente alla query.

    L'output è simile al seguente:

    Title: Romeo and Juliet, Author: William Shakespeare, Paul Werstine (Editor),
    Barbara A. Mowat (Editor), Paavo Emil Cajander (Translator)
    In Romeo and Juliet, Shakespeare creates a violent world, in which two young
    people fall in love. It is not simply that their families disapprove; the Montagues
    and the Capulets are engaged in a blood feud.In this death-filled setting, the
    movement from love at first sight to the lovers' final union in death seems
    almost inevitable. And yet, this play set in an extraordinary world has become
    the quintessential story of young love. In part because of its exquisite language,
    it is easy to respond as if it were about all young lovers.
    ---------
    Title: A Midsummer Night's Dream, Author: William Shakespeare, Paul Werstine (Editor),
    Barbara A. Mowat (Editor), Catherine Belsey (Contributor)
    Shakespeare's intertwined love polygons begin to get complicated from the start--Demetrius
    and Lysander both want Hermia but she only has eyes for Lysander. Bad news is,
    Hermia's father wants Demetrius for a son-in-law. On the outside is Helena,
    whose unreturned love burns hot for Demetrius. Hermia and Lysander plan to flee
    from the city under cover of darkness but are pursued by an enraged Demetrius
    (who is himself pursued by an enraptured Helena). In the forest, unbeknownst
    to the mortals, Oberon and Titania (King and Queen of the faeries) are having
    a spat over a servant boy. The plot twists up when Oberon's head mischief-maker,
    Puck, runs loose with a flower which causes people to fall in love with the
    first thing they see upon waking. Throw in a group of labourers preparing a
    play for the Duke's wedding (one of whom is given a donkey's head and Titania
    for a lover by Puck) and the complications become fantastically funny.
    ---------
    

Esegui la pulizia

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.

Elimina il progetto

Il modo più semplice per evitare la fatturazione è eliminare il progetto per cui questo tutorial.

Delete a Google Cloud project:

gcloud projects delete PROJECT_ID

Se hai eliminato il progetto, la pulizia è stata completata. Se non hai eliminato progetto, procedi con l'eliminazione delle singole risorse.

Elimina singole risorse

  1. Imposta le variabili di ambiente.

    export PROJECT_ID=${PROJECT_ID}
    export KUBERNETES_CLUSTER_PREFIX=postgres
    export REGION=us-central1
    
  2. Esegui il comando terraform destroy:

    export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
    terraform  -chdir=../postgresql-cloudnativepg/terraform/FOLDER destroy \
    -var project_id=${PROJECT_ID} \
    -var region=${REGION} \
    -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
    

    Sostituisci FOLDER con gke-autopilot o gke-standard, a seconda del tipo di cluster GKE che hai creato.

    Quando richiesto, digita yes.

Passaggi successivi