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 producenta inicjowanie połączeń z różnymi miejscami docelowymi w sieci prywatnego środowiska wirtualnego w chmurze konsumenta. Sieci producenta i odbiorcy 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 producenta 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 osiągalnoś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 osiągalności z przyłącza 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 internetem 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). Działa jako centralna brama, która umożliwia egzekwowanie zasad bezpieczeństwa w przypadku połączeń inicjowanych przez Agent Engine wdrożony z interfejsem PSC do zasobów VPC, takich jak maszyny wirtualne, GKE, internet i środowiska wielochmurowe.

Rozwiązanie

  • Zapobiega wydobywaniu danych: blokuje nieautoryzowane przesyłanie plików i 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 nakłady operacyjne: 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 SWP.
  • Zezwalaj na połączenie z publiczną witryną (https://api.frankfurter.app/) przez Secure Web Proxy wdrożony w sieci VPC klienta i mający adres RFC1918.
  • Zezwalaj na ruch z podsieci przyłączenia do sieci do SWP, a odrzucaj cały inny ruch.

Rysunek 1.

565e9eb07ef18f44.png

Czego się nauczysz

  • Tworzenie przyłącza sieci
  • Jak producent może używać przyłącza sieci do tworzenia interfejsu PSC
  • Jak nawiązać komunikację od producenta 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ć implementację 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 bezpieczny internetowy serwer proxy i regionalne wewnętrzne/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 jawnego routingu 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 pamiętaj, aby zastąpić symbol 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 określające, 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 routingu jawnego, 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 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 silniku agenta.

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

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, które są używane w rekordzie A DNS.

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

Utwórz regułę 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łączenia sieciowego 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 załącznika sieciowego:

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 usługi SWP.

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 będą odrzucać ruch pochodzący od znanych podmiotów złośliwych, zanim zainicjują ruch z agenta. W tym przykładzie dodaliśmy reguły blokowania węzłów wyjściowych sieci 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 wykorzystaniu 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 wyraźnym serwerem proxy dla ruchu wychodzącego z internetu.

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żytkownik 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 sekcji poniżej 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, wykonując 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 zanim zmiana dostępu zostanie zastosowana, może minąć trochę czasu.

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 serwera proxy (proxy_server) kierowanego na SWP w sieci VPC konsumentów za pomocą 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 w niej ten kod, 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 masowej, 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

Po uruchomieniu komórki zostanie wygenerowany identyfikator silnika wnioskowania. W następnym kroku potrzebny będzie wygenerowany identyfikator, 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 silnika agenta 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 łączność 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 połączenia sieciowego używane przez Agent Engine możesz też sprawdzić, wykonując te czynności:

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

Wybierz projekt najemcy (nazwa projektu kończąca 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, otwórz Cloud Logging:

Monitorowanie → Eksplorator logów

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

f53831ef8ec663db.png

fc154a5b22da2a87.png

Ten 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 logów 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""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ć silnik agenta wdrożony za pomocą interfejsu Private Service Connect z ruchem wychodzącym z internetu realizowanym przez jawny serwer proxy.

Infrastruktura konsumenta została utworzona, a do niej dodano przyłącze sieci, które umożliwiło producentowi utworzenie maszyny wirtualnej z wieloma interfejsami sieciowymi, aby połączyć komunikację konsumenta i producenta. Wiesz już, 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