1. Введение
Интерфейс Private Service Connect — это ресурс, позволяющий сети виртуальной частной сети (VPC) производителя инициировать соединения с различными пунктами назначения в сети VPC потребителя. Сети производителя и потребителя могут находиться в разных проектах и организациях.
Если сетевое соединение принимает подключение от интерфейса Private Service Connect, Google Cloud выделяет этому интерфейсу IP-адрес из подсети потребителя, указанной в сетевом соединении. Сети потребителя и производителя соединяются и могут обмениваться данными, используя внутренние IP-адреса.
Соединение между сетевым устройством и интерфейсом Private Service Connect аналогично соединению между конечной точкой Private Service Connect и сервисным устройством, но имеет два ключевых отличия:
- Сетевое подключение позволяет сети-производителю инициировать соединения с сетью-потребителем (исходящий трафик управляемых сервисов), а конечная точка позволяет сети-потребителю инициировать соединения с сетью-производителем (входящий трафик управляемых сервисов).
- A Private Service Connect interface connection is transitive. This means that a producer network can communicate with other networks that are connected to the consumer network.
Vertex AI PSC-Interface reachability considerations
- PSC-Interface is capable of routing traffic to VPC or on-premesis based destinations within the RFC1918 address block.
- Для работы PSC-интерфейса с блоками адресов, отличными от RFC-1918, требуется явное развертывание прокси-сервера в VPC потребителя с адресом RFC-1918. В рамках развертывания Vertex AI прокси-сервер должен быть определен вместе с полным доменным именем (FQDN) целевой конечной точки.
- When you configure your deployment with only a PSC Interface, it retains its default internet access. This outbound traffic egresses directly from the secure, Google-managed tenant network.
Вопросы, касающиеся интерфейса Vertex AI PSC и VPC-SC.
- When your project is part of a VPC Service Controls perimeter, the Google-managed tenants default internet access is blocked by the perimeter to prevent data exfiltration.
- To allow the deployment access to the public internet in this scenario, you must explicitly configure a secure egress path that routes traffic through your VPC.
- Рекомендуемый способ достижения этой цели — настройка прокси-сервера внутри периметра вашей VPC с адресом RFC1918 и создание шлюза Cloud NAT, чтобы разрешить виртуальной машине-прокси доступ к интернету.
For additional information, refer to the following resources:
Deploy an agent | Generative AI on Vertex AI | Google Cloud
Настройка интерфейса Private Service Connect для ресурсов Vertex AI | Google Cloud
Что вы построите
В этом руководстве вы создадите комплексный Agent Engine, развернутый с использованием интерфейса Private Service Connect (PSC), который позволит подключаться к общедоступному сайту (https://api.frankfurter.app/) через виртуальную машину-прокси, развернутую в VPC клиента с адресом RFC1918. Пример развертывания применим в проектах с поддержкой VPC-SC или для администраторов, которым требуется исходящий интернет через сеть клиента, а не через VPC арендатора.
Рисунок 1

Вам потребуется создать единое подключение psc-network-attachment в потребительской VPC, используя DNS-пиринг для разрешения имени прокси-виртуальной машины потребительской сети в проекте арендатора, где размещен Agent Engine, что приведет к следующим сценариям использования:
Deploy Agent Engine and configuring a proxy VM to act as an explicit proxy, allowing it to reach a public URL https://api.frankfurter.app
Что вы узнаете
- Как создать сетевое подключение
- Как производитель может использовать сетевое подключение для создания интерфейса PSC
- How to establish communication from the producer to the consumer using DNS Peering
- How to deploy and use a proxy vm for internet egress
Что вам понадобится
Проект Google Cloud
Разрешения IAM
- Compute Network Admin (roles/compute.networkAdmin)
- Администратор вычислительного экземпляра (roles/compute.instanceAdmin)
- Администратор безопасности вычислительных ресурсов (roles/compute.securityAdmin)
- Администратор DNS (roles/dns.admin)
- Пользователь туннеля, защищенный IAP (roles/iap.tunnelResourceAccessor)
- Ведение логов (roles/logging.admin)
- Администратор блокнотов (roles/notebooks.admin)
- Администратор IAM проекта (roles/resourcemanager.projectIamAdmin)
- Администратор учетной записи службы (roles/iam.serviceAccountAdmin)
- Администратор использования сервиса (roles/serviceusage.serviceUsageAdmin)
2. Прежде чем начать
Обновите проект, чтобы он соответствовал учебному пособию.
В этом руководстве переменные `$variables` используются для упрощения настройки gcloud в Cloud Shell.
Внутри Cloud Shell выполните следующие действия:
gcloud config list project
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"
Убедитесь, что API успешно включены.
gcloud services list --enabled
3. Настройка потребителя
Создайте потребительскую VPC.
Эта VPC находится в проекте клиента. В этой VPC будут созданы следующие ресурсы.
- Потребительская подсеть
- Подсеть сетевого подключения
- Облачный маршрутизатор (необходим для облачного NAT)
- Облачный NAT
Внутри Cloud Shell выполните следующие действия:
gcloud compute networks create consumer-vpc --project=$projectid --subnet-mode=custom
Создайте потребительские подсети.
Внутри Cloud Shell создайте подсеть для виртуальной машины-прокси:
gcloud compute networks subnets create rfc1918-subnet1 --project=$projectid --range=10.10.10.0/28 --network=consumer-vpc --region=us-central1
Создайте подсеть подключения к частной сети (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
Настройка облачного маршрутизатора и NAT.
В этом руководстве Cloud NAT используется для обеспечения доступа в интернет для виртуальной машины-прокси, которая не имеет публичного IP-адреса. Cloud NAT позволяет виртуальным машинам только с частными IP-адресами подключаться к интернету, что дает им возможность выполнять такие задачи, как установка программных пакетов.
Внутри Cloud Shell создайте Cloud Router.
gcloud compute routers create cloud-router-for-nat --network consumer-vpc --region us-central1
Внутри Cloud Shell создайте NAT-шлюз с включенным логированием. Мы будем использовать логирование для проверки доступа к публичному IP-адресу API Frankfurter (https://api.frankfurter.app/).
gcloud compute routers nats create cloud-nat-us-central1 --router=cloud-router-for-nat --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges --region us-central1 --enable-logging --log-filter=ALL
4. Включите IAP.
Чтобы разрешить IAP подключаться к вашим виртуальным машинам, создайте правило брандмауэра, которое:
- Применяется ко всем экземплярам виртуальных машин, к которым вы хотите обеспечить доступ с помощью IAP.
- Разрешает входящий трафик из диапазона IP-адресов 35.235.240.0/20. Этот диапазон содержит все IP-адреса, которые IAP использует для пересылки TCP-трафика.
Внутри Cloud Shell создайте правило брандмауэра IAP.
gcloud compute firewall-rules create ssh-iap-consumer \
--network consumer-vpc \
--allow tcp:22 \
--source-ranges=35.235.240.0/20
5. Создайте экземпляры виртуальных машин для потребителей.
В Cloud Shell создайте экземпляр виртуальной машины потребителя, proxy-vm, который будет служить явным прокси для Agent Engine. В качестве приложения для проксирования HTTP-трафика мы будем использовать tinyproxy.
gcloud compute instances create proxy-vm \
--project=$projectid \
--machine-type=e2-micro \
--image-family debian-11 \
--no-address \
--can-ip-forward \
--image-project debian-cloud \
--zone us-central1-a \
--subnet=rfc1918-subnet1 \
--shielded-secure-boot \
--metadata startup-script="#! /bin/bash
sudo apt-get update
sudo apt-get install tcpdump
sudo apt-get install tinyproxy -y
sudo apt-get install apache2 -y
sudo service apache2 restart
echo 'proxy server !!' | tee /var/www/html/index.html
EOF"
6. Подключение к сети 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, перейдите по следующей ссылке:
Сетевые службы → Подключение к частной сети → Подключение к сети → psc-network-attachment

7. Частная DNS-зона
Вы создадите зону Cloud DNS для demo.com и заполните её записью A, указывающей на IP-адреса вашей виртуальной машины-прокси. Позже в 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-адреса экземпляров, используемых для записей DNS A.
Внутри Cloud Shell выполните команду describe для экземпляров виртуальных машин.
gcloud compute instances describe proxy-vm --zone=us-central1-a | grep networkIP:
Внутри Cloud Shell создайте набор записей для виртуальной машины proxy-vm.demo.com, обязательно обновите IP-адрес в соответствии с выводом вашей среды.
gcloud dns --project=$projectid record-sets create proxy-vm.demo.com. --zone="private-dns-codelab" --type="A" --ttl="300" --rrdatas="10.10.10.2"
Создайте правило облачного брандмауэра, разрешающее доступ через интерфейс PSC.
В следующем разделе создайте правило брандмауэра, разрешающее трафику, исходящему от сетевого подключения PSC, доступ к прокси-виртуальной машине в потребительской VPC.
В Cloud Shell создайте правило входящего трафика брандмауэра.
gcloud compute firewall-rules create allow-access-to-compute \
--network=consumer-vpc \
--action=ALLOW \
--rules=ALL \
--direction=INGRESS \
--priority=1000 \
--source-ranges="192.168.10.0/28" \
--destination-ranges="10.10.10.0/28" \
--enable-logging
8. Создайте блокнот Jupyter.
В следующем разделе вы узнаете, как создать блокнот Jupyter. Этот блокнот будет использоваться для развертывания Agent Engine, нацеленного на явный прокси-сервер для исходящего интернет-трафика.
Создайте управляемую пользователем учетную запись службы.
В следующем разделе вы создадите учетную запись службы, которая будет связана с экземпляром Vertex AI Workbench, используемым в этом руководстве.
В данном руководстве к учетной записи службы будут применены следующие роли:
- Администратор хранилища
- Пользователь Vertex AI
- Администратор реестра артефактов
- Пользователь учетной записи службы IAM
Внутри 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. Обновите явный прокси-сервер.
В следующем разделе вам потребуется подключиться к явному прокси-серверу по SSH, обновить конфигурационный файл tinyproxy.conf, а затем выполнить сброс настроек.
Из Cloud Shell
gcloud compute ssh --zone us-central1-a "proxy-vm" --tunnel-through-iap --project $projectid
Откройте конфигурационный файл tinyproxy, обновите его с помощью текстового редактора или любым другим удобным для вас способом. Ниже приведен пример с использованием VIM.
sudo vim /etc/tinyproxy/tinyproxy.conf
# Locate the "Listen" configuration line to restrict listening to only its private IP address of the Proxy-VM, rather than all interfaces.
Listen 10.10.10.2
# Locate the "Allow" configuration line to allow requests ONLY from the PSC Network Attachment Subnet
Allow 192.168.10.0/24
Save the configs by the following steps:
1. Press the `ESC` key to enter Command Mode.
2. Type `:wq` to save (w) and quit (q).
3. Press `Enter`
Restart the tinyproxy service to apply the changes:
sudo systemctl restart tinyproxy
Validate the tinyproxy service is running:
sudo systemctl status tinyproxy
Perform an exit returning to cloud shell
exit
10. Создайте экземпляр 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=rfc1918-subnet1 --disable-public-ip --shielded-secure-boot=true --shielded-integrity-monitoring=true --shielded-vtpm=true --service-account-email=notebook-sa@$projectid.iam.gserviceaccount.com
11. Обновление агента службы 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
Внутри Cloud Shell укажите номер своего проекта.
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"
12. Proxy VM Tcpdump
Для проверки IP-соединения от Agent Engine можно использовать TCPDUMP. Это позволит нам наблюдать за обменом данными, исходящим из подсети PSC Network Attachment, 192.168.10.0/28, при отправке запроса get от Agent Engine к общедоступному URL-адресу.
Подключайтесь к виртуальной машине-прокси через SSH из Cloud Shell.
gcloud compute ssh --zone us-central1-a "proxy-vm" --tunnel-through-iap --project $projectid
Выполните команду tcpdump из операционной системы прокси-сервера.
sudo tcpdump -i any net 192.168.10.0/28 -nn
13. Разверните Agent Engine
Примечание: Для выполнения заданий в этом разделе мы будем использовать консоль GCP и блокнот JupyterLab.
В следующем разделе вы создадите блокнот, выполняющий следующие задачи:
- Использует API Frankfurter (https://api.frankfurter.app/) для получения данных об обменном курсе.
- Указывает на явный прокси-сервер (proxy_server), нацеленный на прокси-виртуальную машину в VPC потребителя, используя полное доменное имя proxy-vm.demo.com.
- Определите параметры dnsPeeringConfigs "domain": "demo.com."
Запустите задачу обучения в экземпляре Vertex AI Workbench.
- В консоли Google Cloud перейдите в Vertex AI → Workbench
- Рядом с именем вашего экземпляра Vertex AI Workbench (workbench-tutorial) нажмите «Открыть JupyterLab». Ваш экземпляр Vertex AI Workbench откроется в JupyterLab.
- Выберите Файл > Создать > Блокнот
- Выберите Ядро > Python 3
Установите необходимые библиотеки Python: установите библиотеки, необходимые для Agent Engine, включая pyyaml, google-cloud-aiplatform, cloudpickle, google-cloud-api-keys и langchain-google-vertexai.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
!pip install pyyaml
!pip install google-cloud-aiplatform[agent_engines,langchain]==1.96.0
!pip install cloudpickle==3.1.1
!pip install google-cloud-api-keys
!pip install langchain-google-vertexai==2.0.24
Перезапустите ядро Jupyter Notebook: убедитесь, что недавно установленные библиотеки загружены корректно.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
# Restart the notebook kernel after install, so you can run langchain successfully.
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)
Задайте переменные проекта и корзины: укажите идентификатор проекта Google Cloud, номер проекта, имя сервиса, каталог GCS, конечную точку, имя корзины и местоположение.
Перед запуском ячейки обновите следующие поля.
- PROJECT_ID = "enter-your-projectid"
- НОМЕР_ПРОЕКТА = "введите номер_вашего_проекта"
- BUCKET = "введите уникальное название корзины"
Примечание: На следующем шаге мы будем использовать переменную BUCKET для создания сегмента Cloud Storage.
В блокноте JupyterLab создайте новую ячейку, обновите ее и выполните следующее.
PROJECT_ID = "enter-your-projectid" #@param {type:"string"}
PROJECT_NUMBER = "enter-your-projectnumber" #@param {type:"string"}
SERVICE_NAME = "aiplatform" #@param ["autopush-aiplatform", "staging-aiplatform", "aiplatform"]
# @markdown Specify where your agent code should be written in GCS:
GCS_DIR = "reasoning-engine-test" #@param {type:"string"}
ENDPOINT = "https://us-central1-aiplatform.googleapis.com" # @param ["https://us-central1-aiplatform.googleapis.com", "https://us-central1-autopush-aiplatform.sandbox.googleapis.com", "https://us-central1-staging-aiplatform.sandbox.googleapis.com"]
BUCKET= "enter-a-unique-bucket-name" #@param {type:"string"}
LOCATION="us-central1" #@param {type:"string"}
Создайте корзину GCS: создайте корзину Cloud Storage для хранения кода агента.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
!gcloud storage buckets create gs://{BUCKET}
Задайте имя сетевого подключения: укажите имя вашего сетевого подключения Private Service Connect.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
NETWORK_ATTACHMENT_NAME = 'psc-network-attachment' #@param {type:"string"}
Инициализация клиентских библиотек Python: настройка необходимых клиентских библиотек для сервисов Google Cloud.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
import json
import pprint
import cloudpickle
from google import auth as google_auth
from google.auth.transport import requests as google_requests
from google.cloud import storage
import yaml
def get_identity_token():
"""Gets ID token for calling Cloud Run."""
credentials, _ = google_auth.default()
auth_request = google_requests.Request()
credentials.refresh(auth_request)
return credentials.id_token
if not GCS_DIR or "your_ldap" in GCS_DIR:
raise ValueError("GCS_DIR must be set or you must set your ldap.")
if not PROJECT_ID:
raise ValueError("PROJECT_ID must be set.")
client = storage.Client(project=PROJECT_ID)
bucket = client.get_bucket(BUCKET)
Настройка агента и инструментов: Определите класс StreamingAgent и функцию get_exchange_rate для получения курсов валют с использованием API Frankfurter через явный прокси.
В блокноте JupyterLab создайте новую ячейку и запустите приведенную ниже конфигурацию, обратите внимание на следующие моменты:
- Функция `def get_exchange_rate` будет использовать API Frankfurter (https://api.frankfurter.app/) для получения данных об обменном курсе.
- proxy_server = "http://proxy-vm.demo.com:8888" Полное доменное имя (FQDN) связано с виртуальной машиной-прокси, развернутой в потребительской VPC. Для разрешения FQDN на более позднем этапе мы используем DNS-пиринг.
from langchain_google_vertexai import ChatVertexAI
from langchain.agents import AgentExecutor
from langchain.agents.format_scratchpad.tools import format_to_tool_messages
from langchain.agents.output_parsers.tools import ToolsAgentOutputParser
from langchain.tools.base import StructuredTool
from langchain_core import prompts
from re import S
from typing import Callable, Sequence
import google.auth
import vertexai
class StreamingAgent:
def __init__(
self,
model: str,
tools: Sequence[Callable],
project_id: str,
):
self.model_name = model
self.tools = tools
self.project_id = project_id
def set_up(self):
"""All unpickle-able logic should go here.
The .set_up() method should not be called for an object that is being
prepared for deployment.
"""
creds, _ = google.auth.default(quota_project_id=self.project_id)
vertexai.init(project=self.project_id, location="us-central1", credentials=creds)
prompt = {
"input": lambda x: x["input"],
"agent_scratchpad": (
lambda x: format_to_tool_messages(x["intermediate_steps"])
),
} | prompts.ChatPromptTemplate.from_messages([
("user", "{input}"),
prompts.MessagesPlaceholder(variable_name="agent_scratchpad"),
])
llm = ChatVertexAI(model_name=self.model_name)
if self.tools:
llm = llm.bind_tools(tools=self.tools)
self.agent_executor = AgentExecutor(
agent=prompt | llm | ToolsAgentOutputParser(),
tools=[StructuredTool.from_function(tool) for tool in self.tools],
)
def query(self, input: str):
"""Query the application.
Args:
input: The user prompt.
Returns:
The output of querying the application with the given input.
"""
return self.agent_executor.invoke(input={"input": input})
def stream_query(self, input: str):
"""Query the application and stream the output.
Args:
input: The user prompt.
Yields:
Chunks of the response as they become available.
"""
for chunk in self.agent_executor.stream(input={"input": input}):
yield chunk
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}}
"""
import requests
proxy_server = "http://proxy-vm.demo.com:8888" # This is the VM's FQDN to reach the proxy vm in the consumers network
proxies = {
"http": proxy_server,
"https": proxy_server,
}
response = requests.get(
f"https://api.frankfurter.app/{currency_date}",
params={"from": currency_from, "to": currency_to},
proxies=proxies,
)
return response.json()
Загрузка файлов агента в облачное хранилище: загрузите сериализованный агент и его требования в указанный вами сегмент GCS.
В блокноте JupyterLab создайте новую ячейку и выполните следующее:
# Upload files to Cloud Storage.
if not GCS_DIR:
raise ValueError("GCS_DIR must be set.")
FILE = "streaming_agent.pkl"
blob = bucket.blob(f"{GCS_DIR}/{FILE}")
with blob.open("wb") as f:
cloudpickle.dump(
StreamingAgent(
model="gemini-2.0-flash-001", # Required.
tools=[get_exchange_rate], # Optional.
project_id=PROJECT_ID
), f)
requirements = """
google-cloud-aiplatform[agent_engines,langchain]==1.96.0
cloudpickle==3.1.1
"""
blob = bucket.blob(f"{GCS_DIR}/requirements-streaming.txt")
blob.upload_from_string(requirements)
!gsutil ls gs://{BUCKET}/{GCS_DIR}
Развертывание Agent Engine: Разверните Agent Engine, настроив его с использованием интерфейса PSC и DNS-пиринга для разрешения полного доменного имени (FQDN) виртуальной машины прокси в потребительской VPC.
В блокноте JupyterLab создайте и запустите ячейку, указанную ниже, обратите внимание на следующие моменты:
- Настройка DNS-пиринга с потребительскими VPC осуществляется с помощью dnsPeeringConfigs (dnsPeeringConfigs) для доменного имени demo.com.
import requests
token = !gcloud auth application-default print-access-token
response = requests.post(
f"{ENDPOINT}/v1beta1/projects/{PROJECT_ID}/locations/{LOCATION}/reasoningEngines",
headers={
"Content-Type": "application/json; charset=utf-8",
"Authorization": f"Bearer {token[0]}"
},
data=json.dumps({
"displayName": "PSC-I Explicit Proxy",
"description": "test psc-i agent + proxy vm",
"spec": {
"packageSpec": {
"pickleObjectGcsUri": f"gs://{BUCKET}/{GCS_DIR}/streaming_agent.pkl",
"requirementsGcsUri": f"gs://{BUCKET}/{GCS_DIR}/requirements-streaming.txt",
"pythonVersion": "3.10"
},
"deploymentSpec": {
"pscInterfaceConfig": {
"networkAttachment": NETWORK_ATTACHMENT_NAME,
"dnsPeeringConfigs": [
{
"domain": "demo.com.",
"targetProject": PROJECT_ID,
"targetNetwork": "consumer-vpc", #Consumer VPC
},
],
}
}
},
})
)
pprint.pprint(json.loads(response.content))
reasoning_engine_id = json.loads(response.content)["name"].split("/")[5]
pprint.pprint(reasoning_engine_id)
Мониторинг состояния развертывания: проверьте состояние операции развертывания Agent Engine.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
operation_id = json.loads(response.content)["name"].split("/")[7]
pprint.pprint(operation_id)
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
Примечание: Эта операция может занять около 5 минут. Повторите запуск ячейки, чтобы проверить ход выполнения. Пожалуйста, не переходите к следующему разделу, пока не увидите результат, аналогичный скриншоту ниже.
# You can run this multiple times to check the status of the deployment operation, operation takes approx 5 min.
token = !gcloud auth application-default print-access-token
response = requests.get(
f"{ENDPOINT}/v1beta1/projects/{PROJECT_ID}/locations/{LOCATION}/operations/{operation_id} ",
headers={
"Content-Type": "application/json; charset=utf-8",
"Authorization": f"Bearer {token[0]}"
}
)
pprint.pprint(json.loads(response.content))
Пример успешного запуска:

Запрос к развернутому агенту: Отправьте запрос к развернутому Agent Engine, чтобы проверить его функциональность.
В блокноте JupyterLab создайте новую ячейку и выполните следующее.
response = requests.post(
f"{ENDPOINT}/v1beta1/projects/{PROJECT_ID}/locations/{LOCATION}/reasoningEngines/{reasoning_engine_id}:query",
headers={
"Content-Type": "application/json; charset=utf-8",
"Authorization": f"Bearer {token[0]}"
},
data=json.dumps({ "input": {"input": "What is the exchange rate from US dollars to Euro?"} })
)
print(response.text)
Потоковая передача результатов запроса: Потоковая передача выходных данных из запроса Agent Engine.
В блокноте JupyterLab создайте новую ячейку и выполните следующий код, который инициирует вызов API к общедоступному URL-адресу с использованием явного прокси в VPC потребителя.
token = !gcloud auth application-default print-access-token
print(f"{ENDPOINT}/v1beta1/projects/{PROJECT_ID}/locations/us-central1/reasoningEngines/{reasoning_engine_id}:streamQuery")
response = requests.post(
f"{ENDPOINT}/v1beta1/projects/{PROJECT_ID}/locations/us-central1/reasoningEngines/{reasoning_engine_id}:streamQuery",
headers={
"Content-Type": "application/json; charset=utf-8",
"Authorization": f"Bearer {token[0]}"
},
data=json.dumps({ "input": {"input": "What is the exchange rate from US dollars to Euro?"} })
)
for chunk in response.iter_lines():
print(chunk.decode('utf-8'))
# pprint.pprint(json.loads(response.content))
Пример успешного запуска:

14. Проверка Tcpdump
Просмотрите вывод tcpdump, в котором подробно описана связь между IP-адресом сетевого подключения PSC, используемым Agent Engine, и виртуальной машиной Prox-VM при отправке запроса.
user@proxy-vm:~$ sudo tcpdump -i any net 192.168.10.0/28 -nn tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 22:17:53.983212 ens4 In IP 192.168.10.2.22261 > 10.10.10.2.8888: Flags [S], seq 3841740961, win 28800, options [mss 1440,sackOK,TS val 4245243253 ecr 0,nop,wscale 7], length 0 22:17:53.983252 ens4 Out IP 10.10.10.2.8888 > 192.168.10.2.22261: Flags [S.], seq 2232973833, ack 3841740962, win 64768, options [mss 1420,sackOK,TS val 2251247643 ecr 4245243253,nop,wscale 7], length 0 22:17:53.985167 ens4 In IP 192.168.10.2.22261 > 10.10.10.2.8888: Flags [.], ack 1, win 225, options [nop,nop,TS val 4245243256 ecr 2251247643], length 0 22:17:53.986476 ens4 In IP 192.168.10.2.22261 > 10.10.10.2.8888: Flags [P.], seq 1:45, ack 1, win 16384, options [nop,nop,TS val 4245243256 ecr 2251247643], length 44 22:17:53.986485 ens4 Out IP 10.10.10.2.8888 > 192.168.10.2.22261: Flags [.], ack 45, win 506, options [nop,nop,TS val 2251247646 ecr 4245243256], length 0 22:17:54.043347 ens4 Out IP 10.10.10.2.8888 > 192.168.10.2.22261: Flags [P.], seq 1:71, ack 45, win 506, options [nop,nop,TS val 2251247703 ecr 4245243256], length 70
15. Проверка интерфейса PSC
Также вы можете просмотреть IP-адреса сетевого подключения, используемые Agent Engine, перейдя по следующей ссылке:
Сетевые службы → Подключение к частной сети → Подключение к сети → psc-network-attachment
Выберите проект арендатора (название проекта заканчивается на -tp).

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

16. Проверка достоверности данных облачного логирования
Выйдите из сессии proxy-vm TCPDump и выполните команду PING к Frankfurter api.frankfurter.app, чтобы получить соответствующий публичный IP-адрес.
ping -c4 api.frankfurter.app
В примере указано, что 104.26.1.198 — это публичный IP-адрес для api.frankfurter.app.
user@proxy-vm:~$ ping -c4 api.frankfurter.app
PING api.frankfurter.app (104.26.1.198) 56(84) bytes of data.
64 bytes from 104.26.1.198 (104.26.1.198): icmp_seq=1 ttl=61 time=10.9 ms
64 bytes from 104.26.1.198 (104.26.1.198): icmp_seq=2 ttl=61 time=10.9 ms
64 bytes from 104.26.1.198 (104.26.1.198): icmp_seq=3 ttl=61 time=10.9 ms
64 bytes from 104.26.1.198 (104.26.1.198): icmp_seq=4 ttl=61 time=10.9 ms
Давайте посмотрим на журналы NAT, чтобы увидеть, наблюдается ли трафик для 104.26.1.198.
Перейдите по следующей ссылке:
Мониторинг → Проводник журналов
Используйте следующий фильтр:
resource.type="nat_gateway"

Выберите период времени, затем выполните запрос.

Разверните запись в журнале, которая идентифицирует публичный IP-адрес (104.26.1.198) назначения (api.frankfurter.app) и исходный IP-адрес и имя виртуальной машины прокси, которая проверяет использование явного прокси для исходящего трафика из интернета.

17. Уборка
В блокноте JupyterLab создайте новую ячейку и выполните следующий код, который запустит удаление развертывания Agent Engine.
token = !gcloud auth application-default print-access-token
response = requests.delete(
f"{ENDPOINT}/v1beta1/projects/{PROJECT_ID}/locations/us-central1/reasoningEngines/{reasoning_engine_id}",
headers={
"Content-Type": "application/json; charset=utf-8",
"Authorization": f"Bearer {token[0]}"
},
)
print(response.text)
В Cloud Shell удалите компоненты учебного пособия.
gcloud dns record-sets delete proxy-vm.demo.com --zone=private-dns-codelab --type=A
gcloud dns managed-zones delete private-dns-codelab
gcloud compute instances delete proxy-vm --zone=us-central1-a --quiet
gcloud compute instances delete workbench-tutorial --zone=us-central1-a --quiet
gcloud compute routers delete cloud-router-for-nat --region=us-central1 --quiet
gcloud compute network-attachments delete psc-network-attachment --region=us-central1 --quiet
gcloud compute networks subnets delete intf-subnet rfc1918-subnet1 --region=us-central1 --quiet
gcloud compute networks delete consumer-vpc --quiet
18. Поздравляем!
Поздравляем, вы успешно настроили и проверили Agent Engine, развернутый с использованием интерфейса Private Service Connect Interface, при этом исходящий трафик из интернета осуществляется через явно указанный прокси-сервер.
Вы создали инфраструктуру для потребителей и добавили сетевое подключение, которое позволило производителю создать виртуальную машину с несколькими сетевыми адаптерами для обеспечения связи между потребителями и производителем. Вы научились создавать явный прокси-сервер и DNS-пиринг, обеспечивающие подключение к Интернету.
Cosmopup считает, что обучающие материалы — это здорово!!
