Integracja Agent Engine (ADK) z PSC SWP

1. Wprowadzenie

Interfejs Private Service Connect to zasób, który umożliwia sieci prywatnego środowiska wirtualnego w chmurze (VPC) dostawcy inicjowanie połączeń z różnymi miejscami docelowymi w sieci VPC konsumenta. Sieci producenta i konsumenta mogą znajdować się w różnych projektach i organizacjach.

Jeśli przyłącze sieci akceptuje połączenie z interfejsu Private Service Connect, Google Cloud przydziela interfejsowi adres IP z podsieci konsumenta określonej przez przyłącze sieci. Sieci konsumenta i dostawcy są połączone i mogą komunikować się za pomocą wewnętrznych adresów IP.

Połączenie między przyłączem sieci a interfejsem Private Service Connect jest podobne do połączenia między punktem końcowym Private Service Connect a przyłączem usługi, ale ma 2 kluczowe różnice:

  • Przyłącze sieci umożliwia sieci producenta inicjowanie połączeń z siecią konsumenta (ruch wychodzący usługi zarządzanej), a punkt końcowy umożliwia sieci konsumenta inicjowanie połączeń z siecią producenta (ruch przychodzący usługi zarządzanej).
  • Połączenie interfejsu Private Service Connect jest przechodnie. Oznacza to, że sieć producenta może komunikować się z innymi sieciami połączonymi z siecią konsumenta.

Wskazówki dotyczące dostępności interfejsu PSC Vertex AI

  • Interfejs PSC może kierować ruch do miejsc docelowych w sieci VPC lub lokalnych, które zostały poznane przez sieć VPC.
  • Aby ograniczyć zakres dostępności z połączenia sieciowego używanego przez Agent Engine do sieci VPC, najlepszym rozwiązaniem jest wdrożenie reguł zapory sieciowej ruchu wychodzącego.
  • Aby ograniczyć zakres wychodzącego ruchu sieciowego pochodzącego z podsieci przyłączenia sieciowego Agent Engine, należy wdrożyć regułę zapory sieciowej VPC dotyczącą ruchu wychodzącego. Ta reguła jawnie zezwoli na ruch z Agent Engine do SWP, a odrzuci cały inny ruch wychodzący.

Kwestie dotyczące VPC-SC interfejsu PSC Vertex AI

  • Aby interfejs PSC Agent Engine działał, musisz zapewnić łączność wychodzącą z internetu w sieci VPC klienta, nawet jeśli włączone są Ustawienia usługi VPC.

Bezpieczny internetowy serwer proxy

Bezpieczny internetowy serwer proxy to zarządzana usługa natywna dla chmury, która zapewnia szczegółową kontrolę i bezpieczeństwo ruchu wychodzącego (HTTP/HTTPS). Pełni funkcję centralnej bramy, która umożliwia egzekwowanie zasad bezpieczeństwa w przypadku połączeń inicjowanych przez Agent Engine wdrożony za pomocą interfejsu PSC z zasobami VPC, takimi jak maszyny wirtualne, GKE, internet i środowiska wielochmurowe.

Rozwiązanie

  • Zapobiega wydobywaniu danych: blokuje nieautoryzowane przesyłanie plików lub komunikację ze złośliwymi witrynami.
  • Wymusza zgodność: zapewnia, że ruch wychodzący jest zgodny z zasadami bezpieczeństwa i zasadami dotyczącymi danych obowiązującymi w organizacji.
  • Zmniejsza narzut operacyjny: jako usługa w pełni zarządzana Secure Web Proxy eliminuje konieczność wdrażania, skalowania i utrzymywania własnych maszyn wirtualnych proxy.
  • Zapewnia szczegółowy wgląd: umożliwia inspekcję ruchu zaszyfrowanego za pomocą protokołu TLS (Transport Layer Security) w celu wykrywania ukrytych zagrożeń.

Więcej informacji znajdziesz w tych materiałach:

Wdrażanie agenta | Generatywna AI w Vertex AI | Google Cloud

Konfigurowanie interfejsu Private Service Connect dla zasobów Vertex AI | Google Cloud

Co utworzysz

W tym samouczku utworzysz kompleksowy Agent Engine wdrożony z interfejsem Private Service Connect (PSC) zintegrowanym z SWP, aby wykonać te czynności przy użyciu bibliotek ADK:

  • Wdróż peering DNS w Agent Engine, aby rozwiązać w konfiguracji serwera proxy w ramach procesu czyszczenia konta w interfejsie PSC pełną i jednoznaczną nazwę domeny.
  • Zezwalaj na łączność z witryną publiczną (https://api.frankfurter.app/) za pomocą Secure Web Proxy wdrożonego w sieci VPC konsumenta z adresem RFC1918.
  • Zezwalaj na ruch z podsieci przyłącza sieci do SWP, a odrzucaj cały pozostały ruch.

Rysunek 1.

565e9eb07ef18f44.png

Czego się nauczysz

  • Tworzenie przyłącza sieci
  • Jak producent może użyć przyłącza sieci do utworzenia interfejsu PSC
  • Nawiązywanie komunikacji od dostawcy do konsumenta za pomocą DNS Peering
  • Jak wdrożyć i używać SWP na potrzeby ruchu wychodzącego z internetu
  • Jak zdefiniować reguły zapory sieciowej dotyczące ruchu wychodzącego, aby ograniczyć dostępność sieci Agent Engine

Czego potrzebujesz

Projekt Google Cloud

Uprawnienia

2. Zanim zaczniesz

Aktualizowanie projektu na potrzeby samouczka

W tym samouczku używamy zmiennych $variables, aby ułatwić wdrażanie konfiguracji gcloud w Cloud Shell.

W Cloud Shell wykonaj te czynności:

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

Włączanie interfejsu API

W Cloud Shell wykonaj te czynności:

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 "iap.googleapis.com"
gcloud services enable "networksecurity.googleapis.com"
gcloud services enable "networkservices.googleapis.com"
gcloud services enable "cloudresourcemanager.googleapis.com"

Sprawdzanie, czy interfejsy API zostały włączone

gcloud services list --enabled

3. Konfiguracja konsumencka

Tworzenie sieci VPC konsumenta

Ta sieć VPC znajduje się w projekcie klienta. W tej sieci VPC zostaną utworzone te zasoby:

  • Podsieć konsumencka
  • Podsieć przyłącza sieci
  • Podsieć tylko-proxy
  • Reguły zapory sieciowej
  • Cloud DNS

W Cloud Shell wykonaj te czynności:

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

Tworzenie podsieci konsumenta

W Cloud Shell utwórz podsieć dla SWP:

gcloud compute networks subnets create swp-subnet --project=$projectid --range=10.10.10.0/28 --network=consumer-vpc --region=us-central1 --enable-private-ip-google-access

Utwórz podsieć przyłącza sieci Private Service Connect

W Cloud Shell utwórz podsieć dla przyłącza sieci PSC:

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

Utwórz regionalną podsieć proxy

W Cloud Shell utwórz podsieć tylko-proxy wymaganą w przypadku usług opartych na Envoy, takich jak Secure Web Proxy oraz regionalne wewnętrzne i zewnętrzne systemy równoważenia obciążenia aplikacji. Flaga –purpose musi mieć wartość REGIONAL_MANAGED_PROXY:

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

Utwórz podsieć notatnika

W Cloud Shell utwórz podsieć dla instancji notatnika:

gcloud compute networks subnets create notebook-subnet --project=$projectid --range=192.168.20.0/28 --network=consumer-vpc --region=us-central1 --enable-private-ip-google-access

4. Tworzenie Secure Web Proxy

Tryb jawny Secure Web Proxy (lub tryb routingu jawnego serwera proxy) to metoda wdrażania, w której obciążenia klienta muszą być jawnie skonfigurowane do używania wewnętrznego adresu IP lub pełnej i jednoznacznej nazwy domeny oraz portu SWP jako serwera proxy przekazującego.

Ta zasada będzie zawierać reguły, które regulują ruch przez bezpieczny internetowy serwer proxy na podstawie dopasowania sesji host() == 'api.frankfurter.app' i dopasowania aplikacji request.method == 'GET'.

W poniższych krokach zastąp YOUR-PROJECT-ID identyfikatorem projektu.

W Cloud Shell utwórz plik policy.yaml:

cat > policy.yaml << EOF
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy 
description: "My basic SWP policy" 
EOF

W Cloud Shell zaimportuj zasady:

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

Tworzenie reguł Secure Web Proxy

Zdefiniuj w zasadach reguły, które określają, jaki ruch jest dozwolony, a jaki zabroniony. Reguły są sprawdzane według priorytetu.

W Cloud Shell utwórz plik rule.yaml, aby zezwolić na dostęp do punktu końcowego internetu używanego przez silnik agenta, api.frankfurter.app:

cat > rule.yaml << EOF
name: "projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy/rules/allow-example"
description: "Allow frankfurter API"
enabled: true
priority: 10
basicProfile: ALLOW
sessionMatcher: "host() == 'api.frankfurter.app'"
EOF

W Cloud Shell wygeneruj regułę zasady zabezpieczeń:

gcloud network-security gateway-security-policies rules import allow-example \
    --source=rule.yaml \
    --location=us-central1 \
    --gateway-security-policy=my-swp-policy

Tworzenie reguł Secure Web Proxy

Instancja SWP, która jest wdrażana w trybie jawnego routingu, musi być utworzona w taki sposób, aby silnik agenta musiał określać adres IP lub w pełni kwalifikowaną nazwę domeny SWP w konfiguracji serwera proxy ADK, zgodnie z definicją w pliku YAML bramy. Ta konfiguracja łączy też instancję z odpowiednią zasadą, siecią i podsiecią.

W Cloud Shell utwórz plik gateway.yaml, który będzie używany do wdrażania platformy SWP.

Po zaktualizowaniu tych zmiennych o szczegóły środowiska (PROJECT_ID, REGION, NETWORK_NAME i PROXY_ONLY_SUBNET_NAME) zapisz plik YAML. Określony port 8888 to zewnętrzny port tunelu zmapowany na konfigurację serwera proxy w Agent Engine.

cat > gateway.yaml << EOF
name: "projects/$projectid/locations/us-central1/gateways/my-swp-instance"
type: SECURE_WEB_GATEWAY
ports: [8888]
addresses: ["10.10.10.5"]
gatewaySecurityPolicy: "projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy"
network: "projects/$projectid/global/networks/consumer-vpc"
subnetwork: "projects/$projectid/regions/us-central1/subnetworks/swp-subnet"
routingMode: EXPLICIT_ROUTING_MODE
EOF

W Cloud Shell zaimportuj bramę:

gcloud network-services gateways import my-swp-instance \
    --source=gateway.yaml \
    --location=us-central1

5. Przyłącze sieci Private Service Connect

Przyłącza sieci to zasoby regionalne, które reprezentują stronę konsumenta interfejsu Private Service Connect. Z przyłączem sieci możesz powiązać jedną podsieć, a producent przypisuje adresy IP do interfejsu Private Service Connect z tej podsieci. Podsieć musi znajdować się w tym samym regionie co przyłącze sieci. Przyłącze sieci musi znajdować się w tym samym regionie co usługa producenta.

Tworzenie przyłącza sieci

W Cloud Shell utwórz przyłącze sieci.

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

Wyświetlanie listy przyłączy sieci

W Cloud Shell wyświetl listę przyłączy sieci.

gcloud compute network-attachments list

Opisz przyłącza sieci

W Cloud Shell opisz przyłącze sieciowe.

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

Zanotuj nazwę przyłącza sieci PSC, psc-network-attachment, która będzie używana przez producenta podczas tworzenia interfejsu Private Service Connect.

Aby wyświetlić adres URL przyłączenia sieci PSC w konsoli Google Cloud, otwórz:

Network Services → Private Service Connect → Network Attachment → psc-network-attachment

15f80b46c3a0332d.png

6. Prywatna strefa DNS

Utwórz strefę Cloud DNS dla demo.com i wypełnij ją rekordem A, który wskazuje adresy IP platformy SWP. Później w Agent Engine zostanie wdrożona komunikacja równorzędna DNS, która umożliwi dostęp do rekordów DNS konsumenta.

W Cloud Shell wykonaj te czynności, aby utworzyć nazwę DNS demo.com.

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"

Uzyskaj i zapisz adresy IP platformy usług Google używane w rekordzie DNS A.

W Cloud Shell wykonaj opis instancji swp, my-swp-instance:

gcloud network-services gateways describe my-swp-instance --location=us-central1

W Cloud Shell utwórz zestaw rekordów dla SWP, swp.demo.com. Pamiętaj, aby zaktualizować adres IP na podstawie danych wyjściowych środowiska.

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

Konfiguracja zapory sieciowej

Tworzenie reguły zapory sieciowej Cloud Firewall, która zezwala na dostęp z interfejsu PSC

W następnej sekcji utwórz regułę zapory sieciowej, która zezwala na ruch pochodzący z sieci PSC do podsieci SWP w sieci VPC klienta. Aby zwiększyć bezpieczeństwo, możesz określić adres IP SWP jako jedyne miejsce docelowe.

W Cloud Shell utwórz regułę zapory sieciowej ruchu wychodzącego, która zezwala na dostęp z przyłącza sieci do SWP:

gcloud compute firewall-rules create allow-access-to-swp \
    --network=consumer-vpc \
    --action=ALLOW \
    --rules=ALL \
    --direction=EGRESS \
    --priority=1000 \
    --source-ranges="192.168.10.0/28" \
    --destination-ranges="10.10.10.5/32" \
    --enable-logging

W Cloud Shell utwórz regułę zapory sieciowej ruchu wychodzącego, która odrzuca cały ruch z przyłącza sieci:

gcloud compute firewall-rules create deny-all \
    --network=consumer-vpc \
    --action=DENY \
    --rules=ALL \
    --direction=EGRESS \
    --priority=65534 \
    --source-ranges="192.168.10.0/28" \
    --destination-ranges="0.0.0.0/0" \
    --enable-logging

7. Utwórz zasadę zapory sieciowej dla sieci VPC, aby zapewnić ochronę przed zagrożeniami:

W sekcji poniżej utwórz zasadę zapory sieciowej, która umożliwi Ci korzystanie z zarządzanych przez Google list zagrożeń w celu blokowania znanych złośliwych witryn, zanim ruch dotrze do platformy ochrony usług.

W Cloud Shell utwórz globalną zasadę zapory sieciowej:

gcloud compute network-firewall-policies create psc-secure-policy \
    --global \
    --description="Policy to protect VPC with Threat Intelligence"

W Cloud Shell powiąż zasadę z siecią VPC:

gcloud compute network-firewall-policies associations create \
    --firewall-policy=psc-secure-policy \
    --network=consumer-vpc \
    --name=psc-swp-association \
    --global-firewall-policy

W Cloud Shell dodaj reguły Threat Intelligence:

Te reguły odrzucą ruch pochodzący od znanych złośliwych podmiotów, zanim zainicjują ruch z agenta. W tym przykładzie dodaliśmy reguły blokowania węzłów wyjściowych TOR (ruch wychodzący), blokowania znanych szkodliwych adresów IP (ruch wychodzący), blokowania znanych anonimowych serwerów proxy(ruch wychodzący) i blokowania programów do wydobywania kryptowalut, aby zapobiec nieautoryzowanemu użyciu zasobów (ruch wychodzący).

gcloud compute network-firewall-policies rules create 100 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-tor-exit-nodes \
    --layer4-configs=all \
    --enable-logging \
    --description="Block anonymous Tor traffic" \
    --global-firewall-policy
gcloud compute network-firewall-policies rules create 110 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-known-malicious-ips \
    --layer4-configs=all \
    --enable-logging \
    --description="Block known botnets and malware sources" \
    --global-firewall-policy
gcloud compute network-firewall-policies rules create 120 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-anon-proxies \
    --layer4-configs=all \
    --enable-logging \
    --description="Block Known Anonymous Proxies" \
    --global-firewall-policy
gcloud compute network-firewall-policies rules create 130 \
    --firewall-policy=psc-secure-policy \
    --action=deny \
    --direction=EGRESS \
    --dest-threat-intelligence=iplist-crypto-miners \
    --layer4-configs=all \
    --enable-logging \
    --description="Block Crypto Miners (Prevent unauthorized resource usage)" \
    --global-firewall-policy

8. Tworzenie notatnika Jupyter

W sekcji poniżej znajdziesz instrukcje tworzenia notatnika Jupyter. Ten notatnik będzie używany do wdrażania Agent Engine z określonym serwerem proxy na potrzeby wychodzącego ruchu internetowego.

Tworzenie konta usługi zarządzanego przez użytkownika

W następnej sekcji utworzysz konto usługi, które będzie powiązane z instancją Vertex AI Workbench używaną w tym samouczku.

W tym samouczku do konta usługi zostaną przypisane te role:

W Cloud Shell utwórz konto usługi.

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

W Cloud Shell zaktualizuj konto usługi, przypisując mu rolę Administrator miejsca na dane.

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

W Cloud Shell zaktualizuj konto usługi, przypisując mu rolę użytkownika Vertex AI.

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

W Cloud Shell zaktualizuj konto usługi, przypisując mu rolę Administrator Artifact Registry.

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

W Cloud Shell zezwól kontu usługi notatnika na używanie domyślnego konta usługi 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"

9. Tworzenie instancji Vertex AI Workbench

W następnej sekcji utwórz instancję Vertex AI Workbench, która zawiera utworzone wcześniej konto usługi notebook-sa.

W Cloud Shell utwórz instancję 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=notebook-subnet --disable-public-ip --shielded-secure-boot=true --shielded-integrity-monitoring=true --shielded-vtpm=true --service-account-email=notebook-sa@$projectid.iam.gserviceaccount.com     

Dodaj kolejną regułę do istniejącego Secure Web Proxy, aby przekierowywać ruch z tej instancji notatnika:

W Cloud Shell utwórz plik rule-notebook.yaml za pomocą edytora tekstu. Pamiętaj, aby zaktualizować plik YAML o identyfikator projektu.

cat > rule-notebook.yaml << EOF
name: projects/$projectid/locations/us-central1/gatewaySecurityPolicies/my-swp-policy/rules/allow-notebook-subnet
description: Allow Internet access for notebook subnet
enabled: true
priority: 2
basicProfile: ALLOW
sessionMatcher: inIpRange(source.ip,'192.168.20.2')
EOF

W Cloud Shell wygeneruj regułę zasady zabezpieczeń:

gcloud network-security gateway-security-policies rules import allow-notebook-subnet \
    --source=rule-notebook.yaml \
    --location=us-central1 \
    --gateway-security-policy=my-swp-policy

10. Aktualizacja agenta usługi Vertex AI

Vertex AI działa w Twoim imieniu, aby wykonywać operacje takie jak uzyskiwanie adresu IP z podsieci przyłącza sieci PSC używanej do tworzenia interfejsu PSC. W tym celu Vertex AI używa agenta usługi (wymienionego poniżej), który wymaga uprawnień administratora sieci:

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

W Cloud Shell uzyskaj numer projektu.

gcloud projects describe $projectid | grep projectNumber

W Cloud Shell ustaw numer projektu.

projectnumber=YOUR-PROJECT-NUMBER

W Cloud Shell utwórz konto usługi dla AI Platform. Pomiń ten krok, jeśli w projekcie masz już konto usługi.

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

W Cloud Shell zaktualizuj konto agenta usługi, przypisując mu rolę compute.networkAdmin.

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

W Cloud Shell zaktualizuj konto agenta usługi, przypisując mu rolę dns.peer.

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

Aktualizacja domyślnego konta usługi

Przyznaj domyślnemu kontu usługi dostęp do Vertex AI. Pamiętaj, że zastosowanie zmiany dostępu może potrwać.

W Cloud Shell zaktualizuj domyślne konto usługi, przypisując mu rolę aiplatform.user.

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

11. Wdrażanie Agent Engine

Uwaga: do wykonania zadań w tej sekcji użyjemy konsoli GCP i notatnika JupyterLab.

W kolejnej sekcji utworzysz notatnik, który będzie wykonywać te zadania:

  • Korzysta z interfejsu Frankfurter API (https://api.frankfurter.app/) do pobierania danych o kursach wymiany.
  • Odwołuje się do jawnego serwera proxy (proxy_server) kierowanego na SWP w sieci VPC konsumentów przy użyciu w pełni kwalifikowanej nazwy domeny swp.demo.com.
  • Zdefiniuj dnsPeeringConfigs "domain": "demo.com."

Uruchom zadanie trenowania w instancji Vertex AI Workbench.

  • W konsoli Google Cloud otwórz Vertex AI → Workbench.
  • Obok nazwy instancji Vertex AI Workbench (workbench-tutorial) kliknij Otwórz JupyterLab. Instancja Vertex AI Workbench otworzy się w JupyterLab.
  • Wybierz: File > New > Notebook
  • Wybierz: Kernel > Python 3

Zainstaluj niezbędne biblioteki Pythona: zainstaluj biblioteki wymagane przez Agent Engine, w tym pyyaml, google-cloud-aiplatform, cloudpickle, google-cloud-api-keys i langchain-google-vertexai.

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie, podając adres IP SWP:

7b827a6a38bb5afc.png

!pip install --proxy http://10.10.10.5:8888 --upgrade google-cloud-aiplatform[agent_engines,adk]

W poniższym fragmencie kodu zdefiniuj te zmienne na podstawie swojego środowiska:

  • PROJECT_ID
  • BUCKET_NAME
  • AGENT_NAME

W tym laboratorium użyjesz zmiennych BUCKET_NAME i AGENT_NAME do zainicjowania i skonfigurowania zasobnika pamięci, który jest dostępny globalnie.

W sekcji poniżej zdefiniowano PROXY_SERVER, np.swp.demo.com, który wymaga komunikacji równorzędnej DNS do rozpoznawania nazw. W konfiguracji AGENT_PEER_DOMAIN jest wdrażana jako demo.com, co odpowiada prywatnej strefie DNS utworzonej we wcześniejszym kroku w sieci AGENT_PEER_NETWORK, consumer-vpc.

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie:

# --- Fundamental Project Configuration ---
PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "us-central1" # e.g., "us-central1"
BUCKET_NAME = "YOUR_BUCKET_NAME" # A GCS bucket in the same location

# --- Agent Configuration ---
AGENT_NAME = "YOUR_AGENT_NAME"
MODEL = "gemini-2.5-flash" # Or another suitable model

# --- Network and Proxy Configuration ---
# The agent will call the Frankfurter API via this proxy
PROXY_SERVER = "http://swp.demo.com:8888"

# --- Deployment Configuration (PSC & DNS Peering) ---
# This should be a pre-existing Network Attachment
NETWORK_ATTACHMENT_NAME = f"projects/{PROJECT_ID}/regions/{LOCATION}/networkAttachments/psc-network-attachment"
# Optional DNS Peering config
AGENT_PEER_DOMAIN = "demo.com."
AGENT_PEER_NETWORK = "consumer-vpc"

# --- Initialize Vertex AI SDK ---
import vertexai
STAGING_BUCKET = f"gs://{BUCKET_NAME}"

vertexai.init(project=PROJECT_ID, location=LOCATION, staging_bucket=STAGING_BUCKET)

print(f"Vertex AI SDK initialized for project {PROJECT_ID} in {LOCATION}.")

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie:

!adk create $AGENT_NAME --model=$MODEL --project=$PROJECT_ID --region=$LOCATION

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie, aby utworzyć zmienną proxy odpowiadającą w pełni kwalifikowanej nazwie domeny i portowi SWP.

import os
os.environ["PROXY_SERVER_URL"] = "http://swp.demo.com:8888"

W tej komórce kodu pokazujemy konfigurację jawnego serwera proxy dla Agent Engine, która umożliwia dostęp do punktu końcowego internetu api.frankfurter.app przez określenie SWP za pomocą PROXY_SERVER_TO_USE, które jest mapowane na os.environ["PROXY_SERVER_URL"]..

import requests
# Use the globally defined proxy server URL
    proxies = {
       "http": PROXY_SERVER_TO_USE,
       "https": PROXY_SERVER_TO_USE,
    }
    try:
        response = requests.get(
            f"https://api.frankfurter.app/{currency_date}",
            params={"from": currency_from, "to": currency_to},
            proxies=proxies,
) 
response.raise_for_status() 
print(response.json()) 
except requests.exceptions.RequestException as e: print(f"An error occurred: {e}")

W notatniku JupyterLab utwórz nową komórkę i uruchom poniższy kod, który definiuje implementację narzędzia dla interfejsu API kierowania na wymianę walut api.frankfurther.app.

%%writefile $AGENT_NAME/agent.py
from google.adk.agents.llm_agent import Agent
import os
import requests


# Get Proxy Server URL
# This is the VM's FQDN to reach the proxy vm in the consumers network
if "PROXY_SERVER_URL" not in os.environ:
    raise ValueError("Missing required environment variable: PROXY_SERVER_URL is not set.")
PROXY_SERVER_TO_USE = os.environ["PROXY_SERVER_URL"]

# Mock tool implementation
def get_exchange_rate(
    currency_from: str = "USD",
    currency_to: str = "EUR",
    currency_date: str = "latest",
):
    """Retrieves the exchange rate between two currencies on a specified date.

    Uses the Frankfurter API (https://api.frankfurter.app/) to obtain
    exchange rate data.

    Args:
        currency_from: The base currency (3-letter currency code).
            Defaults to "USD" (US Dollar).
        currency_to: The target currency (3-letter currency code).
            Defaults to "EUR" (Euro).
        currency_date: The date for which to retrieve the exchange rate.
            Defaults to "latest" for the most recent exchange rate data.
            Can be specified in YYYY-MM-DD format for historical rates.

    Returns:
        dict: A dictionary containing the exchange rate information.
            Example: {"amount": 1.0, "base": "USD", "date": "2023-11-24",
                "rates": {"EUR": 0.95534}}
    """
    # Use the globally defined proxy server URL
    proxies = {
       "http": PROXY_SERVER_TO_USE,
       "https": PROXY_SERVER_TO_USE,
    }
    
    try:
        response = requests.get(
            f"https://api.frankfurter.app/{currency_date}",
            params={"from": currency_from, "to": currency_to},
            proxies=proxies,
        )
        response.raise_for_status()  # Raise an error for bad responses
        return response.json()
    except Exception as e:
        return f"An unexpected error occurred: {e}"

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description="Provides the currency exchange rates between two currencies",
    instruction="You are a helpful assistant that provides the currency exchange rates between two currencies. Use the 'get_exchange_rate' tool for this purpose.",
    tools=[get_exchange_rate],
)

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie:

# 1. Set your variables
CURRENCY_DATE="latest"
CURRENCY_FROM="USD"
CURRENCY_TO="EUR"
PROXY_SERVER="http://swp.demo.com:8888"

# 2. Run the curl command
!curl -x "$PROXY_SERVER" "https://api.frankfurter.app/$CURRENCY_DATE?from=$CURRENCY_FROM&to=$CURRENCY_TO"

W notatniku JupyterLab utwórz nową komórkę i uruchom poniższy kod, który wywołuje konfigurację interfejsu PSC używaną przez Agent Engine, a także peering DNS.

import json
import os

CONFIG_FILE_PATH = os.path.join(AGENT_NAME, ".agent_engine_config.json")
# Create your config as a Python dictionary ---
config_data = {
    "requirements": [
        "google-cloud-aiplatform[agent_engines,adk]",
        "requests",
    ],
    "psc_interface_config": {
        "network_attachment": NETWORK_ATTACHMENT_NAME,
        "dns_peering_configs": [
            {
                "domain": AGENT_PEER_DOMAIN,
                "target_project": PROJECT_ID,
                "target_network": AGENT_PEER_NETWORK,
            },
        ],
    },
}

# Write the dictionary to a JSON file ---
os.makedirs(AGENT_NAME, exist_ok=True) # Ensure the directory exists
with open(CONFIG_FILE_PATH, 'w') as f:
    json.dump(config_data, f, indent=4)

print(f"Successfully created {CONFIG_FILE_PATH} with your variables.")

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie:

import json
import os

CONFIG_FILE_PATH = os.path.join(AGENT_NAME, ".agent_engine_config.json")
# Create your config as a Python dictionary ---
config_data = {

    "psc_interface_config": {
        "network_attachment": NETWORK_ATTACHMENT_NAME,
        "dns_peering_configs": [
            {
                "domain": AGENT_PEER_DOMAIN,
                "target_project": PROJECT_ID,
                "target_network": AGENT_PEER_NETWORK,
            },
        ],
    },
}

# Write the dictionary to a JSON file ---
os.makedirs(AGENT_NAME, exist_ok=True) # Ensure the directory exists
with open(CONFIG_FILE_PATH, 'w') as f:
    json.dump(config_data, f, indent=4)

print(f"Successfully created {CONFIG_FILE_PATH} with your variables.")

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie:

%%writefile $AGENT_NAME/.env

GOOGLE_CLOUD_PROJECT=PROJECT_ID
GOOGLE_CLOUD_LOCATION=us-central1
GOOGLE_GENAI_USE_VERTEXAI=1


PROXY_SERVER_URL=http://swp.demo.com:8888

W notatniku JupyterLab utwórz nową komórkę i uruchom ten kod, aby utworzyć agenta.

!adk deploy agent_engine $AGENT_NAME --staging_bucket=$STAGING_BUCKET --env_file=$AGENT_NAME/.env --agent_engine_config_file=$AGENT_NAME/.agent_engine_config.json --display_name=$AGENT_NAME

Identyfikator silnika rozumowania zostanie wygenerowany po uruchomieniu komórki. W następnym kroku będziesz potrzebować wygenerowanego identyfikatora, który w tym przykładzie ma postać 3235268984265768960.

✅ Created agent engine: projects/9315891080/locations/us-central1/reasoningEngines/3235268984265768960

W notatniku JupyterLab utwórz nową komórkę i uruchom poniższy kod. Pamiętaj, aby zaktualizować go o numer projektu i identyfikator uzasadnienia Agent Engine z poprzedniego wyniku:

from vertexai import agent_engines
remote_app = agent_engines.get("projects/PROJECT_NUMBER/locations/us-central1/reasoningEngines/ENTER_YOUR_ID")

W notatniku JupyterLab utwórz nową komórkę i uruchom to polecenie:

def print_event_nicely_with_thoughts(event):
    """
    Parses and prints streaming query events, including thoughts.
    """
    try:
        content = event.get('content', {})
        role = content.get('role')
        parts = content.get('parts', [{}])

        if not parts:
            print("...")
            return

        part = parts[0] # Get the first part

        # Event 1: Model is thinking (calling a tool or just text)
        if role == 'model':

            # Check for and print any explicit 'thought' text
            if 'thought' in part:
                print(f"🧠 Thought: {part['thought']}")

            # Check for a function call
            if 'function_call' in part:
                # If we haven't *already* printed an explicit thought,
                # print a generic one.
                if 'thought' not in part:
                    print("🧠 Thinking... (decided to use a tool)")

                call = part['function_call']
                print(f"   🔧 Tool Call: {call.get('name')}()")
                print(f"      Args: {call.get('args')}")

            # Check for the final text answer
            elif 'text' in part:
                text = part.get('text', '')
                print(f"\n💬 Model: {text}")

        # Event 2: The tool returns its result
        elif role == 'user' and 'function_response' in part:
            resp = part['function_response']
            print(f"⚙️ Tool Response (from {resp.get('name')}):")
            print(f"   Output: {resp.get('response')}")

        # Other event types (like progress messages)
        else:
            print("...") # Show progress for other events

    except Exception as e:
        print(f"Error processing event: {e}")
        # print(f"Raw event: {event}") # Uncomment to debug



for event in remote_app.stream_query(
    user_id="u_456",
    # session_id=remote_session["id"],
    message="Provide USD to INR conversion rate",
):
    print_event_nicely_with_thoughts(event)

Przykład udanego wykonania, które weryfikuje połączenie z publicznym punktem końcowym api.frankfurther.app za pomocą SWP na podstawie kursu wymiany USD na INR.

f9f925983ab5cc9d.png

12. Weryfikacja interfejsu PSC

Adresy IP dołączone do sieci używane przez Agent Engine możesz też wyświetlić, wykonując te czynności:

Usługi sieciowe → Private Service Connect → Przyłącze sieci → psc-network-attachment

Wybierz projekt najemcy (nazwa projektu kończy się na -tp).

c9c412334a7f5ad9.png

Wyróżnione pole oznacza adres IP używany przez Agent Engine z załącznika sieci PSC.

e94c6c03fb51f7fe.png

13. SWP - Cloud Logging Validation

Aby sprawdzić, czy SWP wykonuje ruch wychodzący z internetu, możesz wyświetlić Cloud Logging. W tym celu wykonaj te czynności:

Monitorowanie → Eksplorator logów

Wstaw zapytanie: resource.type=" networkservices.googleapis.com/Gateway", a potem kliknij Uruchom zapytanie. Poniżej znajduje się przykład potwierdzający punkt końcowy docelowy, api.frankfurter.app.

f53831ef8ec663db.pngfc154a5b22da2a87.png

Poniższy przykład Cloud Logging sprawdza:

Destination_range: adres IP interfejsu PSC Agent Engine

Source_range: Podsieć tylko-proxy Dest_ip: Adres IP Secure Web Proxy

Pamiętaj, aby zmienić project_id w zapytaniu dotyczącym logowania w chmurze.

logName:("projects/project_id/logs/compute.googleapis.com%2Ffirewall") AND jsonPayload.rule_details.reference:("network:consumer-vpc/firewall:allow-access-to-swp")
{
  "insertId": "1j9ym95fmu8g6o",
  "jsonPayload": {
    "vpc": {
      "project_id": "XXXXXXXXXXXXX",
      "subnetwork_name": "intf-subnet",
      "vpc_name": "consumer-vpc"
    },
    "rule_details": {
      "destination_range": [
        "10.10.10.5/32"
      ],
      "reference": "network:consumer-vpc/firewall:allow-access-to-swp",
      "priority": 1000,
      "source_range": [
        "192.168.10.0/28"
      ],
      "direction": "EGRESS",
      "ip_port_info": [
        {
          "ip_protocol": "ALL"
        }
      ],
      "action": "ALLOW"
    },
    "disposition": "ALLOWED",
    "remote_instance": {
      "region": "us-central1"
    },
    "remote_vpc": {
      "vpc_name": "consumer-vpc",
      "project_id": "XXXXXXXXXXXXXXX",
      "subnetwork_name": "swp-subnet"
    },
    "connection": {
      "src_ip": "192.168.10.2",
      "src_port": 48640,
      "dest_port": 8888,
      "dest_ip": "10.10.10.5",
      "protocol": 6
    }
  },
  "resource": {
    "type": "gce_subnetwork",
    "labels": {
      "subnetwork_id": "7147084067647653041",
      "project_id": "XXXXXXXXXXXXXX",
      "location": "us-central1",
      "subnetwork_name": "intf-subnet"
    }
  },
  "timestamp": "2025-12-30T12:51:36.628538815Z",
  "logName": "projects/dec30-run1-agent/logs/compute.googleapis.com%2Ffirewall",
  "receiveTimestamp": "2025-12-30T12:51:40.846652708Z"
}

14. Czyszczenie danych

W notatniku JupyterLab utwórz nową komórkę i uruchom poniższy kod, który spowoduje usunięcie wdrożenia silnika agenta.

Sprawdź, czy aktualizujesz "project number" i "reasoningEngines token".

import requests
token = !gcloud auth application-default print-access-token
ENDPOINT = "https://us-central1-aiplatform.googleapis.com"
response = requests.delete(
    f"{ENDPOINT}/v1beta1/projects/218166745590/locations/us-central1/reasoningEngines/3086854705725308928",
    params={"force": "true"},
    headers={
        "Content-Type": "application/json; charset=utf-8",
        "Authorization": f"Bearer {token[0]}"
    },
)
print(response.text)

W Cloud Shell usuń komponenty samouczka.

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

gcloud network-security gateway-security-policies rules delete allow-notebook-subnet \
    --gateway-security-policy=my-swp-policy \
    --location=us-central1

gcloud network-security gateway-security-policies rules delete allow-example \
    --gateway-security-policy=my-swp-policy \
    --location=us-central1

gcloud network-security gateway-security-policies delete my-swp-policy \
    --location=us-central1
gcloud network-services gateways delete my-swp-instance\
    --location=us-central1

gcloud dns record-sets delete swp.demo.com --zone=private-dns-codelab  --type=A

gcloud dns managed-zones delete private-dns-codelab


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

export ROUTER_NAME=$(gcloud compute routers list --regions=us-central1 \
    --filter="name ~ swg-autogen-router" --format="value(name)")


 gcloud compute routers nats delete swg-autogen-nat --router=$ROUTER_NAME --region=us-central1 --quiet 

gcloud compute routers delete $ROUTER_NAME --region=us-central1 --quiet

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

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

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

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

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

gcloud compute networks delete consumer-vpc --quiet

15. Gratulacje

Gratulacje. Udało Ci się skonfigurować i zweryfikować Agent Engine wdrożony z interfejsem Private Service Connect z ruchem wychodzącym z internetu wykonywanym przez jawny serwer proxy.

Ty utworzyłeś infrastrukturę konsumenta i dodałeś przyłącze sieci, które umożliwiło producentowi utworzenie maszyny wirtualnej z wieloma interfejsami sieciowymi, aby połączyć komunikację konsumenta i producenta. Dowiedziałeś(-aś) się, jak utworzyć jawny serwer proxy i połączenie równorzędne DNS, które umożliwiają łączność z internetem.

Cosmopup uważa, że samouczki są świetne!!

e6d3675ca7c6911f.jpeg

Co dalej?

Więcej informacji i filmy

Dokumentacja