Agent Engine PSC Явный прокси

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

f42f2db921f6d5af.png

Вам потребуется создать единое подключение 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

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

8eec51cb197da218.png

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, используемым в этом руководстве.

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

Внутри 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))

Пример успешного запуска:

3f6dcd1074af7651.png

Запрос к развернутому агенту: Отправьте запрос к развернутому 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))

Пример успешного запуска:

1bd81d12426a348f.png

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

8a4b5a6e5dfd63d7.png

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

c618359f6eafc0c6.png

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"

31024dc29c39084.png

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

5976857e92d149d3.png

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

14e293a7fea68db4.png

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 считает, что обучающие материалы — это здорово!!

c911c127bffdee57.jpeg

Что дальше?

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

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