Distribuzione di modelli di contenitori personalizzati su vertex ai: una guida alla produzione

Una guida alla creazione di distribuzioni di modelli ml sicure, scalabili e conformi al gdpr su vertex ai, sfruttando terraform, i controlli di servizio vpc e il monitoraggio avanzato nelle regioni ue.

Distribuzione di modelli di contenitori personalizzati su vertex ai: una guida alla produzione
TL;DR

Una guida alla creazione di distribuzioni di modelli ml sicure, scalabili e conformi al gdpr su vertex ai, sfruttando terraform, i controlli di servizio vpc e il monitoraggio avanzato nelle regioni ue.

Creazione di endpoint ml sicuri e scalabili con vertex ai: una guida per i professionisti dell'ue

Quando creo soluzioni di machine learning per la produzione, non penso solo a far inferire un modello; penso all'intero ciclo di vita: sicurezza, scalabilità, osservabilità e, sempre più spesso, conformità normativa. per coloro che operano all'interno dell'unione europea, considerazioni aggiuntive come la residenza dei dati e la conformità al gdpr non sono opzionali, ma fondamentali. ecco perché mi sono immerso a fondo in vertex ai di google cloud, una piattaforma gestita che affronta efficacemente queste sfide, in particolare per i modelli di contenitori personalizzati.

In questa guida, ti mostrerò come distribuisco un modello pytorch o tensorflow personalizzato utilizzando il registro modelli e gli endpoint di previsione di vertex ai. il mio obiettivo è mostrarti come costruire un'immagine container pronta per la produzione, registrare il tuo modello e distribuirlo su un endpoint privato protetto con i controlli di servizio vpc. tratteremo anche la configurazione dell'auto-scaling, la divisione del traffico per i rilasci canary e l'impostazione di un monitoraggio completo con cloud logging e vertex ai model monitoring. enfatizzerò una prospettiva ue, utilizzando regioni come europe-west1 e europe-west4 per soddisfare i requisiti di residenza dei dati e discutendo le implicazioni del gdpr e dell'eu chips act per le strategie di inferenza cloud. alla fine, avrai l'esperienza per distribuire e gestire i tuoi modelli personalizzati su vertex ai con fiducia, assicurandoti che siano sicuri, performanti e conformi.

Prerequisiti

Prima di iniziare, assicurati che il tuo ambiente locale e il progetto google cloud siano configurati. presumo che tu abbia:

  • progetto google cloud: con fatturazione abilitata.
  • gcloud cli: installato e configurato (versione 460.0.0 o superiore).
  • docker: desktop o engine installato.
  • python: 3.12+ e pip.
  • terraform cli: installato (versione 1.7.0 o superiore).
  • comprensione di base: dei concetti di machine learning, docker e gcp.

Strumenti che userò

  • gcloud cli
  • docker
  • python 3.12+
  • terraform cli
  • google cloud sdk per python (google-cloud-aiplatform)

Per iniziare: preparazione del mio ambiente

Prima di immergermi nella distribuzione, mi assicuro sempre che il mio ambiente google cloud sia preparato e che la mia macchina locale abbia gli strumenti necessari installati. per questa guida, sto lavorando con un progetto google cloud in cui la fatturazione è abilitata e la mia gcloud cli è autenticata. tutte le risorse che provisioneremo saranno in regioni europee per allinearci ai nostri obiettivi di conformità ue.

Configurazione del progetto gcp

Innanzitutto, confermo che la mia configurazione gcloud punti al mio progetto e alla mia regione di destinazione. di solito standardizzo su europe-west4 per le mie distribuzioni ue.

gcloud config set project $(gcloud config get-value project)
gcloud config set region europe-west4
gcloud auth application-default login

Autorizzazioni iam richieste

L'account di servizio che utilizzo per le operazioni terraform e gcloud necessita di ruoli iam specifici. per la configurazione iniziale, roles/owner viene spesso utilizzato, ma per la produzione, applica il principio del privilegio minimo, utilizzando una combinazione dei seguenti:

  • `roles/resourcemanager.projectiamadmin
*

roles/serviceusage.serviceusageadmin

*

roles/compute.networkadmin

*

roles/aiplatform.admin

*

roles/artifactregistry.admin

*

roles/storage.admin

*

roles/logging.configwriter

*

roles/monitoring.editor

*

roles/accesscontextmanager.policyadmin`

Ambiente python

Per mantenere le mie dipendenze pulite e isolate, creo e attivo sempre un ambiente virtuale python dedicato per ogni progetto. ciò previene conflitti e garantisce la riproducibilità.

python3.12 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install google-cloud-aiplatform==1.42.0 google-cloud-storage==2.10.0 flask==3.0.3 gunicorn==22.0.0 transformers==4.38.2 torch==2.2.1 sentencepiece==0.1.99

Costruzione: le fasi di implementazione

fase 1: bootstrapping dell'infrastruttura gcp con terraform

La mia prima mossa è il provisioning dell'infrastruttura utilizzando infrastructure as code. per questo, mi rivolgo a terraform. mi aiuta a garantire la riproducibilità, a mantenere il controllo della versione e a mantenere tutto nella mia regione ue scelta. sto configurando l'abilitazione dell'api di progetto, una rete vpc personalizzata, un connettore serverless vpc access, un account di servizio dedicato per vertex ai e un repository artifact registry. questi componenti sono cruciali per una distribuzione di modelli sicura e privata.

Per provisionarli, li definirò nei miei file main.tf, variables.tf e terraform.tfvars.

# main.tf
provider "google" {
  project = var.project_id
  region  = var.region
}

resource "google_project_service" "api_services" {
  for_each = toset([
    "artifactregistry.googleapis.com",
    "compute.googleapis.com",
    "containerregistry.googleapis.com", # per la compatibilità con le versioni precedenti di docker.
    "aiplatform.googleapis.com",
    "vpcaccess.googleapis.com",
    "cloudbuild.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "accesscontextmanager.googleapis.com", # per i controlli di servizio vpc
    "logging.googleapis.com",
    "monitoring.googleapis.com"
  ])
  service = each.key
  project = var.project_id
  disable_on_destroy = false
}

resource "google_compute_network" "vpc_network" {
  project = var.project_id
  name    = "vertex-ai-custom-vpc"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "vpc_subnetwork" {
  project       = var.project_id
  name          = "vertex-ai-custom-subnet"
  ip_cidr_range = "10.10.0.0/20"
  region        = var.region
  network       = google_compute_network.vpc_network.id
}

resource "google_vpc_access_connector" "connector" {
  project = var.project_id
  name    = "vertex-ai-connector"
  region  = var.region
  ip_cidr_range = "10.8.0.0/28"
  network = google_compute_network.vpc_network.id

  depends_on = [
    google_project_service.api_services["vpcaccess.googleapis.com"]
  ]
}

resource "google_service_account" "vertex_sa" {
  project      = var.project_id
  account_id   = "vertex-ai-model-deployer"
  display_name = "account di servizio per la distribuzione del modello vertex ai"
}

resource "google_project_iam_member" "vertex_sa_permissions" {
  for_each = toset([
    "roles/aiplatform.user",
    "roles/artifactregistry.writer",
    "roles/storage.objectadmin",
    "roles/logging.logwriter",
    "roles/monitoring.metricwriter",
    "roles/compute.networkuser" # richiesto per l'accesso vpc
  ])
  project = var.project_id
  role    = each.key
  member  = "serviceaccount:${google_service_account.vertex_sa.email}"
}

resource "google_artifact_registry_repository" "model_repo" {
  project       = var.project_id
  location      = var.region
  repository_id = "vertex-ai-model-images"
  description   = "immagini docker per il servizio di modelli personalizzati vertex ai"
  format        = "docker"

  depends_on = [
    google_project_service.api_services["artifactregistry.googleapis.com"]
  ]
}
# variables.tf
variable "project_id" {
  description = "l'id del progetto google cloud."
  type        = string
}

variable "region" {
  description = "la regione gcp per le distribuzioni (ad esempio, europe-west4)."
  type        = string
  default     = "europe-west4"
}

variable "access_policy_number" {
  description = "il numero della policy di accesso della tua organizzazione per i controlli di servizio vpc. trova questo usando `gcloud access-context-manager policies list --organization organization_id`."
  type        = string
}

variable "model_display_name" {
  description = "nome visualizzato per il modello vertex ai."
  type        = string
  default     = "sentimentanalysismodel"
}

variable "vertex_model_resource_name" {
  description = "nome completo della risorsa del modello vertex ai dal passaggio 3 (gcloud ai models list --format='value(name)')."
  type        = string
}
# terraform.tfvars (esempio)
project_id           = "my-gcp-project-id"
region               = "europe-west4"
access_policy_number = "123456789"
model_display_name   = "sentimentanalysismodel"
vertex_model_resource_name = "projects/your_project_number/locations/europe-west4/models/your_model_id"

Dopo aver impostato questi file, eseguo terraform per effettuare il provisioning delle risorse:

terraform init
terraform plan
terraform apply --auto-approve

Output atteso:

apply complete! resources: 10 added, 0 changed, 0 destroyed.

Risoluzione dei problemi: * error 403: the caller does not have permission: ricontrollerei che il mio utente autenticato gcloud abbia roles/owner o i ruoli iam specifici che ho elencato nei prerequisiti. * api not enabled: verificherei che tutte le risorse google_project_service richieste siano elencate e abilitate correttamente nel mio main.tf.

fase 2: sviluppo e containerizzazione del mio server di modelli personalizzati

Successivamente, devo impacchettare il mio modello e la sua logica di servizio in un container docker leggero e ottimizzato. sto utilizzando un modello di analisi del sentiment pre-addestrato di hugging face (distilbert-base-uncased-finetuned-sst-2-english) servito tramite un'applicazione flask. la chiave qui è mantenere l'immagine piccola e garantire tempi di avvio rapidi per una scalabilità efficiente.

Innanzitutto, scarico gli artefatti del modello localmente in una directory model/:

# download_model.py
from transformers import pipeline

# carica un modello di analisi del sentiment pre-addestrato
sentiment_pipeline = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english")

# salva il modello e il tokenizer
sentiment_pipeline.model.save_pretrained("model/")
sentiment_pipeline.tokenizer.save_pretrained("model/")
print("model saved to ./model/")
python download_model.py

Quindi, creo la mia applicazione flask predict.py e il suo dockerfile:

# predict.py
import os
from flask import flask, request, jsonify
from transformers import pipeline

app = flask(__name__)

# carica il modello globalmente per evitare il ricaricamento ad ogni richiesta
def load_model():
    model_path = os.environ.get('aip_model_dir', './model/')
    print(f"loading model from: {model_path}")
    return pipeline("sentiment-analysis", model=model_path)

sentiment_pipeline = load_model()

@app.route('/ping', methods=['get'])
def ping():
    return jsonify({'status': 'healthy'})

@app.route('/predict', methods=['post'])
def predict():
    try:
        instances = request.json['instances']
        if not isinstance(instances, list):
            return jsonify({'error': 'instances must be a list of strings'}), 400

        results = sentiment_pipeline(instances)
        return jsonify({'predictions': results})
    except exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    # usa gunicorn in produzione per la robustezza
    app.run(host='0.0.0.0', port=os.environ.get('aip_http_port', 8080))
# dockerfile
# usa un'immagine python 3.12 slim per una dimensione ridotta
from python:3.12-slim-bookworm as builder

# installa le dipendenze di build per transformers
run apt-get update && apt-get install -y --no-install-recommends \n    build-essential \n    curl \n    && rm -rf /var/lib/apt/lists/*

# imposta la directory di lavoro
workdir /app

# copia il file requirements e installa le dipendenze
copy requirements.txt .
run pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt

# immagine finale
from python:3.12-slim-bookworm

# installa le dipendenze di runtime dai wheels
workdir /app
copy --from=builder /app/wheels /app/wheels
copy --from=builder /usr/lib/python3.12/site-packages /usr/lib/python3.12/site-packages
run pip install --no-cache-dir --no-index --find-links=/app/wheels -r requirements.txt

# copia il codice dell'applicazione e il modello
copy predict.py .
copy model/ ./model/

# espone la porta che vertex ai si aspetta
env aip_http_port=8080
expose 8080

# comando per eseguire il server di previsione utilizzando gunicorn
entrypoint ["gunicorn", "--bind", "0.0.0.0:8080", "predict:app", "--timeout", "90", "--workers", "2"]
# requirements.txt
flask==3.0.3
gunicorn==22.0.0
transformers==4.38.2
torch==2.2.1
sentencepiece==0.1.99 # richiesto da alcuni modelli hugging face

Ora, costruisco e invio l'immagine docker al mio repository artifact registry:

project_id=$(gcloud config get-value project)
region="europe-west4"
repo_name="vertex-ai-model-images"
image_name="sentiment-model-server:v1.0.0"

docker build -t ${region}-docker.pkg.dev/${project_id}/${repo_name}/${image_name} .

gcloud auth configure-docker ${region}-docker.pkg.dev
docker push ${region}-docker.pkg.dev/${project_id}/${repo_name}/${image_name}

export container_image_uri=${region}-docker.pkg.dev/${project_id}/${repo_name}/${image_name}
echo "container image pushed: ${container_image_uri}"

Output atteso:

the push refers to repository [europe-west4-docker.pkg.dev/your-gcp-project-id/vertex-ai-model-images/sentiment-model-server]
... (layers pushed) ...
v1.0.0: digest: sha256:... size: ...
container image pushed: europe-west4-docker.pkg.dev/your-gcp-project-id/vertex-ai-model-images/sentiment-model-server:v1.0.0

Risoluzione dei problemi: * denied: permission denied for repository: mi assicurerei che l'account di servizio o l'utente autenticato abbia il ruolo artifact registry writer. * docker build fails: controllerei requirements.txt per errori di battitura o dipendenze mancanti e mi assicurerei che build-essential sia installato correttamente nella fase di build.

ottimizzazione delle build di container per il cloud

mentre `from python:3.12-slim-bookworm` è un ottimo punto di partenza per un'immagine leggera, in ambienti cloud di produzione più grandi, spesso prenderei in considerazione l'utilizzo di immagini di base ottimizzate per gpu (ad esempio, da ngc di nvidia) o i meccanismi di caching di cloud build per build più veloci e ripetibili. i comandi `apt-get install` nel dockerfile dovrebbero sempre essere seguiti da `rm -rf /var/lib/apt/lists/*` per minimizzare le dimensioni dell'immagine finale cancellando le cache dei pacchetti, il che è fondamentale per i tempi di avvio a freddo e i costi.

fase 3: registrazione del modello con il registro modelli di vertex ai

Vertex ai model registry è il mio hub centralizzato per l'archiviazione e la gestione delle versioni dei modelli ml. la registrazione della mia immagine container e degli artefatti del modello associati qui consente a vertex ai di gestire il ciclo di vita del modello e semplificare le distribuzioni. per questo esempio, ho integrato i pesi del modello direttamente nell'immagine container per semplicità. per modelli più grandi, li caricherei tipicamente su cloud storage (gcs) e farei in modo che il container li prelevi all'avvio.

project_id=$(gcloud config get-value project)
region="europe-west4"
model_display_name="sentimentanalysismodel"

# registra il modello con il registro modelli di vertex ai
gcloud ai models upload \n  --project=${project_id} \n  --region=${region} \n  --display-name=${model_display_name} \n  --container-image-uri=${container_image_uri} \n  --container-command='["gunicorn", "--bind", "0.0.0.0:8080", "predict:app", "--timeout", "90", "--workers", "2"]' \n  --container-predict-route="/predict" \n  --container-health-route="/ping" \n  --container-ports=8080 \n  --description="modello di analisi del sentiment distribuito tramite container personalizzato"

# l'id effettivo del modello è un numero lungo. mi servirà per terraform.
# memorizzerò il nome completo della risorsa (inclusi progetto e posizione) per un uso successivo.
export model_resource_name=$(gcloud ai models list --project=${project_id} --region=${region} --filter="displayname=${model_display_name}" --format="value(name)")
echo "modello registrato con nome risorsa: ${model_resource_name}"

Output atteso:

model [projects/your_project_number/locations/europe-west4/models/your_model_id] uploaded.
... (details) ...
model registered with resource name: projects/your_project_number/locations/europe-west4/models/your_model_id

Risoluzione dei problemi: * 403 permission denied: mi assicurerei che l'account di servizio abbia roles/aiplatform.user. * invalid image uri: ricontrollerei la variabile container_image_uri per la correttezza.

fase 4: distribuzione di un endpoint di previsione privato con i controlli di servizio vpc

Per garantire la massima sicurezza e prevenire l'esfiltrazione dei dati, distribuisco sempre i miei modelli su un endpoint vertex ai all'interno di un perimetro vpc service controls. ciò isola i miei dati e le mie risorse, rendendoli inaccessibili dall'esterno del mio perimetro definito. l'endpoint utilizzerà anche un ip privato per le richieste di inferenza, mantenendo il traffico strettamente all'interno del mio vpc. questo è un passaggio critico per la conformità al gdpr e la sicurezza generale dei dati nell'ue.

Aggiungerò le seguenti risorse al mio main.tf per definire il perimetro dei controlli di servizio vpc e l'endpoint vertex ai. il modello stesso viene referenziato dal nome completo della risorsa del passaggio 3 (var.vertex_model_resource_name) quando eseguo gcloud ai endpoints deploy-model dopo che terraform ha creato l'endpoint.

# main.tf (aggiungere al precedente file terraform)
#
# il provider hashicorp google include google_vertex_ai_endpoint e vpc service controls,
# ma non esiste una sorgente dati denominata google_ai_models e nessuna risorsa google_vertex_ai_endpoint_model.
# dopo che terraform ha creato l'endpoint, distribuisci il modello del passaggio 3 con gcloud (blocco shell sottostante).

resource "google_access_context_manager_service_perimeter" "vertex_ai_perimeter" {
  name        = "accesspolicies/${var.access_policy_number}/serviceperimeters/vertex_ai_perimeter_v1"
  title       = "vertex-ai-perimeter-v1"
  description = "perimetro dei controlli di servizio vpc per vertex ai"
  perimeter_type = "regular"

  status {
    restricted_services = [
      "aiplatform.googleapis.com",
      "artifactregistry.googleapis.com",
      "storage.googleapis.com",
      "cloudbuild.googleapis.com" # richiesto se cloud build viene utilizzato all'interno del perimetro
    ]
    vpc_accessible_services {
      enable_restriction = true
      allowed_services   = [
        "restricted_services"
      ]
    }
  }

  # le policy di ingresso/egresso possono essere definite qui per un controllo granulare
  # ad esempio, per consentire a specifici account di servizio o intervalli ip di interagire con le risorse all'interno del perimetro.
  # policy_data {
  #   ingress_policies {
  #     ingress_from {
  #       sources {
  #         resource = "projects/${var.project_id}"
  #       }
  #       identities = [
  #         "serviceaccount:${google_service_account.vertex_sa.email}"
  #       ]
  #     }
  #     ingress_to {
  #       resources = [
  #         "projects/${var.project_id}"
  #       ]
  #       operations {
  #         service_name = "aiplatform.googleapis.com"
  #         method_selectors {
  #           method = "*"
  #         }
  #       }
  #     }
  #   }
  # }

  depends_on = [
    google_project_service.api_services["accesscontextmanager.googleapis.com"]
  ]
}

resource "google_vertex_ai_endpoint" "sentiment_endpoint" {
  project         = var.project_id
  location        = var.region
  display_name    = "sentiment-analysis-endpoint"
  description     = "endpoint per il modello di analisi del sentiment tramite contenitore personalizzato"
  network         = google_compute_network.vpc_network.id # associa alla rete vpc
  service_account = google_service_account.vertex_sa.email

  depends_on = [
    google_access_context_manager_service_perimeter.vertex_ai_perimeter, # assicurati che il perimetro esista
    google_project_iam_member.vertex_sa_permissions["roles/compute.networkuser"]
  ]
}

Dopo che terraform apply ha creato l'endpoint, distribuisci il modello registrato (id numerico) su quell'endpoint:

project_id=$(gcloud config get-value project)
region="europe-west4"
# impostato dall'esportazione del passaggio 3 o da terraform.tfvars (variabile vertex_model_resource_name), ad esempio:
# export vertex_model_resource_name="projects/123/locations/europe-west4/models/4567890123456789012"
: "${vertex_model_resource_name:?imposta sul nome completo del modello dal passaggio 3}"

endpoint_num="$(gcloud ai endpoints list --project="${project_id}" --region="${region}" \n  --filter="displayname=sentiment-analysis-endpoint" --format="value(name)" | awk -f/ '{print $nf}')"
model_num="$(printf '%s' "${vertex_model_resource_name}" | awk -f/ '{print $nf}')"
service_account_email="vertex-ai-model-deployer@${project_id}.iam.gserviceaccount.com"

gcloud ai endpoints deploy-model "${endpoint_num}" \n  --project="${project_id}" \n  --region="${region}" \n  --model="${model_num}" \n  --display-name="sentiment-model-v1" \n  --machine-type=n1-standard-4 \n  --min-replica-count=1 \n  --max-replica-count=2 \n  --traffic-split=0=100 \n  --service-account="${service_account_email}"

Imposta vertex_model_resource_name su var.vertex_model_resource_name (da terraform.tfvars) o sul model_resource_name che hai acquisito nel passaggio 3.

Prima di eseguire terraform, mi assicuro che il modello del passaggio 3 sia stato caricato con successo. poi, applico queste modifiche:

terraform apply --auto-approve

Output atteso:

apply complete! resources: 3 added, 0 changed, 0 destroyed.
... (output che mostra la creazione dell'endpoint) ...

Risoluzione dei problemi: * 403 permission denied by vpc service controls: mi assicurerei che il mio account di servizio sia all'interno del perimetro o abbia regole di ingresso/uscita esplicite che consentano l'accesso. verificherei anche che tutti i servizi pertinenti (aiplatform.googleapis.com, storage.googleapis.com, artifactregistry.googleapis.com) siano limitati all'interno del perimetro. * invalid network configuration: verificherei che google_vertex_ai_endpoint.sentiment_endpoint.network faccia riferimento correttamente all'id della mia rete vpc. * endpoint does not exist o model not found: questo di solito significa che l'id dell'endpoint o del modello utilizzato con gcloud ai endpoints deploy-model era errato, o che il gcloud ai models upload nel passaggio 3 non è stato completato prima della distribuzione.

navigazione della complessità dei controlli di servizio vpc

i controlli di servizio vpc migliorano significativamente la sicurezza, ma aggiungono uno strato di complessità. il debug dei problemi di accesso può essere impegnativo. consiglio di iniziare con un set minimo di servizi con restrizioni e di aggiungerne gradualmente altri. testa sempre a fondo i modelli di accesso della tua applicazione dopo aver implementato vpc sc, poiché i servizi esterni o persino i comandi `gcloud` possono essere influenzati se non configurati correttamente con i livelli di accesso.

fase 5: configurazione dell'autoscaling e della gestione del traffico

La gestione del traffico e la scalabilità efficiente sono fondamentali per qualsiasi distribuzione in produzione. l'autoscaling e la suddivisione del traffico di vertex ai vengono configurati sul modello distribuito (tramite gcloud o l'api rest), non tramite una risorsa terraform google_vertex_ai_endpoint_model – quel tipo di risorsa non fa parte del provider google di hashicorp. dopo la distribuzione, regolo le repliche (e opzionalmente i target delle metriche di autoscaling) con gcloud ai endpoints mutate-deployed-model, e regolo la suddivisione del traffico quando aggiungo una seconda distribuzione allo stesso endpoint. le metriche di autoscaling della previsione online utilizzano nomi come aiplatform.googleapis.com/prediction/online/cpu/utilization (vedere il riferimento sull'autoscaling di google).

project_id=$(gcloud config get-value project)
region="europe-west4"
endpoint_num="$(gcloud ai endpoints list --project="${project_id}" --region="${region}" \n  --filter="displayname=sentiment-analysis-endpoint" --format="value(name)" | awk -f/ '{print $nf}')"
deployed_model_id="$(gcloud ai endpoints describe "${endpoint_num}" --project="${project_id}" --region="${region}" \n  --format="value(deployedmodels[0].id)")"

gcloud ai endpoints mutate-deployed-model "${endpoint_num}" \n  --project="${project_id}" \n  --region="${region}" \n  --deployed-model-id="${deployed_model_id}" \n  --min-replica-count=1 \n  --max-replica-count=10

Per i rilasci canary, distribuisco un'altra versione del modello sullo stesso endpoint, quindi imposto la mappa del traffico dell'endpoint (ad esempio 90 % / 10 %) utilizzando gcloud ai endpoints update o l'api – vedi la documentazione di vertex ai per la suddivisione del traffico su endpoint a più distribuzioni. le metriche di autoscaling della previsione online utilizzano nomi come aiplatform.googleapis.com/prediction/online/cpu/utilization (vedi il riferimento sull'autoscaling di google).

Esito atteso: i conteggi delle repliche si aggiornano senza terraform; verifica nella console cloud o con gcloud ai endpoints describe.

fase 6: implementazione di un monitoraggio e logging completi

Un monitoraggio e una registrazione robusti sono irrinunciabili per l'eccellenza operativa, e ancora di più per la conformità al gdpr. configurerò cloud logging per acquisire tutte le richieste e le risposte di previsione, indirizzando questi log a un sink regionale. inoltre, abiliterò vertex ai model monitoring per rilevare la deriva dei dati, la deriva dei concetti e la deriva dell'attribuzione, garantendo che il mio modello rimanga accurato e funzioni come previsto nel tempo. per il gdpr, è vitale che i miei log siano conservati in regioni ue con politiche appropriate.

# main.tf (aggiungere al precedente file terraform)
# i job di monitoraggio dei modelli vengono creati tramite console, gcloud o l'api vertex ai. il provider hashicorp
# google non definisce google_vertex_ai_model_monitoring_job. di seguito: bucket di log ue + sink.

resource "google_logging_project_sink" "vertex_ai_log_sink" {
  project = var.project_id
  name    = "vertex-ai-audit-log-sink"
  # sto indirizzando i log a un bucket gcs, assicurandomi che sia in una regione ue.
  destination = "storage.googleapis.com/${google_storage_bucket.log_bucket.name}"
  filter      = "resource.type=("aiplatform.googleapis.com/endpoint" or "aiplatform.googleapis.com/model")"

  depends_on = [
    google_project_service.api_services["logging.googleapis.com"],
    google_project_service.api_services["storage.googleapis.com"]
  ]
}

resource "google_storage_bucket" "log_bucket" {
  project       = var.project_id
  name          = "vertex-ai-log-bucket-${var.project_id}"
  location      = upper(var.region) # es. europe-west4
  force_destroy = false
  uniform_bucket_level_access = true

  # imposto una policy di retention per la conformità al gdpr, ad esempio, 365 giorni.
  retention_policy {
    is_locked        = false
    retention_period = 31536000 # 365 giorni in secondi
  }
}

data "google_project" "project" {
  project_id = var.project_id
}

# concedi all'account di servizio di logging il permesso di scrivere nel bucket
resource "google_storage_bucket_iam_member" "log_bucket_iam" {
  bucket = google_storage_bucket.log_bucket.name
  role   = "roles/storage.objectcreator"
  member = "serviceaccount:service-${data.google_project.project.number}@gcp-sa-logging.iam.gserviceaccount.com"
}

Monitoraggio del modello: creo un job di monitoraggio del modello nella console google cloud (vertex ai → endpoint → monitoring) o con gcloud ai model-monitoring-jobs create, utilizzando dati di base e schema in bucket gcs ue. passo l'id del modello distribuito da gcloud ai endpoints describe. il blocco terraform rimosso utilizzava un tipo di risorsa che non esiste nel provider hashicorp.

Nota sugli schemi e le baseline: il monitoraggio confronta il traffico live con un dataset di baseline e uno schema. mantieni entrambi in un bucket ue per la residenza; non fare affidamento su uri di esempio solo statunitensi per le baseline di produzione.

Ora, eseguo terraform di nuovo:

terraform apply --auto-approve

Output atteso:

apply complete! resources: 3 added, 0 changed, 0 destroyed.

Risoluzione dei problemi: * model monitoring job failed: verificherei che il gcs_path per lo schema e i dati di base sia corretto e accessibile dall'account di servizio vertex ai. mi assicurerei anche che il deployed_model_id corrisponda a una distribuzione attiva sull'endpoint. * permission denied for logging sink: mi assicurerei che l'account di servizio cloud logging (service-project_number@gcp-sa-logging.iam.gserviceaccount.com) abbia le autorizzazioni storage object creator sul bucket di destinazione.

fase 7: convalida della residenza dei dati ue e della conformità

Per qualsiasi organizzazione con sede nell'ue, garantire la residenza dei dati è fondamentale per la conformità al gdpr e l'adesione a iniziative come l'eu chips act. l'eu chips act sottolinea il rafforzamento dell'ecosistema dei semiconduttori dell'ue, influenzando il modo in cui le organizzazioni potrebbero considerare l'inferenza on-premise rispetto a quella cloud per i dati sensibili. distribuendo le risorse esclusivamente nelle regioni ue, mantengo il controllo sulla posizione dei dati. ho configurato tutto in europe-west4, ma anche europe-west1 funzionerebbe. verificherò rapidamente le posizioni utilizzando i comandi gcloud:

project_id=$(gcloud config get-value project)
region="europe-west4"

echo "verifica della posizione di artifact registry..."
gcloud artifacts repositories describe vertex-ai-model-images --location=${region} --project=${project_id} --format="value(location)"

echo "verifica della posizione dell'endpoint vertex ai..."
gcloud ai endpoints describe sentiment-analysis-endpoint --region=${region} --project=${project_id} --format="value(location)"

echo "verifica della posizione del bucket di log..."
gcloud storage buckets describe gs://vertex-ai-log-bucket-${project_id} --format="value(location)"

echo "verifica della posizione del connettore di accesso vpc..."
gcloud vpc-access connectors describe vertex-ai-connector --region=${region} --project=${project_id} --format="value(location)"

Output atteso:

verifying artifact registry location...
europe-west4
verifying vertex ai endpoint location...
europe-west4
verifying log bucket location...
europe-west4
verifying vpc access connector location...
europe-west4

Questa verifica conferma che la mia infrastruttura è conforme ai requisiti di residenza dei dati ue, posizionando le mie distribuzioni ml per la conformità al gdpr.

fase 8: esecuzione di una previsione e osservazione dei risultati

Con il modello distribuito e il monitoraggio configurato, è il momento di avviare una richiesta di previsione di esempio per testare l'endpoint e osservare i risultati in cloud logging. questo dimostra il flusso di inferenza end-to-end.

# predict_client.py
import os
from google.cloud import aiplatform

project_id = os.environ.get('project_id')
region = os.environ.get('region', 'europe-west4')
endpoint_name = os.environ.get('endpoint_name', 'sentiment-analysis-endpoint')

def predict_text_sentiment(project: str, location: str, endpoint_name: str, text_instances: list):
    aiplatform.init(project=project, location=location)

    # filtro per display_name per assicurarmi di ottenere l'endpoint corretto
    endpoints = aiplatform.endpoint.list(filter=f"display_name="{endpoint_name}"")
    if not endpoints:
        raise valueerror(f"endpoint with display_name {endpoint_name} not found.")
    endpoint = endpoints[0]

    # il formato della richiesta dipende dall'implementazione della rotta /predict del mio container
    # per la mia app flask, si aspetta {'instances': ["testo1", "testo2"]}
    instances_payload = [{"instances": text_instances}]

    response = endpoint.predict(instances=instances_payload)

    print("risposta di previsione:")
    for prediction in response.predictions:
        print(prediction)

if __name__ == '__main__':
    # frasi di esempio per l'analisi del sentiment
    sample_texts = [
        "questo è un prodotto straordinario, lo adoro!",
        "il servizio è stato terribile e sono molto deluso.",
        "è stata un'esperienza nella media, né buona né cattiva."
    ]

    print(f"invio richiesta di previsione a {endpoint_name} in {region} per il progetto {project_id}")
    predict_text_sentiment(project_id, region, endpoint_name, sample_texts)

Eseguirò lo script di previsione:

project_id=$(gcloud config get-value project)
region="europe-west4"
endpoint_name="sentiment-analysis-endpoint"

export project_id
export region
export endpoint_name

python predict_client.py

Output atteso:

prediction response:
{'label': 'positive', 'score': 0.9998...}
{'label': 'negative', 'score': 0.9996...}
{'label': 'positive', 'score': 0.8876...} # (il neutro potrebbe essere classificato come leggermente positivo o negativo a seconda del modello)

Dopo aver eseguito la previsione, navigo su cloud logging nella mia console gcp. filtro i log per resource.type="aiplatform.googleapis.com/endpoint" e resource.labels.endpoint_id="il_tuo_endpoint_id_dall'output_di_terraform" per vedere le mie richieste e risposte di previsione. ciò verifica che il mio sink di logging stia acquisendo attivamente i dati di inferenza.

Risoluzione dei problemi: * 403 permission denied: mi assicurerei che l'account di servizio che esegue predict_client.py (il mio account utente se uso gcloud auth application-default login) abbia roles/aiplatform.user e l'accesso di rete necessario se non è in esecuzione all'interno del vpc. * valueerror: endpoint with display_name... not found.: ricontrollerei le variabili endpoint_name e region e mi assicurerei che il mio endpoint sia stato distribuito con successo.

Test della mia implementazione

Oltre a una singola previsione, testo sempre accuratamente la mia distribuzione per garantire stabilità, prestazioni e scalabilità.

  1. test di carico: utilizzo strumenti come apachebench (ab), locust o jmeter per simulare utenti concorrenti e verificare il comportamento di autoscaling. monitoro sempre l'utilizzo della cpu e il numero di repliche in cloud monitoring.
# esempio con apachebench
# installazione: sudo apt-get install apache2-utils
# nota: richiede accesso esterno o un client all'interno del vpc per raggiungere l'endpoint privato.
# per gli endpoint privati, questo verrebbe tipicamente eseguito da una vm all'interno dello stesso vpc.
# l'url sottostante è per gli endpoint pubblici. per quelli privati, lo indirizzeresti tramite il suo ip interno.
# se lo esponi tramite un bilanciatore di carico o simile, verrebbe utilizzato quell'url.
# per i test diretti da una vm all'interno del vpc, utilizzeresti un approccio diverso per la scoperta dell'endpoint.
# per questo esempio, presumo un accesso esterno temporaneo per dimostrazione, o test dall'interno del vpc.
# sostituisci endpoint_id con l'id del tuo endpoint vertex ai.
# puoi ottenere il dns pubblico dell'endpoint se non hai limitato l'accesso esterno:
# gcloud ai endpoints describe sentiment-analysis-endpoint --region=europe-west4 --format="value(publicendpoint.dnsname)"
endpoint_id="$(gcloud ai endpoints list --project=${project_id} --region=${region} --filter="display_name=sentiment-analysis-endpoint" --format="value(endpoints[0].id)")"
endpoint_url="https://europe-west4-aiplatform.googleapis.com/v1/projects/${project_id}/locations/${region}/endpoints/${endpoint_id}:predict"
payload='{"instances": ["questa è una frase di test."]}'

# esempio: 100 richieste, 10 concorrenti.
# nota: questo richiede che l'endpoint sia accessibile pubblicamente o acceduto da un ambiente connesso al vpc.
# se vpc sc limita l'accesso esterno, questo comando `ab` probabilmente fallirebbe a meno che non venga eseguito dall'interno del perimetro.
ab -n 100 -c 10 -t 'application/json' -p <(echo "${payload}") -h "authorization: bearer $(gcloud auth print-access-token)" "${endpoint_url}"
  1. verifica del canary rollout: se introduco una nuova versione del modello con una piccola divisione del traffico, mi assicuro che solo la percentuale specificata di richieste venga indirizzata alla nuova versione. di solito lo osservo registrando identificatori univoci da ogni versione del modello all'interno del mio predict.py o esaminando i risultati delle previsioni se i modelli producono risultati distinti.

  2. allarmi di monitoraggio: attivo intenzionalmente condizioni per il mio vertex ai model monitoring (ad esempio, inviando dati che causerebbero una deriva) e confermo che gli allarmi e-mail o pub/sub vengano ricevuti come configurato.

  3. revisione dei log: ispeziono regolarmente cloud logging per errori, picchi di latenza e output di previsione corretti. mi assicuro che i dati sensibili siano gestiti in conformità con le mie politiche gdpr e che la configurazione del logging filtri o rediga correttamente ciò che è necessario.

Considerazioni sulla produzione

La distribuzione in produzione implica più che semplicemente far funzionare il codice. ecco alcune aree chiave su cui mi concentro sempre:

migliori pratiche di sicurezza

  • controlli di servizio vpc: come ho dimostrato, utilizza sempre i controlli di servizio vpc per i carichi di lavoro sensibili al fine di prevenire l'esfiltrazione dei dati. questo crea un solido perimetro di sicurezza attorno alle tue risorse vertex ai.
  • minimo privilegio: concedi all'account di servizio vertex ai solo i ruoli iam assolutamente necessari. evito roles/editor o roles/owner per le distribuzioni in produzione.
  • gestione dei segreti: memorizza le chiavi api, le credenziali o i parametri sensibili del modello in secret manager, non direttamente nell'immagine del contenitore o nel codice.
  • sicurezza dei contenitori: esegui regolarmente la scansione delle tue immagini docker per le vulnerabilità utilizzando artifact analysis o strumenti di terze parti. usa immagini di base minime come python:3.12-slim per ridurre la superficie di attacco.
  • governance del modello: implementa la firma del modello (ad esempio, usando sigstore/cosign) per verificare l'integrità e l'origine degli artefatti del modello. assicurati che il logging di audit completo sia abilitato in tutte le fasi del ciclo di vita ml.

ottimizzazione delle prestazioni

  • tipi di macchine: seleziona i tipi di macchine appropriati (n1-standard, a2-highgpu, ecc.) per il tuo carico di lavoro. le istanze gpu accelerano significativamente l'inferenza per i grandi modelli di deep learning.
  • ottimizzazione del contenitore: ottimizza il tuo dockerfile per dimensioni e prestazioni di avvio a freddo. usa build multi-stage, pulisci i file non necessari e precarica i modelli in memoria.
  • batching: per scenari ad alto throughput, implementa il batching delle richieste all'interno del tuo predict.py per elaborare più inferenze in una singola chiamata, riducendo l'overhead.
  • scalabilità orizzontale: configura min_replica_count e max_replica_count con autoscaling_metric_specs aggressivi per gestire efficacemente le fluttuazioni del traffico.

considerazioni sulla scalabilità

  • distribuzione regionale: distribuisci i modelli in regioni geograficamente vicine ai tuoi utenti per minimizzare la latenza, in particolare in europe-west1 o europe-west4 per gli utenti ue.
  • servizio gestito: vertex ai è un servizio gestito, che gestisce la scalabilità dell'infrastruttura sottostante. il mio focus si sposta sull'ottimizzazione del mio contenitore e del modello per l'efficienza piuttosto che sulla gestione dei cluster kubernetes.
  • gestione delle quote: sono sempre consapevole delle quote di vertex ai e compute engine. richiedo proattivamente aumenti se prevedo volumi di traffico molto elevati.

raccomandazioni sul monitoraggio

  • dashboard: creo dashboard personalizzate in cloud monitoring per visualizzare metriche chiave come la latenza delle richieste, i tassi di errore, l'utilizzo di cpu/gpu e il numero di repliche.
  • politiche di alerting: imposto politiche di alerting granulari per soglie critiche (ad esempio, latenza p99 che supera i 500 ms, tasso di errore superiore all'1%).
  • analisi dei log: utilizzo cloud logging con esportazioni bigquery per analisi e audit avanzati dei log.
  • monitoraggio del modello: l'uso continuo del monitoraggio del modello vertex ai per rilevare la deriva dei dati, la deriva dei concetti e il degrado della qualità delle previsioni è essenziale. il monitoraggio proattivo del modello può ridurre del 70% il tempo medio di rilevamento del degrado del modello, il che rappresenta un significativo vantaggio operativo.

domande comuni

d: come posso aggiornare il mio modello distribuito senza tempi di inattività?

r: lo ottengo utilizzando la suddivisione del traffico sul mio endpoint vertex ai. distribuisco la nuova versione del modello (ad esempio, la versione 1) sullo stesso endpoint con il 0% di traffico. una volta verificata, sposto gradualmente il traffico (ad esempio, 5%, poi 25%, poi 100%) sulla nuova versione. ciò consente rilasci canary e un facile rollback in caso di problemi.

d: qual è il costo di distribuzione di un modello personalizzato su vertex ai?

r: il prezzo di vertex ai per i modelli di contenitori personalizzati si basa principalmente sul tipo di macchina, sull'utilizzo dell'acceleratore e sul numero di repliche. ad esempio, un tipo di macchina n1-standard-4 senza gpu costa circa 0,15 €/ora (0,16 $/ora) in europe-west4. il monitoraggio dei modelli comporta costi aggiuntivi, circa 0,01 €/1000 richieste di previsione (0,01 $/1000) campionate. con un tasso di conversione di 1 $ ≈ 0,92 €, un piccolo endpoint n1-standard-4 in esecuzione 24 ore su 24, 7 giorni su 7 con 1 replica costerebbe circa 109,50 €/mese (119,00 $/mese) per l'istanza, più i costi delle richieste. faccio sempre riferimento alla pagina dei prezzi di vertex ai per le cifre più recenti e le variazioni regionali specifiche.

d: posso usare le gpu con il mio modello di contenitore personalizzato?

r: sì, vertex ai supporta tipi di macchine abilitati per gpu. specificherei accelerator_type (ad esempio, nvidia_tesla_t4) e accelerator_count nella mia machine_spec all'interno del blocco dedicated_resources della mia risorsa terraform google_vertex_ai_endpoint_model. è fondamentale che la mia immagine docker abbia i driver gpu e le librerie necessarie (ad esempio, cuda, cudnn, nvidia container toolkit) incorporati.

d: come gestisco artefatti di modelli di grandi dimensioni che non rientrano nell'immagine del contenitore?

r: per i modelli più grandi di pochi gb, archivio gli artefatti del modello in un bucket gcs. il mio contenitore personalizzato predict.py scarica quindi questi artefatti da gcs nella directory /tmp del contenitore durante l'avvio del contenitore. vertex ai fornirà automaticamente le credenziali per l'account di servizio del modello distribuito per accedere a gcs, semplificando la gestione degli accessi.

d: in che modo i controlli di servizio vpc influiscono sulla distribuzione e sull'accesso ai modelli?

r: i controlli di servizio vpc creano un perimetro di sicurezza che limita il movimento dei dati. le risorse all'interno del perimetro (come il mio endpoint vertex ai e i bucket gcs) possono comunicare solo con altre risorse all'interno dello stesso perimetro o servizi esplicitamente consentiti. ciò significa che i client che accedono all'endpoint devono essere all'interno del perimetro (ad esempio, una vm nel mio vpc) o avere un accesso in ingresso esplicitamente concesso tramite un livello di accesso. questo migliora significativamente la sicurezza dei dati prevenendo l'accesso non autorizzato e l'esfiltrazione dei dati.

d: quali sono le implicazioni dell'eu chips act sulle distribuzioni ml nel cloud?

r: l'eu chips act mira a rafforzare l'industria dei semiconduttori dell'ue. sebbene si concentri principalmente sulla produzione, ha implicazioni per l'elaborazione dei dati e la resilienza della catena di approvvigionamento. per le mie distribuzioni ml, mi incoraggia a considerare dove avviene l'elaborazione dell'inferenza. l'utilizzo di regioni cloud all'interno dell'ue, come europe-west1 o europe-west4, garantisce che i dati rimangano nella giurisdizione ue, il che è vantaggioso per la conformità e la riduzione dei rischi geopolitici associati alle posizioni di elaborazione dei dati, anche se i chip sottostanti provengono da tutto il mondo. ciò rafforza la necessità di chiare strategie di residenza dei dati nelle operazioni cloud.

d: qual è la versione python consigliata per i contenitori personalizzati su vertex ai nel 2026?

r: all'inizio del 2026, python 3.12+ è la versione consigliata per i nuovi sviluppi. offre miglioramenti delle prestazioni e nuove funzionalità che contribuiscono a un'erogazione del modello più efficiente. mi propongo sempre di utilizzare l'ultima versione stabile di python supportata dalle mie librerie ml principali (pytorch, tensorflow, transformers) per beneficiare delle ultime ottimizzazioni e patch di sicurezza.

Conclusione

La distribuzione di modelli di machine learning personalizzati in produzione, specialmente nel rigoroso panorama normativo dell'ue, è una sfida sfaccettata. in questa guida, ti ho illustrato il mio processo per la creazione di una distribuzione vertex ai sicura, scalabile e conforme utilizzando l'infrastructure as code. la combinazione di artifact registry per la gestione dei container, del registro modelli vertex ai per la gestione delle versioni, di endpoint di previsione privati con i controlli di servizio vpc per l'isolamento dei dati e di un robusto monitoraggio con cloud logging e vertex ai model monitoring crea una solida base per qualsiasi carico di lavoro ml in produzione.

Un compromesso significativo da considerare è la complessità iniziale introdotta dai controlli di servizio vpc. sebbene incredibilmente potenti per la sicurezza, richiedono un'attenta pianificazione e possono complicare il debug. la mia raccomandazione è di investire tempo fin dall'inizio per progettare correttamente la tua rete e le tue politiche di accesso, poiché un adattamento a posteriori può essere molto più doloroso. per i finops, tieni sempre d'occhio il numero di repliche e i tipi di macchine; le istanze gpu inattive, in particolare, possono portare a costi imprevisti se l'autoscaling non è configurato correttamente.

Il mio prossimo passo concreto dopo aver impostato una tale pipeline è sempre quello di perfezionare il monitoraggio del modello. do la priorità alla creazione di un dataset di riferimento robusto e di uno schema dettagliato che rifletta accuratamente gli input e gli output del modello. questo approccio proattivo mi consente di rilevare precocemente la deriva dei dati o il degrado delle prestazioni, garantendo che i miei modelli continuino a fornire valore in produzione, non solo nello sviluppo.

Last updated:

This article was produced using an AI-assisted research and writing pipeline. Learn how we create content →