Proxy esplicito dell'interfaccia PSC di Vertex AI Pipelines

1. Introduzione

Un'interfaccia Private Service Connect è una risorsa che consente a una rete Virtual Private Cloud (VPC) producer di avviare connessioni a varie destinazioni in una rete VPC consumer. Le reti di produttori e consumatori possono trovarsi in progetti e organizzazioni diversi.

Se un collegamento di rete accetta una connessione da un'interfaccia Private Service Connect, Google Cloud assegna all'interfaccia un indirizzo IP da una subnet consumer specificata dal collegamento di rete. Le reti del consumatore e del produttore sono connesse e possono comunicare utilizzando indirizzi IP interni.

Una connessione tra un collegamento di rete e un'interfaccia Private Service Connect è simile alla connessione tra un endpoint Private Service Connect e un collegamento al servizio, ma presenta due differenze fondamentali:

  • Un collegamento di rete consente a una rete producer di avviare connessioni a una rete consumer (uscita del servizio gestito), mentre un endpoint consente a una rete consumer di avviare connessioni a una rete producer (ingresso del servizio gestito).
  • Una connessione di interfaccia Private Service Connect è transitiva. Ciò significa che una rete producer può comunicare con altre reti connesse alla rete consumer.

Considerazioni sull'accessibilità dell'interfaccia PSC di Vertex AI

  • L'interfaccia PSC è in grado di instradare il traffico verso destinazioni VPC o on-premise all'interno del blocco di indirizzi RFC1918.
  • Il targeting dell'interfaccia PSC di blocchi di indirizzi non RFC-1918 richiede un proxy esplicito di cui è stato eseguito il deployment nel VPC del consumer con un indirizzo RFC-1918. All'interno del deployment di Vertex AI, il proxy deve essere definito insieme a un FQDN dell'endpoint di destinazione. Vedi la figura 1 che rappresenta il proxy esplicito configurato nei VPC dei clienti per facilitare il routing ai seguenti CIDR non RFC-1918:

[1] 240.0.0.0/4

[2] 203.0.113.0/2

[3]10.10.20.0/28 non è richiesto alcun proxy, rientra nell'intervallo RFC1918.

  • Quando configuri il deployment solo con un'interfaccia PSC, questa mantiene l'accesso a internet predefinito. Questo traffico in uscita esce direttamente dalla rete tenant sicura e gestita da Google.

476f87a96f153b95.png

Considerazioni su Vertex AI PSC-Interface VPC-SC

  • Quando il tuo progetto fa parte di un perimetro di Controlli di servizio VPC, l'accesso a internet predefinito dei tenant gestiti da Google viene bloccato dal perimetro per impedire l'esfiltrazione di dati.
  • Per consentire l'accesso al deployment a internet pubblico in questo scenario, devi configurare esplicitamente un percorso di uscita sicuro che indirizzi il traffico tramite il VPC. Il modo consigliato per farlo è configurare un server proxy all'interno del perimetro VPC con un indirizzo RFC1918 e creare un gateway Cloud NAT per consentire alla VM proxy di accedere a internet.

Per ulteriori informazioni, consulta le seguenti risorse:

Configura un'interfaccia Private Service Connect per le risorse Vertex AI | Google Cloud

Cosa creerai

In questo tutorial, creerai un deployment completo di Vertex AI Pipelines con l'interfaccia Private Service Connect (PSC) per consentire la connettività dal producer al calcolo del consumer, come illustrato nella Figura 1, con targeting degli endpoint non RFC-1928.

Figura 2

782ba8f1f3c3f522.png

Creerai un singolo psc-network-attachment nel VPC consumer sfruttando il peering DNS per risolvere le VM consumer nel progetto tenant che ospita Vertex AI Training, il che comporta i seguenti casi d'uso:

  1. Esegui il deployment di Vertex AI Pipelines e configura una VM proxy in modo che funga da proxy esplicito, consentendole di eseguire un wget su una VM nella subnet di classe E.

Cosa imparerai a fare

  • Come creare un collegamento di rete
  • Come un producer può utilizzare un collegamento di rete per creare un'interfaccia PSC
  • Come stabilire la comunicazione dal producer al consumer utilizzando il peering DNS
  • Come stabilire la comunicazione con lo spazio di indirizzi IP non RFC1918 da Vertex AI Pipelines

Che cosa ti serve

Progetto Google Cloud

Autorizzazioni IAM

2. Prima di iniziare

Aggiornare il progetto per supportare il tutorial

Questo tutorial utilizza le variabili $per facilitare l'implementazione della configurazione di gcloud in Cloud Shell.

In Cloud Shell, esegui le seguenti operazioni:

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectid=YOUR-PROJECT-NAME
echo $projectid

Abilitazione delle API

In Cloud Shell, esegui le seguenti operazioni:

gcloud services enable "compute.googleapis.com"
gcloud services enable "aiplatform.googleapis.com"
gcloud services enable "dns.googleapis.com"
gcloud services enable "notebooks.googleapis.com"
gcloud services enable "storage.googleapis.com"
gcloud services enable "cloudresourcemanager.googleapis.com"
gcloud services enable "artifactregistry.googleapis.com"
gcloud services enable "cloudbuild.googleapis.com"

3. Configurazione consumatore

Crea il VPC consumer

In Cloud Shell, esegui le seguenti operazioni:

gcloud compute networks create consumer-vpc --project=$projectid --subnet-mode=custom

Crea le subnet consumer

In Cloud Shell, esegui le seguenti operazioni:

gcloud compute networks subnets create class-e-subnet --project=$projectid --range=240.0.0.0/4 --network=consumer-vpc --region=us-central1

In Cloud Shell, esegui le seguenti operazioni:

gcloud compute networks subnets create rfc1918-subnet1 --project=$projectid --range=10.10.10.0/28 --network=consumer-vpc --region=us-central1

Crea la subnet del collegamento di rete Private Service Connect

In Cloud Shell, esegui le seguenti operazioni:

gcloud compute networks subnets create intf-subnet --project=$projectid --range=192.168.10.0/28 --network=consumer-vpc --region=us-central1

Configurazione di router Cloud e NAT

In questo tutorial, Cloud NAT viene utilizzato per fornire l'accesso a internet alla VM proxy, che non ha un indirizzo IP pubblico. Cloud NAT consente alle VM con solo indirizzi IP privati di connettersi a internet, consentendo loro di eseguire attività come l'installazione di pacchetti software.

In Cloud Shell, crea il router Cloud.

gcloud compute routers create cloud-router-for-nat --network consumer-vpc --region us-central1

In Cloud Shell, crea il gateway NAT.

gcloud compute routers nats create cloud-nat-us-central1 --router=cloud-router-for-nat --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges --region us-central1 --enable-logging --log-filter=ALL

4. Abilitare IAP

Per consentire a IAP di connettersi alle tue istanze VM, crea una regola firewall che:

  • Si applichi a tutte le istanze VM a cui vuoi accedere tramite IAP.
  • Consente il traffico in entrata dall'intervallo IP 35.235.240.0/20. Questo intervallo contiene tutti gli indirizzi IP che utilizzati da IAP per l'inoltro TCP.

In Cloud Shell, crea la regola firewall IAP.

gcloud compute firewall-rules create ssh-iap-consumer \
    --network consumer-vpc \
    --allow tcp:22 \
    --source-ranges=35.235.240.0/20

5. Crea istanze VM consumer

In Cloud Shell, crea l'istanza VM consumer, class-e-vm.

gcloud compute instances create class-e-vm \
    --project=$projectid \
    --machine-type=e2-micro \
    --image-family debian-11 \
    --no-address \
    --shielded-secure-boot \
    --image-project debian-cloud \
    --zone us-central1-a \
    --subnet=class-e-subnet \
    --metadata startup-script="#! /bin/bash
      sudo apt-get update
      sudo apt-get install tcpdump
      sudo apt-get install apache2 -y
      sudo service apache2 restart
      echo 'Class-e server !!' | tee /var/www/html/index.html
      EOF"

In Cloud Shell, crea l'istanza VM consumer, proxy-vm, che fungerà da proxy esplicito per Vertex AI Pipelines. Utilizzeremo tinyproxy come applicazione per il proxy del traffico HTTP, anche se è supportato anche HTTPS.

gcloud compute instances create proxy-vm \
    --project=$projectid \
    --machine-type=e2-micro \
    --image-family debian-11 \
    --no-address \
    --can-ip-forward \
    --shielded-secure-boot \
    --image-project debian-cloud \
    --zone us-central1-a \
    --subnet=rfc1918-subnet1 \
    --metadata startup-script="#! /bin/bash
      sudo apt-get update
      sudo apt-get install tcpdump
      sudo apt-get install tinyproxy -y
      sudo apt-get install apache2 -y
      sudo service apache2 restart
      echo 'proxy server !!' | tee /var/www/html/index.html
      EOF"

6. Collegamento di rete Private Service Connect

I collegamenti di rete sono risorse regionali che rappresentano il lato consumer di un'interfaccia Private Service Connect. Associ un'unica subnet a un collegamento di rete e il producer assegna gli IP all'interfaccia Private Service Connect da quella subnet. La subnet deve trovarsi nella stessa regione del collegamento di rete. Un collegamento di rete deve trovarsi nella stessa regione del servizio di produzione.

Crea il collegamento di rete

In Cloud Shell, crea il collegamento di rete.

gcloud compute network-attachments create psc-network-attachment \
    --region=us-central1 \
    --connection-preference=ACCEPT_AUTOMATIC \
    --subnets=intf-subnet

Elencare i collegamenti di rete

In Cloud Shell, elenca il collegamento di rete.

gcloud compute network-attachments list

Descrivi i collegamenti di rete

In Cloud Shell, descrivi il collegamento di rete.

gcloud compute network-attachments describe psc-network-attachment --region=us-central1

Prendi nota del nome dell'allegato di rete PSC, psc-network-attachment, che verrà utilizzato dal producer durante la creazione dell'interfaccia Private Service Connect.

Per visualizzare l'URL dell'allegato di rete PSC in Cloud Console, vai a:

Servizi di rete → Private Service Connect → Collegamento di rete → psc-network-attachment

e191e54a103d2222.png

7. Zona DNS privata

Creerai una zona Cloud DNS per demo.com e la popolerai con record A che rimandano agli indirizzi IP delle tue VM. In un secondo momento, il peering DNS verrà implementato nel job Vertex AI Pipelines, il che gli consentirà di accedere ai record DNS del consumer.

In Cloud Shell, esegui le seguenti operazioni:

gcloud dns --project=$projectid managed-zones create private-dns-codelab --description="" --dns-name="demo.com." --visibility="private" --networks="https://compute.googleapis.com/compute/v1/projects/$projectid/global/networks/consumer-vpc"

In Cloud Shell, esegui un comando describe sulle istanze VM per ottenere i rispettivi indirizzi IP.

gcloud compute instances describe class-e-vm --zone=us-central1-a | grep  networkIP:

gcloud compute instances describe proxy-vm --zone=us-central1-a | grep  networkIP:

In Cloud Shell, crea il set di record per la VM, class-e-vm, assicurati di aggiornare l'indirizzo IP in base all'output del tuo ambiente.

gcloud dns --project=$projectid record-sets create class-e-vm.demo.com. --zone="private-dns-codelab" --type="A" --ttl="300" --rrdatas="240.0.0.2"

In Cloud Shell, crea il set di record per la VM proxy-vm, assicurati di aggiornare l'indirizzo IP in base all'output del tuo ambiente.

gcloud dns --project=$projectid record-sets create proxy-vm.demo.com. --zone="private-dns-codelab" --type="A" --ttl="300" --rrdatas="10.10.10.2"

Crea una regola Cloud Firewall per consentire l'accesso dall'interfaccia PSC

Nella sezione seguente, crea una regola firewall che consenta il traffico proveniente dall'accesso all'allegato di rete PSC alle risorse di calcolo RFC1918 nel VPC dei consumer.

In Cloud Shell, crea la regola firewall in entrata che consente l'accesso dalla subnet dell'allegato di rete PSC alla VM proxy.

gcloud compute firewall-rules create allow-access-to-proxy \
    --network=consumer-vpc \
    --action=ALLOW \
    --rules=ALL \
    --direction=INGRESS \
    --priority=1000 \
    --source-ranges="192.168.10.0/28" \
    --destination-ranges="10.10.0.0/19" \
    --enable-logging

In Cloud Shell, crea la regola firewall in entrata che consente l'accesso dalla subnet proxy-vm alla subnet class-e.

gcloud compute firewall-rules create allow-access-to-class-e \
    --network=consumer-vpc \
    --action=ALLOW \
    --rules=ALL \
    --direction=INGRESS \
    --priority=1000 \
    --source-ranges="10.10.10.0/28" \
    --destination-ranges="240.0.0.0/4" \
    --enable-logging

8. Aggiorna il proxy esplicito

Nella sezione seguente, dovrai eseguire l'accesso SSH al proxy esplicito e aggiornare il file di configurazione tinyproxy.conf, quindi eseguire un ripristino.

Da Cloud Shell

gcloud compute ssh --zone us-central1-a "proxy-vm" --tunnel-through-iap --project $projectid

Apri il file di configurazione di tinyproxy e aggiornalo utilizzando un editor a tua scelta. Di seguito è riportato un esempio che utilizza VIM.

sudo vim /etc/tinyproxy/tinyproxy.conf

# Locate the "Listen" configuration line to restrict listening to only its private IP address of the Proxy-VM, rather than all interfaces. 

Listen 10.10.10.2

# Locate the "Allow" configuration line to allow requests ONLY from the PSC Network Attachment Subnet

Allow 192.168.10.0/24

Save the configs by the following steps:
1. Press the `ESC` key to enter Command Mode.
2. Type `:wq` to save (w) and quit (q).
3. Press `Enter`

Restart the tinyproxy service to apply the changes:
sudo systemctl restart tinyproxy

Validate the tinyproxy service is running:
sudo systemctl status tinyproxy

Perform an exit returning to cloud shell
exit

9. Crea un notebook Jupyter

La sezione seguente ti guida nella creazione di un blocco note Jupyter. Questo notebook verrà utilizzato per eseguire il deployment di un job Vertex AI Pipelines che invia un comando wget da Vertex AI Pipelines alle istanze di test. Il percorso dati tra Vertex AI Pipelines e la rete consumer contenente le istanze utilizza un'interfaccia di rete Private Service Connect.

Crea un service account gestito dall'utente

Nella sezione seguente creerai un service account che verrà associato all'istanza di Vertex AI Workbench utilizzata nel tutorial.

Nel tutorial, al service account verranno applicati i seguenti ruoli:

In Cloud Shell, crea il service account.

gcloud iam service-accounts create notebook-sa \
    --display-name="notebook-sa"

In Cloud Shell, aggiorna il service account con il ruolo Storage Admin.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/storage.admin"

In Cloud Shell, aggiorna il service account con il ruolo Utente Vertex AI.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/aiplatform.user"

In Cloud Shell, aggiorna il service account con il ruolo Amministratore di Artifact Registry.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/artifactregistry.admin"

In Cloud Shell, aggiorna il service account con il ruolo Editor Cloud Build.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/cloudbuild.builds.editor"

In Cloud Shell, consenti al service account del notebook di utilizzare il service account Compute Engine predefinito.

gcloud iam service-accounts add-iam-policy-binding \
    $(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')-compute@developer.gserviceaccount.com \
    --member="serviceAccount:notebook-sa@$projectid.iam.gserviceaccount.com" \
    --role="roles/iam.serviceAccountUser"

10. Crea un'istanza di Vertex AI Workbench

Nella sezione seguente, crea un'istanza di Vertex AI Workbench che incorpori il service account creato in precedenza, notebook-sa.

In Cloud Shell, crea l'istanza private-client.

gcloud workbench instances create workbench-tutorial --vm-image-project=cloud-notebooks-managed --vm-image-family=workbench-instances --machine-type=n1-standard-4 --location=us-central1-a --subnet-region=us-central1 --subnet=rfc1918-subnet1 --disable-public-ip --shielded-secure-boot=true --shielded-integrity-monitoring=true --shielded-vtpm=true --service-account-email=notebook-sa@$projectid.iam.gserviceaccount.com

11. Aggiornamento di Vertex AI Service Agent

Vertex AI agisce per tuo conto per eseguire operazioni come l'ottenimento di un indirizzo IP dalla subnet di collegamento di rete PSC utilizzata per creare l'interfaccia PSC. A questo scopo, Vertex AI utilizza un service agent (elencato di seguito) che richiede l'autorizzazione Network Admin.

service-$projectnumber@gcp-sa-aiplatform.iam.gserviceaccount.com

In Cloud Shell, ottieni il numero del progetto.

gcloud projects describe $projectid | grep projectNumber

In Cloud Shell, ottieni il numero del progetto.

gcloud projects describe $projectid | grep projectNumber
projectNumber: '234086459238'

In Cloud Shell, imposta il numero del progetto.

projectnumber=YOUR-PROJECT-Number

In Cloud Shell, crea un service account per AI Platform. Salta questo passaggio se hai un service account esistente nel tuo progetto.

gcloud beta services identity create --service=aiplatform.googleapis.com --project=$projectnumber

In Cloud Shell, aggiorna l'account agente di servizio con il ruolo compute.networkAdmin.

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:service-$projectnumber@gcp-sa-aiplatform.iam.gserviceaccount.com" --role="roles/compute.networkAdmin"

In Cloud Shell, aggiorna l'account agente di servizio con il ruolo dns.peer

gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:service-$projectnumber@gcp-sa-aiplatform.iam.gserviceaccount.com" --role="roles/dns.peer"

Aggiornamento del service account predefinito

Abilita l'API Compute Engine e concedi all'account di servizio predefinito l'accesso a Vertex AI. Tieni presente che la propagazione della modifica dell'accesso potrebbe richiedere un po' di tempo.

In Cloud Shell, aggiorna il service account predefinito con il ruolo aiplatform.user

gcloud projects add-iam-policy-binding $projectid \
  --member="serviceAccount:$projectnumber-compute@developer.gserviceaccount.com" \
    --role="roles/aiplatform.user"

In Cloud Shell, aggiorna il service account predefinito con il ruolo storage.admin

gcloud projects add-iam-policy-binding $projectid \
  --member="serviceAccount:$projectnumber-compute@developer.gserviceaccount.com" \
    --role="roles/storage.admin"

In Cloud Shell, aggiorna il service account predefinito con il ruolo storage.admin

gcloud projects add-iam-policy-binding $projectid \
  --member="serviceAccount:$projectnumber-compute@developer.gserviceaccount.com" \
    --role="roles/artifactregistry.admin"

12. Abilita Tcpdump

Per convalidare la connettività IP da Vertex AI Pipelines, possiamo utilizzare TCPDUMP. Ciò ci consentirà di osservare la comunicazione proveniente dalla subnet di collegamento di rete PSC, 192.168.10.0/28, quando viene richiamata la richiesta GET da Vertex AI Pipelines alla VM, class-e-vm.demo.com (240.0.0.0/4).

Da Cloud Shell, esegui l'accesso SSH alla VM proxy.

gcloud compute ssh --zone us-central1-a "proxy-vm" --tunnel-through-iap --project $projectid

Dal sistema operativo proxy-vm esegui il filtro tcpdump sulla subnet di collegamento di rete class-e-vm e PSC.

sudo tcpdump -i any net 240.0.0.0/4 or 192.168.10.0/28 -nn

Apri una nuova scheda di Cloud Shell, aggiorna la variabile del progetto ed esegui SSH in class-e-vm

gcloud compute ssh --zone us-central1-a "class-e-vm" --tunnel-through-iap --project $projectid

Dal sistema operativo class-e-vm esegui il filtro tcpdump sulla subnet proxy-vm.

sudo tcpdump -i any net 10.10.10.0/28 -nn

13. Esegui il deployment del job pipeline Vertex AI

Nella sezione seguente, creerai un notebook per eseguire un wget riuscito da Vertex AI Pipelines al proxy esplicito. In questo modo puoi raggiungere VM non RFC 1918, ad esempio class-e-vm. Un proxy esplicito non è necessario per Vertex AI Pipelines per accedere a rfc1918-vm, poiché la sua destinazione è un indirizzo IP RFC 1918.

Esegui il job di addestramento nell'istanza di Vertex AI Workbench.

  1. Nella console Google Cloud, vai alla scheda delle istanze nella pagina Vertex AI Workbench.
  2. Accanto al nome dell'istanza di Vertex AI Workbench (workbench-tutorial), fai clic su Apri JupyterLab. L'istanza di Vertex AI Workbench si apre in JupyterLab.
  3. Seleziona File > Nuovo > Notebook.
  4. Seleziona Kernel > Python 3.

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

# Install gcloud
!pip install google-cloud

# Install the pipeline required packages
!pip install --upgrade google-cloud-aiplatform \
                         google-cloud-storage \
                         kfp \
                         google-cloud-pipeline-components

# Import libraries
from time import gmtime, strftime
import json
import requests

Nel blocco note JupyterLab, crea una nuova cella, aggiorna ed esegui quanto segue. Assicurati di aggiornare PROJECT_ID con i dettagli del tuo ambiente.

import json
import requests
import pprint

PROJECT_ID = 'YOUR-PROJECT-ID' #Enter your project ID
PROJECT_NUMBER=!gcloud projects list --filter="project_id:$PROJECT_ID" --format="value(PROJECT_NUMBER)"
PROJECT_NUMBER=str(PROJECT_NUMBER).strip('[').strip(']').strip("'")
print(PROJECT_NUMBER)

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

# us-central1 is used for the codelab
REGION = "us-central1" #@param {type:"string"}
SERVICE_NAME = "aiplatform" #@param {type:"string"}
SERVICE ="{}.googleapis.com".format(SERVICE_NAME)
ENDPOINT="{}-{}.googleapis.com".format(REGION, SERVICE_NAME)
API_VERSION = "v1" # @param {type: "string"}

LOCATION = REGION

Nel notebook JupyterLab, crea una nuova cella ed esegui la configurazione riportata di seguito. Tieni presente i seguenti punti salienti:

  • proxy_server = "http://proxy-vm.demo.com:8888" FQDN è associato alla VM proxy di cui è stato eseguito il deployment nel VPC consumer. Utilizziamo il peering DNS per risolvere l'FQDN in un passaggio successivo.
%%writefile main.py

import logging
import socket
import sys
import os

def make_api_request(url: str, proxy_vm_ip: str, proxy_vm_port: str):
    """
    Makes a GET request to a non-rfc1918 API and saves the response.

    Args:
        url: The URL of the API to send the request to.
    """
    import requests

    try:
        # response = requests.get(url)
        proxy_server = f"http://proxy-vm.demo.com:8888" # replace with you VM's IP and proxy port.

        proxies = {
          "http": proxy_server,
          "https": proxy_server,
        }

        response = requests.get(url, proxies=proxies)
        logging.info(response.text)

        response.raise_for_status()  # Raise an exception for bad status codes
        logging.info(f"Successfully fetched data from {url}")
    except requests.exceptions.RequestException as e:
        logging.error(f"An error occurred: {e}")
        raise e

if __name__ == '__main__':
  # Configure logging to print clearly to the console
  logging.basicConfig(
      level=logging.INFO,
      format='%(levelname)s: %(message)s',
      stream=sys.stdout
  )
  url_to_test = os.environ['NONRFC_URL']
  proxy_vm_ip = os.environ['PROXY_VM_IP']
  proxy_vm_port = os.environ['PROXY_VM_PORT']

  logging.info(f"url_to_test: {url_to_test}")
  logging.info(f"proxy_vm_ip: {proxy_vm_ip}")
  logging.info(f"proxy_vm_port: {proxy_vm_port}")
  make_api_request(url_to_test, proxy_vm_ip, proxy_vm_port)

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

%%writefile Dockerfile
FROM python:3.9-slim

RUN apt-get update && \
  apt-get install -y iputils-ping && \
  apt-get install -y wget

RUN pip install cloudml-hypertune requests kfp

COPY main.py /main.py

ENTRYPOINT ["python3", "/main.py"]

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

!gcloud artifacts repositories create pipelines-test-repo-psc --repository-format=docker --location=us-central1

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

IMAGE_PROJECT = PROJECT_ID
IMAGE_REPO = 'pipelines-test-repo-psc' 
IMAGE_NAME = 'nonrfc-ip-call'
TAG = 'v1'

IMAGE_URI= f'us-central1-docker.pkg.dev/{IMAGE_PROJECT}/{IMAGE_REPO}/{IMAGE_NAME}:{TAG}'
IMAGE_URI

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

!gcloud auth configure-docker us-docker.pkg.dev --quiet

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando. Ignora l'errore (gcloud.builds.submit) se presente.

!gcloud builds submit --tag {IMAGE_URI} --region=us-central1

Nel blocco note JupyterLab, crea ed esegui la cella riportata di seguito. Tieni presente i seguenti punti salienti:

  • Il peering DNS con i VPC consumer è configurato utilizzando dnsPeeringConfigs (dnsPeeringConfigs) per il nome di dominio demo.com.
  • Il proxy esplicito, definito come variabile PROXY_VM_IP, è proxy-vm.demo.com. La risoluzione viene gestita tramite il peering DNS all'interno del VPC consumer.
  • La porta 8888 è la porta di ascolto (predefinita) configurata in tinyproxy
  • Wget a class-e-vm-demo.com viene risolto tramite il peering DNS
  • Il codice specifica "psc-network-attachment" per Vertex, consentendogli di utilizzare la subnet del collegamento di rete per eseguire il deployment di due istanze di interfaccia PSC.
import json
from datetime import datetime


JOB_ID_PREFIX='test_psci-nonRFC' #@param {type:"string"}
JOB_ID = '{}_{}'.format(JOB_ID_PREFIX, datetime.now().strftime("%Y%m%d%H%M%S"))

# PSC-I configs

PRODUCER_PROJECT_ID = PROJECT_ID
DNS_DOMAIN = 'class-e-vm.demo.com' #@param {type:"string"}
NON_RFC_URL = f"http://{DNS_DOMAIN}"

PROXY_VM_IP = "proxy-vm.demo.com" #@param {type:"string"}
PROXY_VM_PORT = "8888" #@param {type:"string"}

CUSTOM_JOB = {
  "display_name": JOB_ID,
  "job_spec": {
      "worker_pool_specs": [
          {
           "machine_spec": {
             "machine_type": "n1-standard-4",
           },
           "replica_count": 1,
           "container_spec": {
             "image_uri": IMAGE_URI,
             "env": [{
               "name": "NONRFC_URL",
               "value": NON_RFC_URL
             },
             {
               "name": "PROXY_VM_IP",
               "value": PROXY_VM_IP
             },
             {
               "name": "PROXY_VM_PORT",
               "value": PROXY_VM_PORT
             }]
           },
         },
      ],
      "enable_web_access": True,
      "psc_interface_config": {
        "network_attachment": "psc-network-attachment",
        "dns_peering_configs": [
          {
            "domain": "demo.com.",
            "target_project": PROJECT_ID,
            "target_network": "consumer-vpc"
          },
        ]
      },
  }
}

print(json.dumps(CUSTOM_JOB, indent=2))

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

import requests
bearer_token = !gcloud auth application-default print-access-token
headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer {}'.format(bearer_token[0]),
}

request_uri = f"https://{REGION}-aiplatform.googleapis.com/{API_VERSION}/projects/{PROJECT_NUMBER}/locations/{REGION}/customJobs/"

print("request_uri: ", request_uri)

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

response_autopush = requests.post(request_uri, json=CUSTOM_JOB, headers=headers)
response = response_autopush
print("response:", response)
if response.reason == 'OK':
  job_name = response.json()['name']
  job_id = job_name.split('/')[-1]
  print("Created Job: ", response.json()['name'])
else:
  print(response.text)

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

# Print KFP SDK version (should be >= 1.6)
! python3 -c "import kfp; print('KFP SDK version: {}'.format(kfp.__version__))"

# Print AI Platform version
! python3 -c "from google.cloud import aiplatform; print('AI Platform version: {}'.format(aiplatform.__version__))"

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

BUCKET_URI = "your-unique-bucket" # Provide a globally unique bucket name

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

!gcloud storage buckets create gs://{BUCKET_URI}

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

# pipeline parameters
CACHE_PIPELINE = False # @param {type: "string"}
_DEFAULT_IMAGE = IMAGE_URI
BUCKET_URI = "gs://{BUCKET_URI}"  # @param {type: "string"}
PIPELINE_ROOT = f"{BUCKET_URI}/pipeline_root/intro"
PIPELINE_DISPLAY_NAME = "pipeline_nonRFCIP" # @param {type: "string"}

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

from re import S
import kfp
from kfp import dsl
from kfp.dsl import container_component, ContainerSpec
from kfp import compiler
from google.cloud import aiplatform


# ==== Component with env variable ====

@container_component
def dns_peering_test_op(dns_domain: str, proxy_vm_ip:str, proxy_vm_port:str):
    return ContainerSpec(
        image=_DEFAULT_IMAGE,
        command=["bash", "-c"],
        args=[
            """
            apt-get update && apt-get install inetutils-traceroute inetutils-ping netcat-openbsd curl -y

            echo "Local IP(s): $(hostname -I)"

            echo "Attempting to trace route to %s"
            traceroute -w 1 -m 7 "%s"

            echo "Sending curl requests to http://%s via proxy %s:%s and recording trace..."
            if curl -L -v --trace-ascii /dev/stdout -x http://%s:%s "http://%s"; then
                echo "Curl request succeeded!"
            else
                echo "Curl request failed!"
                exit 1
            fi
            """ % (dns_domain, dns_domain, dns_domain, proxy_vm_ip, proxy_vm_port, proxy_vm_ip, proxy_vm_port, dns_domain)

        ]
    )

# ==== Pipeline ====
@dsl.pipeline(
    name="dns-peering-test-pipeline",
    description="Test DNS Peering using env variable",
    pipeline_root=PIPELINE_ROOT,
)
def dns_peering_test_pipeline(dns_domain: str, proxy_vm_ip:str, proxy_vm_port:str):
    dns_test_task = dns_peering_test_op(dns_domain=dns_domain, proxy_vm_ip=proxy_vm_ip, proxy_vm_port=proxy_vm_port)
    dns_test_task.set_caching_options(enable_caching=CACHE_PIPELINE)

# ==== Compile pipeline ====
if __name__ == "__main__":
    aiplatform.init(project=PROJECT_ID, location=LOCATION)

    compiler.Compiler().compile(
        pipeline_func=dns_peering_test_pipeline,
        package_path="dns_peering_test_pipeline.yaml",
    )
    print("✅ Pipeline compiled to dns_peering_test_pipeline.yaml")

Nel blocco note JupyterLab, crea una nuova cella ed esegui il seguente comando.

# Define the PipelineJob body; see API Reference https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.pipelineJobs/create

import requests, json
import datetime

bearer_token = !gcloud auth application-default print-access-token
headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer {}'.format(bearer_token[0]),
}

request_uri = f"https://{REGION}-aiplatform.googleapis.com/{API_VERSION}/projects/{PROJECT_NUMBER}/locations/{REGION}/pipelineJobs/"

print("request_uri: ", request_uri)

14. Convalida dell'interfaccia PSC

Puoi anche visualizzare gli indirizzi IP di collegamento di rete utilizzati da Vertex AI Pipelines andando a:

Servizi di rete → Private Service Connect → Collegamento di rete → psc-network-attachment

Seleziona il progetto tenant (il nome del progetto termina con -tp)

f47150235fedb8ce.png

Il campo evidenziato indica l'indirizzo IP utilizzato da Vertex AI Pipelines dal collegamento di rete PSC.

39e7b251aeb4f191.png

15. Convalida di Cloud Logging

La prima esecuzione del job Vertex AI Pipelines richiede circa 14 minuti, mentre le esecuzioni successive sono molto più brevi. Per convalidare un risultato positivo, esegui le seguenti operazioni:

Vai a Vertex AI → Addestramento → Job personalizzati

Seleziona il job personalizzato eseguito

a9be0395c842aa6f.png

Seleziona Visualizza log.

53e30765ba5827f3.png

Una volta disponibile Cloud Logging, seleziona Esegui query che genera la selezione evidenziata di seguito, che conferma un wget riuscito da Vertex AI Pipelines alla VM class-e.

f2c5d9fdf5cc8bed.png

3b3788603bb433ee.png

16. Convalida TCPDump

Esaminiamo l'output di TCPDUMP che convalida ulteriormente la connettività alle istanze di Compute:

Dalla VM proxy osserva HTTP GET e 200 OK

03:05:34.778574 ens4  Out IP 10.10.10.2.40326 > 240.0.0.2.80: Flags [P.], seq 1:63, ack 1, win 511, options [nop,nop,TS val 1435446009 ecr 2475360885], length 62: HTTP: GET / HTTP/1.0
03:05:34.778946 ens4  In  IP 240.0.0.2.80 > 10.10.10.2.40326: Flags [.], ack 63, win 506, options [nop,nop,TS val 2475360889 ecr 1435446009], length 0
03:05:34.778974 ens4  Out IP 10.10.10.2.40326 > 240.0.0.2.80: Flags [P.], seq 63:185, ack 1, win 511, options [nop,nop,TS val 1435446010 ecr 2475360889], length 122: HTTP
03:05:34.781999 ens4  In  IP 240.0.0.2.80 > 10.10.10.2.40326: Flags [.], ack 185, win 506, options [nop,nop,TS val 2475360892 ecr 1435446010], length 0
03:05:34.906678 ens4  In  IP 240.0.0.2.80 > 10.10.10.2.40326: Flags [P.], seq 1:265, ack 185, win 506, options [nop,nop,TS val 2475361016 ecr 1435446010], length 264: HTTP: HTTP/1.1 200 OK

Da class-e-vm osserva HTTP GET e 200 OK

03:05:34.778768 ens4  In  IP 10.10.10.2.40326 > 240.0.0.2.80: Flags [P.], seq 1:63, ack 1, win 511, options [nop,nop,TS val 1435446009 ecr 2475360885], length 62: HTTP: GET / HTTP/1.0
03:05:34.778819 ens4  Out IP 240.0.0.2.80 > 10.10.10.2.40326: Flags [.], ack 63, win 506, options [nop,nop,TS val 2475360889 ecr 1435446009], length 0
03:05:34.781815 ens4  In  IP 10.10.10.2.40326 > 240.0.0.2.80: Flags [P.], seq 63:185, ack 1, win 511, options [nop,nop,TS val 1435446010 ecr 2475360889], length 122: HTTP
03:05:34.781856 ens4  Out IP 240.0.0.2.80 > 10.10.10.2.40326: Flags [.], ack 185, win 506, options [nop,nop,TS val 2475360892 ecr 1435446010], length 0
03:05:34.906503 ens4  Out IP 240.0.0.2.80 > 10.10.10.2.40326: Flags [P.], seq 1:265, ack 185, win 506, options [nop,nop,TS val 2475361016 ecr 1435446010], length 264: HTTP: HTTP/1.1 200 OK

17. Esegui la pulizia

Da Cloud Shell, elimina i componenti del tutorial.

gcloud compute instances delete proxy-vm --zone=us-central1-a --quiet

gcloud compute instances delete workbench-tutorial --zone=us-central1-a --quiet

gcloud compute routers delete cloud-router-for-nat --region=us-central1 --quiet

gcloud compute network-attachments delete psc-network-attachment --region=us-central1 --quiet

gcloud compute networks subnets delete intf-subnet rfc1918-subnet1 --region=us-central1 --quiet

gcloud dns record-sets delete class-e-vm.demo.com --zone=private-dns-codelab  --type=A
gcloud dns record-sets delete proxy-vm.demo.com --zone=private-dns-codelab  --type=A

gcloud dns managed-zones delete private-dns-codelab
gcloud compute networks delete consumer-vpc --quiet

18. Complimenti

Congratulazioni, hai configurato e convalidato correttamente un'interfaccia Private Service Connect con Vertex AI Pipelines.

Hai creato l'infrastruttura consumer e hai aggiunto un collegamento di rete che ha consentito al producer di creare una VM con più NIC per collegare la comunicazione tra consumer e producer. Hai imparato a creare il peering DNS durante il deployment di un proxy esplicito nella rete VPC consumer che consentiva la connettività all'istanza class-e-vm non instradabile direttamente da Vertex.

Cosmopup pensa che i tutorial siano fantastici.

c911c127bffdee57.jpeg

Passaggi successivi

Ulteriori letture e video

Documenti di riferimento