SWP 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.

d7dc28d6567e6283.pngFigura 1

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

  • A interface PSC da Vertex AI consegue rotear o tráfego para destinos em uma VPC ou no local dentro do bloco de endereços RFC1918.
  • O direcionamento de interface da PSC para 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 modo de proxy explícito Secure Web Proxy (SWP) configurado na VPC do consumidor para facilitar o roteamento para os seguintes CIDRs não RFC-1918:
  1. 240.0.0.0/4
  2. 203.0.113.0/24
  3. 10.10.20.0/28 não exige proxy e está no intervalo RFC-1918.
  4. Saída para a Internet

Conexão com a Internet para a rede de locatário gerenciada pelo Google:

Interface do PSC da Vertex AI sem VPC-SC

  • 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 gerenciada pelo Google.

Interface do PSC da Vertex AI com o VPC-SC

  • Quando seu projeto faz parte de um perímetro do VPC Service Controls, o acesso padrão à Internet do locatário gerenciado 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 conectada à Vertex AI. Uma maneira de fazer isso é implantar um servidor proxy na rede VPC com endereço RFC 1918, pareado com um gateway do Cloud NAT. Também é possível usar o Secure Web Proxy para encaminhar o tráfego à Internet. A criação do Secure Web Proxy cria automaticamente um gateway do Cloud NAT.

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 uma interface do Private Service Connect (PSC) para permitir a conectividade do produtor com a computação do consumidor, conforme ilustrado na Figura 1, segmentando um endpoint não RFC 1918 em class-e-subnet.

2d095dc2f4de6b4b.pngFigura 2

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

Implante o Vertex AI Pipelines e configure o Secure Web Proxy em um modo de proxy explícito, permitindo que ele 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 o peering de DNS para resolver domínios particulares configurados na rede VPC do consumidor nas redes VPC gerenciadas pelo Google
  • Como encaminhar o tráfego da interface do PSC da Vertex AI para o Secure Web Proxy
  • Como estabelecer comunicação com o espaço de endereços IP não RFC-1918 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 $variáveis 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-ID]
projectid=YOUR-PROJECT-ID
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"
gcloud services enable "networkservices.googleapis.com"
gcloud services enable "networksecurity.googleapis.com"
gcloud services enable "certificatemanager.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 --enable-private-ip-google-access

Criar a sub-rede somente proxy

gcloud compute networks subnets create proxy-only-uscentral1 \
    --purpose=REGIONAL_MANAGED_PROXY \
    --role=ACTIVE \
    --region=us-central1 \
    --network=consumer-vpc \
    --range=10.10.100.0/26

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 \
--enable-private-ip-google-access

Configuração do Cloud Router e do NAT

O Secure Web Proxy do Google Cloud provisiona e gerencia automaticamente um gateway do Cloud NAT e um Cloud Router associado na região em que ele é implantado.

4. Ativar o IAP

Para permitir que o IAP (proxy com reconhecimento de identidade) se conecte às 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 \ 
    --private-network-ip=240.0.0.2

6. Proxy seguro da Web

O modo explícito do Secure Web Proxy (ou modo de roteamento de proxy explícito) é um método de implantação em que as cargas de trabalho do cliente precisam ser configuradas explicitamente para usar o endereço IP interno ou o nome de domínio totalmente qualificado e a porta do SWP como proxy de encaminhamento.

Nas etapas abaixo, modifique YOUR-PROJECT-ID para o ID do seu projeto.

Criar um proxy da Web:

No Cloud Shell, crie o arquivo policy.yaml usando um editor de texto:

cat > policy.yaml << EOF
description: basic Secure Web Proxy policy
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/policy1
EOF

No Cloud Shell, gere a política do Secure Web Proxy:

gcloud network-security gateway-security-policies import policy1 \
    --source=policy.yaml \
    --location=us-central1

Na seção a seguir, crie uma regra para permitir o acesso ao class-e-vm com base no host sessionMatcher.

No Cloud Shell, crie o arquivo rule1.yaml usando um editor de texto:

cat > rule1.yaml << EOF
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/policy1/rules/allow-nonrfc-classe
description: Allow nonrfc class-e
enabled: true
priority: 1
basicProfile: ALLOW
sessionMatcher: host() == 'class-e-vm.demo.com'
EOF

Na seção a seguir, crie uma regra para permitir que o notebook Jupyter acesse a instalação do apache2 na VM "class-e".

No Cloud Shell, crie o arquivo rule2.yaml usando um editor de texto:

cat > rule2.yaml << EOF
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/policy1/rules/allow-apache2
description: Allow Apache2 install on class-e VM
enabled: true
priority: 2
basicProfile: ALLOW
sessionMatcher: inIpRange(source.ip,'240.0.0.2')
EOF

No Cloud Shell, gere a regra 1 da política de segurança:

gcloud network-security gateway-security-policies rules import allow-nonrfc-classe \
    --source=rule1.yaml \
    --location=us-central1 \
    --gateway-security-policy=policy1

No Cloud Shell, gere a regra2 da política de segurança:

gcloud network-security gateway-security-policies rules import allow-apache2 \
    --source=rule2.yaml \
    --location=us-central1 \
    --gateway-security-policy=policy1

Para oferecer suporte ao Vertex AI Training, configure o gateway Secure Web Proxy com estas configurações:

  • Porta de escuta: use a mesma porta configurada nas configurações de proxy explícitas do código do aplicativo da Vertex AI (por exemplo, 8080).
  • Endereço: atribua um endereço IP particular do intervalo RFC 1918.
  • Modo de roteamento: defina como EXPLICIT_ROUTING_MODE

No Cloud Shell, crie um arquivo gateway.yaml para definir o gateway do Secure Web Proxy:

cat > gateway.yaml << EOF
name: projects/$projectid/locations/us-central1/gateways/swp1
type: SECURE_WEB_GATEWAY
addresses: ["10.10.10.5"]
ports: [8080]
gatewaySecurityPolicy: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/policy1
network: projects/$projectid/global/networks/consumer-vpc
subnetwork: projects/$projectid/regions/us-central1/subnetworks/rfc1918-subnet1
routingMode: EXPLICIT_ROUTING_MODE
EOF

No Cloud Shell, gere a instância do Secure Web Proxy:

gcloud network-services gateways import swp1 \
    --source=gateway.yaml \
    --location=us-central1

A implantação de um Secure Web Proxy pode levar vários minutos.

e8a4cf23bfc63030.png

7. 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_MANUAL \
    --subnets=intf-subnet

Observação:não é necessário mencionar explicitamente o ID do projeto aceito neste anexo. Quando o projeto de locatário gerenciado pelo Google da Vertex AI é configurado, ele é adicionado automaticamente como se estivesse configurado como "Aceitar automaticamente".

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 do anexo de rede do PSC, 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

b969cca5242d9c8a.png

8. 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 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, 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 o Secure Web Proxy e atualize o endereço IP com base na saída do seu ambiente.

gcloud dns --project=$projectid record-sets create explicit-swp.demo.com. --zone="private-dns-codelab" --type="A" --ttl="300" --rrdatas="10.10.10.5"

Criar uma regra de firewall do Cloud 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 aos recursos de computação RFC 1918 na VPC dos consumidores.

No Cloud Shell, crie a regra de firewall de entrada que permite o acesso da sub-rede somente proxy à sub-rede de classe E. Como o SWP inicia a conexão com a sub-rede somente proxy como endereço de origem.

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.100.0/28" \
    --destination-ranges="240.0.0.0/4" \
    --enable-logging

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 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á os seguintes papéis aplicados:

Faça login no Cloud Shell e execute o seguinte:

Crie a conta de serviço.

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

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"

Atualize a conta de serviço com o papel de usuário da AI Platform.

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

Atualize a conta de serviço com o papel de administrador do Artifact Registry.

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

Atualize a conta de serviço com o papel Editor do Cloud Build.

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

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 de cliente particular.

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 realiza operações em seu nome, 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

Observação: antes de atualizar as permissões do agente de serviço, acesse a Vertex AI no console do Cloud para garantir que a API Vertex AI esteja ativada.

No Cloud Shell:

Consiga o número do projeto.

gcloud projects describe $projectid | grep projectNumber

Defina o número do projeto.

projectnumber=YOUR-PROJECT-NUMBER

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

Atualize a conta do agente de serviço com o papel compute.networkAdmin.

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

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.

Use o Cloud Shell para atualizar a conta de serviço padrão da seguinte maneira:

Atualize a conta de serviço padrão com o papel aiplatform.user

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

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"

Atualize a conta de serviço padrão com o papel artifactregistry.admin

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

12. Instale o Apache2 e ative o tcpdump em "class-e-vm":

Na instalação do class-e-vm, instale o apache2 usando o Secure Web Proxy:

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
sudo apt-get -o Acquire::http::Proxy="http://10.10.10.5:8080" update
sudo apt-get -o Acquire::http::Proxy="http://10.10.10.5:8080" install apache2 -y
sudo service apache2 restart
echo 'class-e Server !!' | sudo tee /var/www/html/index.html

Execute a filtragem tcpdump na sub-rede somente proxy, usada pelo Secure Web Proxy para encaminhar o tráfego aos destinos.

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

sudo tcpdump -i any net 10.10.100.0/24 -nn

Observação:ative o Acesso privado do Google na sub-rede da instância workbench-tutorial para que a sessão do JupyterLab seja aberta.

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 que você alcance 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 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://explicit-swp.demo.com:8080"
  • Um 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 nonRFC-1918 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://explicit-swp.demo.com:8080" # replace it with your Secure Web proxy Ip-address and the 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 da Web no modo de roteamento explícito aqui é explicit-swp.demo.com. A resolução é processada via peering de DNS na VPC do consumidor.
  • A porta 8080 é a porta de escuta (padrão) configurada no Secure Web Proxy.
  • wget para class-e-vm-demo.com é resolvido pelo 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 = "explicit-swp.demo.com" #@param {type:"string"}
PROXY_VM_PORT = "8080" #@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 vinculaçã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 de locatário (nome do projeto que termina em -tp).

a2e0b6d6243f26f1.png

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

11e411ea919d3bad.png

15. Validação do Cloud Logging

O job do Vertex AI Pipelines vai levar aproximadamente 14 minutos para ser executado pela primeira vez. As execuções subsequentes são muito mais rápidas. Para validar um resultado bem-sucedido, faça o seguinte:

Acesse Vertex AI → Treinamento → Jobs personalizados

Selecione o job personalizado executado.

2f467254aa0c2e3a.png

Selecione "Ver registros".

8d525d3b152bcc61.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 o class-e-vm.

a4f9e9167f4ce1ae.png

38972f834aa2bd1d.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:

Em class-e-vm, observe o HTTP GET e 200 OK

XXXXXXXXX@class-e-vm:~$ sudo tcpdump -i any net 10.10.100.0/28 -nn
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
05:51:14.173641 ens4  In  IP 10.10.100.8.55306 > 240.0.0.2.80: Flags [S], seq 1747181041, win 65535, options [mss 1420,sackOK,TS val 3942828403 ecr 0,nop,wscale 8], length 0
05:51:14.173668 ens4  Out IP 240.0.0.2.80 > 10.10.100.8.55306: Flags [S.], seq 3013226100, ack 1747181042, win 64768, options [mss 1420,sackOK,TS val 1886125065 ecr 3942828403,nop,wscale 7], length 0
05:51:14.174977 ens4  In  IP 10.10.100.8.55306 > 240.0.0.2.80: Flags [.], ack 1, win 1054, options [nop,nop,TS val 3942828405 ecr 1886125065], length 0
05:51:14.175066 ens4  In  IP 10.10.100.8.55306 > 240.0.0.2.80: Flags [P.], seq 1:223, ack 1, win 1054, options [nop,nop,TS val 3942828405 ecr 1886125065], length 222: HTTP: GET / HTTP/1.1
05:51:14.175096 ens4  Out IP 240.0.0.2.80 > 10.10.100.8.55306: Flags [.], ack 223, win 505, options [nop,nop,TS val 1886125066 ecr 3942828405], length 0
05:51:14.239042 ens4  Out IP 240.0.0.2.80 > 10.10.100.8.55306: Flags [P.], seq 1:246, ack 223, win 505, options [nop,nop,TS val 1886125130 ecr 3942828405], length 245: HTTP: HTTP/1.1 200 OK

17. Limpar

No Cloud Shell, exclua os componentes do tutorial.

gcloud workbench instances delete workbench-tutorial --project=$projectid --location=us-central1-a

gcloud network-security gateway-security-policies rules delete allow-nonrfc-classe \
    --gateway-security-policy=policy1 \
    --location=us-central1

gcloud network-security gateway-security-policies rules delete allow-apache2 \
    --gateway-security-policy=policy1 \
    --location=us-central1

gcloud network-security gateway-security-policies delete policy1 \
    --location=us-central1
gcloud network-services gateways delete swp1 \
    --location=us-central1

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 explicit-swp.demo.com --zone=private-dns-codelab  --type=A

gcloud dns managed-zones delete private-dns-codelab

gcloud computeinstances delete class-e-vm --project=$projectid --zone=us-central1-a --quiet
gcloud compute networks delete consumer-vpc --quiet

18. Parabéns

Parabéns! Você configurou e validou uma conexão entre a interface do Private Service Connect da Vertex AI Pipelines e intervalos de IP não RFC usando o Secure Web Proxy.

Você criou a infraestrutura do consumidor e adicionou um anexo de rede que permitiu ao produtor criar uma VM multi-NIC 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 class-e-vm que não pode ser roteada diretamente do Vertex.

678ba30d64a76795.png

Qual é a próxima etapa?

Leituras e vídeos complementares

Documentos de referência