Интеграция Agent Engine (ADK) PSC SWP

1. Введение

Интерфейс Private Service Connect — это ресурс, позволяющий сети виртуальной частной сети (VPC) производителя инициировать соединения с различными пунктами назначения в сети VPC потребителя. Сети производителя и потребителя могут находиться в разных проектах и ​​организациях.

Если сетевое соединение принимает подключение от интерфейса Private Service Connect, Google Cloud выделяет этому интерфейсу IP-адрес из подсети потребителя, указанной в сетевом соединении. Сети потребителя и производителя соединяются и могут обмениваться данными, используя внутренние IP-адреса.

Соединение между сетевым устройством и интерфейсом Private Service Connect аналогично соединению между конечной точкой Private Service Connect и сервисным устройством, но имеет два ключевых отличия:

  • Сетевое подключение позволяет сети-производителю инициировать соединения с сетью-потребителем (исходящий трафик управляемых сервисов), а конечная точка позволяет сети-потребителю инициировать соединения с сетью-производителем (входящий трафик управляемых сервисов).
  • Соединение через интерфейс Private Service Connect является транзитивным. Это означает, что сеть-производитель может взаимодействовать с другими сетями, подключенными к сети потребителя.

Вопросы доступности интерфейса PSC в Vertex AI

  • PSC-Interface способен маршрутизировать трафик к адресам, расположенным в VPC или локальной сети, которые были определены сетью VPC.
  • Для ограничения зоны доступности сети, используемой Agent Engine, к сети VPC, рекомендуется использовать правила межсетевого экрана для исходящего трафика.
  • Для ограничения исходящего сетевого трафика, исходящего из подсети подключения Agent Engine, следует развернуть правило брандмауэра для исходящего трафика VPC. Это правило будет явно разрешать трафик от Agent Engine к SWP, запрещая при этом весь остальной исходящий трафик.

Вопросы, касающиеся интерфейса Vertex AI PSC и VPC-SC.

  • You must provide internet egress connectivity within the customer VPC for the Agent Engine PSC-Interface to function, even if VPC Service Controls are enabled.

Защищенный веб-прокси

Secure Web Proxy — это управляемый облачный сервис, предоставляющий детальный контроль и безопасность исходящего трафика (HTTP/HTTPS). Он выступает в качестве центрального шлюза, позволяя применять политики безопасности к соединениям, инициированным из Agent Engine, развернутого с PSC Interface, к ресурсам VPC, таким как виртуальные машины, GKE, интернет и мультиоблачные среды.

Что это решает

  • Предотвращает утечку данных: блокирует несанкционированную загрузку или связь со вредоносными сайтами.
  • Обеспечивает соответствие требованиям: гарантирует, что исходящий трафик соответствует политикам безопасности и обработки данных вашей организации.
  • Снижает операционные издержки: будучи полностью управляемым сервисом, Secure Web Proxy устраняет необходимость развертывания, масштабирования или обслуживания собственных виртуальных машин прокси.
  • Обеспечивает глубокий анализ: позволяет проверять зашифрованный трафик протокола Transport Layer Security (TLS) для выявления скрытых угроз.

Для получения дополнительной информации обратитесь к следующим ресурсам:

Развертывание агента | Генеративный ИИ на платформе Vertex AI | Google Cloud

Set up a Private Service Connect interface for Vertex AI resources | Google Cloud

Что вы построите

В этом руководстве вы создадите комплексный Agent Engine, развернутый с использованием интерфейса Private Service Connect (PSC) и интегрированный с SWP, для выполнения следующих задач с помощью библиотек ADK:

  • Разверните DNS-пиринг в Agent Engine для разрешения полного доменного имени SWP, используемого в конфигурации прокси.
  • Разрешите подключение к общедоступному сайту (https://api.frankfurter.app/) через защищенный веб-прокси, развернутый в VPC потребителя с адресом RFC1918.
  • Разрешите трафик из подсети сетевого подключения к SWP, запретив при этом все остальное.

Рисунок 1

565e9eb07ef18f44.png

Что вы узнаете

  • Как создать сетевое подключение
  • Как производитель может использовать сетевое подключение для создания интерфейса PSC
  • Как установить связь между производителем и потребителем с помощью DNS-пиринга
  • Как развернуть и использовать SWP для исходящего интернет-трафика
  • Как определить правила межсетевого экрана для исходящего трафика, чтобы ограничить доступность сети Agent Engine.

Что вам понадобится

Проект Google Cloud

Разрешения IAM

2. Прежде чем начать

Обновите проект, чтобы он соответствовал учебному пособию.

В этом руководстве переменные `$variables` используются для упрощения настройки gcloud в Cloud Shell.

Внутри Cloud Shell выполните следующие действия:

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

Включение API

Внутри Cloud Shell выполните следующие действия:

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"

Убедитесь, что API успешно включены.

gcloud services list --enabled

3. Настройка потребителя

Создайте потребительскую VPC.

Эта VPC находится в проекте клиента. В этой VPC будут созданы следующие ресурсы.

  • Потребительская подсеть
  • Подсеть сетевого подключения
  • Подсеть только для прокси
  • Правила брандмауэра
  • Облачный DNS

Внутри Cloud Shell выполните следующие действия:

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

Создайте потребительские подсети.

Внутри Cloud Shell создайте подсеть для 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

Создайте подсеть подключения к частной сети (Private Service Connect Network Attachment).

Внутри Cloud Shell создайте подсеть для сетевого подключения 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

Создайте региональную подсеть прокси-сервера.

Внутри Cloud Shell создайте подсеть, предназначенную только для прокси-сервера, необходимую для продуктов на базе Envoy, таких как Secure Web Proxy и Regional Internal/External Application Load Balancers. Флаг –purpose должен быть установлен в значение 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

Создайте подсеть для ноутбуков.

Внутри Cloud Shell создайте подсеть для экземпляра ноутбука:

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. Создайте безопасный веб-прокси.

Явный режим Secure Web Proxy (или режим явной маршрутизации прокси) — это метод развертывания, при котором клиентские рабочие нагрузки должны быть явно настроены на использование внутреннего IP-адреса или полного доменного имени и порта SWP в качестве прокси-сервера переадресации.

Данная политика будет содержать правила, регулирующие трафик через защищенный веб-прокси на основе соответствия сессии, host() == 'api.frankfurter.app' и соответствия приложения request.method == 'GET'

В следующих шагах обязательно измените YOUR-PROJECT-ID на идентификатор вашего проекта.

Внутри Cloud Shell создайте файл policy.yaml :

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

Внутри Cloud Shell импортируйте политику:

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

Создание правил безопасного веб-прокси

В рамках политики определите правила, которые разрешают или запрещают трафик. Правила оцениваются на основе приоритета.

Внутри Cloud Shell создайте файл rule.yaml, разрешающий доступ к интернет-точке, используемой агентом 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

В Cloud Shell создайте правило политики безопасности:

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

Создание правил безопасного веб-прокси

Экземпляр SWP, развернутый в режиме явной маршрутизации, должен быть создан таким образом, чтобы Agent Engine был обязан указывать IP-адрес или полное доменное имя (FQDN) SWP в конфигурации прокси-сервера ADK, как определено в YAML-файле шлюза. Эта конфигурация также связывает экземпляр с соответствующей политикой, сетью и подсетью.

Внутри Cloud Shell создайте файл gateway.yaml, используемый для развертывания SWP.

Обязательно сохраните YAML-файл после обновления следующих переменных с указанием данных вашей среды: PROJECT_ID, REGION, NETWORK_NAME и PROXY_ONLY_SUBNET_NAME. Указанный порт 8888 — это внешний туннельный порт, сопоставленный с конфигурацией прокси-сервера в 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

Внутри Cloud Shell импортируйте шлюз:

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

5. Подключение к сети Private Service Connect

Сетевые подключения — это региональные ресурсы, представляющие собой потребительскую сторону интерфейса Private Service Connect. Вы связываете одну подсеть с сетевым подключением, а производитель назначает IP-адреса интерфейсу Private Service Connect из этой подсети. Подсеть должна находиться в том же регионе, что и сетевое подключение. Сетевое подключение должно находиться в том же регионе, что и служба производителя.

Создайте сетевое подключение.

Внутри Cloud Shell создайте сетевое подключение.

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

Перечислите сетевые подключения.

Внутри Cloud Shell отобразите список сетевых подключений.

gcloud compute network-attachments list

Опишите сетевые подключения.

Внутри Cloud Shell опишите сетевое подключение.

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

Запишите имя сетевого подключения PSC, psc-network-attachment , которое будет использоваться производителем при создании интерфейса подключения к частной службе.

Чтобы просмотреть URL-адрес сетевого подключения PSC в Cloud Console, перейдите по следующей ссылке:

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

15f80b46c3a0332d.png

6. Частная DNS-зона

Вы создадите зону Cloud DNS для demo.com и заполните её записью A, указывающей на IP-адреса ваших SWP. Позже в Agent Engine будет развернут DNS-пиринг, который обеспечит доступ к DNS-записям потребителя.

Внутри Cloud Shell выполните следующие действия, чтобы создать 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"

Получите и сохраните IP-адреса SWP, используемых для записи DNS A.

Внутри Cloud Shell выполните команду describe для экземпляра swp, my-swp-instance:

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

Внутри Cloud Shell создайте набор записей для SWP, swp.demo.com, и обязательно обновите IP-адрес в соответствии с выводом вашей среды.

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

Настройка брандмауэра

Создайте правило облачного брандмауэра, разрешающее доступ через интерфейс PSC.

В следующем разделе создайте правило брандмауэра, разрешающее трафику, исходящему от сетевого подключения PSC, доступ к подсети SWP в потребительской VPC. Для повышения уровня безопасности можно указать IP-адрес SWP в качестве единственного адреса назначения.

В Cloud Shell создайте правило брандмауэра для исходящего трафика, разрешающее доступ к 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

В Cloud Shell создайте правило исходящего брандмауэра, запрещающее весь трафик из сетевого подключения:

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. Создайте политику брандмауэра для сети VPC, чтобы обеспечить сбор информации об угрозах:

В следующем разделе создайте политику брандмауэра, которая позволит вам использовать управляемые списки угроз Google для блокировки известных вредоносных сайтов до того, как трафик будет получен SWP.

В Cloud Shell создайте глобальную политику брандмауэра:

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

В Cloud Shell свяжите политику с вашей VPC:

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

В Cloud Shell добавьте правила анализа угроз:

Эти правила будут блокировать трафик, направленный на известных злоумышленников, прежде чем инициировать трафик от агента. В этом примере мы добавили правила для блокировки выходных узлов Tor (исходящий трафик), блокировки известных вредоносных IP-адресов (исходящий трафик), блокировки известных анонимных прокси-серверов (исходящий трафик) и блокировки криптомайнеров для предотвращения несанкционированного использования ресурсов (исходящий трафик).

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. Создайте блокнот Jupyter.

В следующем разделе вы узнаете, как создать блокнот Jupyter. Этот блокнот будет использоваться для развертывания Agent Engine, нацеленного на явный прокси-сервер для исходящего интернет-трафика.

Создайте управляемую пользователем учетную запись службы.

В следующем разделе вы создадите учетную запись службы, которая будет связана с экземпляром Vertex AI Workbench, используемым в этом руководстве.

В данном руководстве к учетной записи службы будут применены следующие роли:

Внутри Cloud Shell создайте учетную запись службы.

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

Внутри Cloud Shell обновите учетную запись службы, присвоив ей роль администратора хранилища.

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

Внутри Cloud Shell обновите учетную запись службы, присвоив ей роль пользователя Vertex AI.

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

Внутри Cloud Shell обновите учетную запись службы, присвоив ей роль администратора реестра артефактов.

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

Внутри Cloud Shell разрешите учетной записи службы ноутбука использовать учетную запись службы 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. Создайте экземпляр Vertex AI Workbench.

В следующем разделе создайте экземпляр Vertex AI Workbench, который будет использовать ранее созданную учетную запись службы notebook-sa.

Внутри Cloud Shell создайте экземпляр частного клиента.

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     

Добавьте еще одно правило в существующий защищенный веб-прокси для переадресации трафика с этого экземпляра ноутбука:

В Cloud Shell создайте файл rule-notebook.yaml с помощью текстового редактора, обязательно указав в YAML идентификатор вашего проекта.

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

В Cloud Shell создайте правило политики безопасности:

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. Обновление агента службы Vertex AI

Vertex AI действует от вашего имени для выполнения таких операций, как получение IP-адреса из подсети сетевого подключения PSC, используемой для создания интерфейса PSC. Для этого Vertex AI использует сервисный агент (указан ниже), для работы которого требуются права сетевого администратора :

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

Внутри Cloud Shell получите номер своего проекта.

gcloud projects describe $projectid | grep projectNumber

Inside Cloud Shell, set your project number.

projectnumber=YOUR-PROJECT-NUMBER

Внутри Cloud Shell создайте учетную запись службы для AI Platform. Пропустите этот шаг, если в вашем проекте уже есть учетная запись службы.

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

Внутри Cloud Shell обновите учетную запись агента службы, добавив ей роль compute.networkAdmin.

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

Внутри Cloud Shell обновите учетную запись агента службы, добавив ей роль dns.peer.

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

Обновление учетной записи службы по умолчанию

Предоставьте вашей учетной записи службы по умолчанию доступ к Vertex AI. Обратите внимание, что для распространения изменений в доступе может потребоваться некоторое время.

Внутри Cloud Shell обновите учетную запись службы по умолчанию, добавив ей роль aiplatform.user.

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

11. Разверните механизм агентов.

Примечание: Для выполнения заданий в этом разделе мы будем использовать консоль GCP и блокнот JupyterLab.

В следующем разделе вы создадите блокнот, выполняющий следующие задачи:

  • Использует API Frankfurter (https://api.frankfurter.app/) для получения данных об обменном курсе.
  • Указывает на явный прокси-сервер (proxy_server), нацеленный на SWP в VPC потребителей, используя полное доменное имя swp.demo.com.
  • Определите параметры dnsPeeringConfigs "domain": "demo.com."

Запустите задачу обучения в экземпляре Vertex AI Workbench.

  • В консоли Google Cloud перейдите в Vertex AI → Workbench
  • Рядом с именем вашего экземпляра Vertex AI Workbench (workbench-tutorial) нажмите «Открыть JupyterLab». Ваш экземпляр Vertex AI Workbench откроется в JupyterLab.
  • Выберите File > New > Notebook
  • Выберите Kernel > Python 3

Установите необходимые библиотеки Python: установите библиотеки, необходимые для Agent Engine, включая pyyaml, google-cloud-aiplatform, cloudpickle, google-cloud-api-keys и langchain-google-vertexai.

В блокноте JupyterLab создайте новую ячейку и выполните следующую команду, указав IP-адрес SWP.

7b827a6a38bb5afc.png

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

В следующем фрагменте кода определите следующие переменные в соответствии с вашей средой:

  • Идентификатор_проекта
  • BUCKET_NAME
  • АГЕНТ_ИМЯ

В этой лабораторной работе вы будете использовать переменные BUCKET_NAME и AGENT_NAME для инициализации и настройки вашего глобального хранилища данных (storage bucket).

В следующем разделе определяется PROXY_SERVER, например, swp.demo.com, для разрешения имен которого требуется DNS-пиринг. В конфигурации AGENT_PEER_DOMAIN развертывается как demo.com, что соответствует частной DNS-зоне, созданной на предыдущем шаге в рамках AGENT_PEER_NETWORK, consumer-vpc.

В блокноте JupyterLab создайте новую ячейку и выполните следующее:

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

В блокноте JupyterLab создайте новую ячейку и выполните следующее.

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

В блокноте JupyterLab создайте новую ячейку и выполните следующую команду, чтобы создать переменную-прокси, соответствующую полному доменному имени (FQDN) и порту SWP.

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

Следующая ячейка кода демонстрирует явную настройку прокси-сервера для Agent Engine для доступа к интернет-адресу api.frankfurter.app путем указания SWP с использованием PROXY_SERVER_TO_USE , который сопоставляется с 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}")

В блокноте JupyterLab создайте новую ячейку и запустите следующий код, определяющий реализацию инструмента для обмена валют, ориентированного на 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],
)

В блокноте JupyterLab создайте новую ячейку и выполните следующее.

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

В блокноте JupyterLab создайте новую ячейку и выполните следующий код, который вызовет конфигурацию интерфейса psc, используемую Agent Engine, в дополнение к настройке 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.")

В блокноте JupyterLab создайте новую ячейку и выполните следующее.

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

В блокноте JupyterLab создайте новую ячейку и выполните следующее.

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

В блокноте JupyterLab создайте новую ячейку и выполните следующий код, чтобы создать агента.

!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

Идентификатор механизма рассуждений будет сгенерирован после выполнения ячейки. Для следующего шага вам понадобится сгенерированный идентификатор, который в данном примере равен 3235268984265768960 .

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

В блокноте JupyterLab создайте новую ячейку и выполните следующий код, обязательно указав номер проекта и идентификатор логического вывода Agent Engine из предыдущего вывода:

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

В блокноте JupyterLab создайте новую ячейку и выполните следующее.

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)

Пример успешного выполнения проверки подключения к общедоступной конечной точке api.frankfurther.app через SWP на основе курса конвертации USD в INR.

f9f925983ab5cc9d.png

12. Проверка интерфейса PSC

Также вы можете просмотреть IP-адреса сетевого подключения, используемые Agent Engine, перейдя по следующей ссылке:

Сетевые службы → Подключение к частной сети → Подключение к сети → psc-network-attachment

Выберите проект арендатора (название проекта заканчивается на -tp).

c9c412334a7f5ad9.png

Выделенное поле обозначает IP-адрес, используемый Agent Engine при подключении к сети PSC.

e94c6c03fb51f7fe.png

13. SWP - Проверка достоверности данных облачного логирования

Для просмотра логов облачных сервисов и проверки исходящего интернет-трафика, выполняемого SWP, перейдите по следующей ссылке:

Мониторинг → Журнал событий

Вставьте запрос: resource.type=" networkservices.googleapis.com/Gatewa y" , затем нажмите «Выполнить запрос». Ниже приведен пример, подтверждающий целевую конечную точку: api.frankfurter.app.

f53831ef8ec663db.png

fc154a5b22da2a87.png

Следующий пример облачного логирования подтверждает следующее:

Destination_range: IP-адрес интерфейса PSC агентского движка

Source_range: Подсеть только для прокси Dest_ip: IP-адрес защищенного веб-прокси

Обязательно измените project_id для запроса облачного логирования.

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. Уборка

В блокноте JupyterLab создайте новую ячейку и выполните следующий код, который запустит удаление развертывания Agent Engine.

Убедитесь, что вы обновляете "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)

В Cloud Shell удалите компоненты учебного пособия.

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. Поздравляем!

Поздравляем, вы успешно настроили и проверили Agent Engine, развернутый с использованием интерфейса Private Service Connect Interface, при этом исходящий трафик из интернета осуществляется через явно указанный прокси-сервер.

Вы создали инфраструктуру для потребителей и добавили сетевое подключение, которое позволило производителю создать виртуальную машину с несколькими сетевыми адаптерами для обеспечения связи между потребителями и производителем. Вы научились создавать явный прокси-сервер и DNS-пиринг, обеспечивающие подключение к Интернету.

Cosmopup считает, что обучающие материалы — это здорово!!

e6d3675ca7c6911f.jpeg

Что дальше?

Дополнительная литература и видеоматериалы

Справочная документация