Proxy explícito da interface PSC do Vertex AI Pipelines

1. Introdução

A interface do Private Service Connect é um recurso que permite que uma rede de nuvem privada virtual (VPC, na sigla em inglês) do produtor inicie conexões com vários destinos em uma rede VPC do consumidor. As redes de produtor e consumidor podem estar em diferentes projetos e organizações.

Se um anexo de rede aceitar uma conexão de uma interface do Private Service Connect, o Google Cloud alocará à interface um endereço IP de uma sub-rede do consumidor especificada pelo anexo de rede. As redes de consumidores e produtores estão conectadas e podem se comunicar por endereços IP internos.

Uma conexão entre um anexo de rede e uma interface do Private Service Connect é semelhante à conexão entre um endpoint do Private Service Connect e um anexo de serviço, mas há duas diferenças principais:

  • Um anexo de rede permite que uma rede produtora inicie conexões com uma rede consumidora (saída de serviço gerenciada), enquanto um endpoint permite que uma rede consumidora inicie conexões com uma rede produtora (entrada de serviço gerenciada).
  • Uma conexão de interface do Private Service Connect é transitiva. Isso significa que uma rede do produtor pode se comunicar com outras que estão conectadas à rede do consumidor.

Considerações sobre a acessibilidade da interface do PSC da Vertex AI

  • A interface do PSC pode rotear o tráfego para destinos baseados em VPC ou locais no bloco de endereços RFC1918.
  • O direcionamento de interface do PSC a blocos de endereços não rfc-1918 exige um proxy explícito implantado na VPC do consumidor com um endereço rfc-1918. Na implantação da Vertex AI, o proxy precisa ser definido com um FQDN do endpoint de destino. Consulte a Figura 1, que representa o proxy explícito configurado nas VPCs dos clientes para facilitar o roteamento para os seguintes CIDRs não RFC-1918:

[1] 240.0.0.0/4

[2] 203.0.113.0/2

[3]10.10.20.0/28 não requer proxy, está no intervalo rfc1918.

  • Quando você configura a implantação apenas com uma interface do PSC, ela mantém o acesso padrão à Internet. Esse tráfego de saída sai diretamente da rede de locatário segura e gerenciada pelo Google.

476f87a96f153b95.png

Considerações sobre a VPC-SC da interface PSC da Vertex AI

  • Quando seu projeto faz parte de um perímetro do VPC Service Controls, o acesso padrão à Internet dos tenants gerenciados pelo Google é bloqueado pelo perímetro para evitar a exfiltração de dados.
  • Para permitir que a implantação acesse a Internet pública nesse cenário, configure explicitamente um caminho de saída seguro que roteie o tráfego pela sua VPC. A maneira recomendada de fazer isso é configurar um servidor proxy dentro do perímetro da VPC com um endereço RFC1918 e criar um gateway do Cloud NAT para permitir que a VM proxy acesse a Internet.

Para mais informações, consulte os seguintes recursos:

Configurar uma interface do Private Service Connect para recursos da Vertex AI | Google Cloud

O que você vai criar

Neste tutorial, você vai criar uma implantação abrangente do Vertex AI Pipelines com a interface do Private Service Connect (PSC) para permitir a conectividade do produtor com a computação do consumidor, conforme ilustrado na Figura 1, segmentando endpoints não RFC-1928.

Figura 2.

782ba8f1f3c3f522.png

Você vai criar um único psc-network-attachment na VPC do consumidor usando o peering de DNS para resolver as VMs do consumidor no projeto do locatário que hospeda o Vertex AI Training, resultando nos seguintes casos de uso:

  1. Implante o Vertex AI Pipelines e configure uma VM proxy para atuar como um proxy explícito, permitindo que ela execute um wget em uma VM na sub-rede de classe E.

O que você vai aprender

  • Como criar um anexo de rede
  • Como um produtor pode usar um anexo de rede para criar uma interface do PSC
  • Como estabelecer comunicação do produtor para o consumidor usando o peering de DNS
  • Como estabelecer comunicação com o espaço de endereços IP não rfc1918 do Vertex AI Pipelines

O que é necessário

Projeto do Google Cloud

Permissões do IAM

2. Antes de começar

Atualizar o projeto para oferecer suporte ao tutorial

Este tutorial usa $variables para ajudar na implementação da configuração do gcloud no Cloud Shell.

No Cloud Shell, faça o seguinte:

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

Ativação da API

No Cloud Shell, faça o seguinte:

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. Configuração do consumidor

Criar a VPC do consumidor

No Cloud Shell, faça o seguinte:

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

Criar as sub-redes do consumidor

No Cloud Shell, faça o seguinte:

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

No Cloud Shell, faça o seguinte:

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

Criar a sub-rede de anexo de rede do Private Service Connect

No Cloud Shell, faça o seguinte:

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

Configuração do Cloud Router e do NAT

Neste tutorial, o Cloud NAT é usado para fornecer acesso à Internet à VM de proxy, que não tem um endereço IP público. O Cloud NAT permite que VMs com apenas endereços IP particulares se conectem à Internet, permitindo que elas executem tarefas como instalar pacotes de software.

No Cloud Shell, crie o Cloud Router.

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

No Cloud Shell, crie o 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. Ativar o IAP

Para permitir que o IAP se conecte às suas instâncias de VM, crie uma regra de firewall que:

  • Aplica-se a todas as instâncias de VM que você quer acessar usando o IAP.
  • Permite o tráfego de entrada do intervalo de IP 35.235.240.0/20. Esse intervalo contém todos os endereços IP que o IAP usa para o encaminhamento de TCP.

No Cloud Shell, crie a regra de firewall do IAP.

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

5. Criar instâncias de VM do consumidor

No Cloud Shell, crie a instância de VM do consumidor, 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"

No Cloud Shell, crie a instância de VM do consumidor, proxy-vm, que vai servir como proxy explícito para o Vertex AI Pipelines. Vamos usar o tinyproxy como o aplicativo para proxy do tráfego HTTP, embora o HTTPS também seja compatível.

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. Anexo de rede do Private Service Connect

Os anexos de rede são recursos regionais que representam o lado do consumidor de uma interface do Private Service Connect. Você associa uma única sub-rede a um anexo de rede, e o produtor atribui IPs à interface do Private Service Connect a partir dessa sub-rede. A sub-rede precisa estar na mesma região do anexo de rede. Um anexo de rede precisa estar na mesma região do serviço do produtor.

Criar o anexo de rede

No Cloud Shell, crie o anexo de rede.

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

Listar os anexos de rede

No Cloud Shell, liste o anexo de rede.

gcloud compute network-attachments list

Descrever os anexos de rede

No Cloud Shell, descreva o anexo de rede.

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

Anote o nome psc-network-attachment, psc-network-attachment, que será usado pelo produtor ao criar a interface do Private Service Connect.

Para ver o URL de anexo de rede do PSC no console do Cloud, navegue até:

Serviços de rede → Private Service Connect → Anexo de rede → psc-network-attachment

e191e54a103d2222.png

7. Zona de DNS particular

Você vai criar uma zona do Cloud DNS para demo.com e preenchê-la com registros A que apontam para os endereços IP das suas VMs. Mais tarde, o peering de DNS será implantado no job do Vertex AI Pipelines, o que permitirá o acesso aos registros DNS do consumidor.

No Cloud Shell, faça o seguinte:

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"

No Cloud Shell, execute uma descrição nas instâncias de VM para receber os respectivos endereços 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:

No Cloud Shell, crie o conjunto de registros para a VM, class-e-vm, e atualize o endereço IP com base na saída do seu 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"

No Cloud Shell, crie o conjunto de registros para a VM, proxy-vm, e atualize o endereço IP com base na saída do seu 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"

Criar uma regra do Cloud Firewall para permitir o acesso da interface do PSC

Na seção a seguir, crie uma regra de firewall que permita o tráfego originado do acesso ao anexo de rede do PSC a recursos de computação RFC1918 na VPC dos consumidores.

No Cloud Shell, crie a regra de firewall de entrada que permite o acesso da sub-rede de anexo de rede do PSC à proxy-vm.

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

No Cloud Shell, crie a regra de firewall de entrada que permite o acesso da sub-rede proxy-vm à sub-rede 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. Atualizar o proxy explícito

Na seção a seguir, você precisará fazer SSH no proxy explícito e atualizar o arquivo de configuração tinyproxy.conf, seguido de uma redefinição.

No Cloud Shell

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

Abra o arquivo de configuração do tinyproxy e atualize usando um editor de sua escolha. Confira um exemplo usando o 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. Crie um notebook do Jupyter

A seção a seguir orienta você na criação de um notebook do Jupyter. Este notebook será usado para implantar um job do Vertex AI Pipelines que envia um wget do Vertex AI Pipelines para as instâncias de teste. O caminho de dados entre o Vertex AI Pipelines e a rede do consumidor que contém as instâncias usa uma interface de rede do Private Service Connect.

Criar uma conta de serviço gerenciada pelo usuário

Na seção a seguir, você vai criar uma conta de serviço que será associada à instância do Vertex AI Workbench usada no tutorial.

No tutorial, a conta de serviço terá as seguintes funções aplicadas:

No Cloud Shell, crie a conta de serviço.

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

No Cloud Shell, atualize a conta de serviço com o papel de administrador do Storage.

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

No Cloud Shell, atualize a conta de serviço com o papel de usuário da Vertex AI.

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

No Cloud Shell, atualize a conta de serviço com o papel Administrador do Artifact Registry.

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

No Cloud Shell, atualize a conta de serviço com o papel de editor do Cloud Build.

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

No Cloud Shell, permita que a conta de serviço do notebook use a conta de serviço padrão do Compute Engine.

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. criar uma instância do Vertex AI Workbench

Na seção a seguir, crie uma instância do Vertex AI Workbench que incorpore a conta de serviço criada anteriormente, notebook-sa.

No Cloud Shell, crie a instância 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. Atualização do agente de serviço da Vertex AI

A Vertex AI age em seu nome para realizar operações como a obtenção de um endereço IP da sub-rede de anexo de rede do PSC usada para criar a interface do PSC. Para isso, a Vertex AI usa um agente de serviço (listado abaixo) que exige a permissão de administrador de rede.

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

No Cloud Shell, recupere o número do projeto.

gcloud projects describe $projectid | grep projectNumber

No Cloud Shell, recupere o número do projeto.

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

No Cloud Shell, defina o número do projeto.

projectnumber=YOUR-PROJECT-Number

No Cloud Shell, crie uma conta de serviço para o AI Platform. Pule esta etapa se você já tiver uma conta de serviço no projeto.

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

No Cloud Shell, atualize a conta do agente de serviço com a função compute.networkAdmin.

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

No Cloud Shell, atualize a conta do agente de serviço com a função dns.peer

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

Atualização da conta de serviço padrão

Ative a API Compute Engine e conceda à sua conta de serviço padrão acesso à Vertex AI. Pode levar algum tempo para a mudança no acesso ser propagada.

No Cloud Shell, atualize a conta de serviço padrão com a função aiplatform.user

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

No Cloud Shell, atualize a conta de serviço padrão com o papel storage.admin.

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

No Cloud Shell, atualize a conta de serviço padrão com o papel storage.admin.

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

12. Ativar o Tcpdump

Para validar a conectividade IP do Vertex AI Pipelines, podemos usar o TCPDUMP. Isso vai permitir observar a comunicação originada da sub-rede de anexo de rede do PSC, 192.168.10.0/28, ao invocar a solicitação GET dos Pipelines da Vertex AI para a VM, class-e-vm.demo.com (240.0.0.0/4).

No Cloud Shell, conecte-se via SSH à VM de proxy.

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

No SO da proxy-vm, execute a filtragem tcpdump na sub-rede de anexo de rede class-e-vm e PSC.

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

Abra uma nova guia do Cloud Shell, atualize a variável do projeto e faça ssh na class-e-vm

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

No SO da VM class-e-vm, execute a filtragem tcpdump na sub-rede proxy-vm.

sudo tcpdump -i any net 10.10.10.0/28 -nn

13. Implantar um job do Vertex AI Pipelines

Na seção a seguir, você vai criar um notebook para realizar um wget bem-sucedido da Vertex AI Pipelines para o proxy explícito. Isso permite alcançar VMs não RFC 1918, como a class-e-vm. Um proxy explícito não é necessário para que o Vertex AI Pipelines acesse rfc1918-vm, já que o destino é um endereço IP RFC 1918.

Execute o job de treinamento na instância do Vertex AI Workbench.

  1. No console do Google Cloud, acesse a guia "Instâncias" na página do Vertex AI Workbench.
  2. Ao lado do nome da instância do Vertex AI Workbench (workbench-tutorial), clique em "Abrir JupyterLab". A instância do Vertex AI Workbench será aberta no JupyterLab.
  3. Selecione Arquivo > Novo > Notebook.
  4. Selecione Kernel > Python 3

No notebook do JupyterLab, crie uma célula e execute o seguinte:

# 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

No notebook do JupyterLab, crie uma nova célula, atualize e execute o seguinte. Atualize PROJECT_ID com os detalhes do seu 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)

No notebook do JupyterLab, crie uma célula e execute o seguinte:

# 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

No notebook do JupyterLab, crie uma nova célula e execute a configuração abaixo. Observe os seguintes destaques:

  • proxy_server = "http://proxy-vm.demo.com:8888" O FQDN está associado à VM de proxy implantada na VPC do consumidor. Estamos usando o peering de DNS para resolver o FQDN em uma etapa posterior.
%%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)

No notebook do JupyterLab, crie uma célula e execute o seguinte:

%%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"]

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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

No notebook do JupyterLab, crie uma célula e execute o seguinte: Ignore o erro (gcloud.builds.submit) se ele aparecer.

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

No notebook do JupyterLab, crie e execute a célula abaixo. Observe os seguintes destaques:

  • O peering de DNS para VPCs consumidoras é configurado usando dnsPeeringConfigs (dnsPeeringConfigs) para o nome de domínio demo.com.
  • O proxy explícito, definido como a variável PROXY_VM_IP, é proxy-vm.demo.com. A resolução é processada pelo peering de DNS na VPC do consumidor.
  • A porta 8888 é a porta de escuta (padrão) configurada no tinyproxy.
  • O Wget para class-e-vm-demo.com é resolvido por peering de DNS.
  • O código especifica o "psc-network-attachment" para o Vertex, permitindo que ele use a sub-rede de anexo de rede para implantar duas instâncias de interface do 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))

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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)

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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)

No notebook do JupyterLab, crie uma célula e execute o seguinte:

# 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__))"

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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

No notebook do JupyterLab, crie uma célula e execute o seguinte:

# 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"}

No notebook do JupyterLab, crie uma célula e execute o seguinte:

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")

No notebook do JupyterLab, crie uma célula e execute o seguinte:

# 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. Validação da interface do PSC

Também é possível conferir os IPs de anexação de rede usados pelo Vertex AI Pipelines navegando até:

Serviços de rede → Private Service Connect → Anexo de rede → psc-network-attachment

Selecione o projeto do locatário (nome do projeto que termina em -tp).

f47150235fedb8ce.png

O campo destacado indica o endereço IP usado pelo Vertex AI Pipelines no anexo de rede PSC.

39e7b251aeb4f191.png

15. Validação do Cloud Logging

O job do Vertex AI Pipelines leva cerca de 14 minutos para ser executado pela primeira vez. As execuções subsequentes são muito mais rápidas. Para validar um resultado positivo, faça o seguinte:

Acesse Vertex AI → Treinamento → Jobs personalizados

Selecione o job personalizado executado.

a9be0395c842aa6f.png

Selecione "Ver registros"

53e30765ba5827f3.png

Quando o Cloud Logging estiver disponível, selecione "Executar consulta", que gera a seleção destacada abaixo e confirma um wget bem-sucedido dos Pipelines da Vertex AI para a classe-e-vm.

f2c5d9fdf5cc8bed.png

3b3788603bb433ee.png

16. Validação do TCPDump

Vamos analisar a saída do TCPDUMP que valida ainda mais a conectividade com instâncias de computação:

Na proxy-vm, observe o 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 classe-e-vm, observe o 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. Limpar

No Cloud Shell, exclua os componentes do 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. Parabéns

Parabéns, você configurou e validou uma interface do Private Service Connect com o Vertex AI Pipelines.

Você criou a infraestrutura do consumidor e adicionou um anexo de rede que permitiu ao produtor criar uma VM de várias NICs para fazer a ponte entre a comunicação do consumidor e do produtor. Você aprendeu a criar um peering de DNS ao implantar um proxy explícito na rede VPC do consumidor, o que permitiu a conectividade com a instância de VM de classe E que não pode ser roteada diretamente do Vertex.

A Cosmopup acha que os tutoriais são incríveis!

c911c127bffdee57.jpeg

Qual é a próxima etapa?

Leituras e vídeos complementares

Documentos de referência