1. はじめに
Private Service Connect インターフェースは、プロデューサーの Virtual Private Cloud(VPC)ネットワークがコンシューマーの VPC ネットワーク内のさまざまな宛先への接続を開始できるようにするためのリソースです。プロデューサー ネットワークとコンシューマー ネットワークは、異なるプロジェクトや組織に属していてもかまわない。
ネットワーク アタッチメントが Private Service Connect インターフェースからの接続を受け入れると、Google Cloud はネットワーク アタッチメントで指定されたコンシューマー サブネットからインターフェースに IP アドレスを割り振ります。コンシューマ ネットワークとプロデューサー ネットワークが接続され、内部 IP アドレスを使用して通信が可能になります。
ネットワーク アタッチメントと Private Service Connect インターフェース間の接続は、Private Service Connect のエンドポイントとサービス アタッチメント間の接続に似ていますが、重要な違いが 2 つあります。
- ネットワーク アタッチメントは、プロデューサー ネットワークからコンシューマー ネットワークへの接続(マネージド サービスの下り、外向き)を開始できるようにします。エンドポイントは、コンシューマー ネットワークからプロデューサー ネットワークへの接続(マネージド サービスの上り、内向き)を開始できるようにします。
- Private Service Connect インターフェースの接続は推移的です。これは、プロデューサー ネットワークは、コンシューマー ネットワークに接続されている他のネットワークと通信できることを意味します。
Vertex AI PSC インターフェースの到達可能性に関する考慮事項
- PSC インターフェースは、VPC ネットワークで学習した VPC またはオンプレミス ベースの宛先にトラフィックをルーティングできます。
- Agent Engine で使用されるネットワーク アタッチメントから VPC ネットワークへの到達可能性の範囲を制限するには、下り(外向き)ファイアウォール ルールの実装がベスト プラクティスです。
- Agent Engine のネットワーク アタッチメント サブネットから送信されるネットワーク下り(外向き)トラフィックの範囲を制限するには、VPC 下り(外向き)ファイアウォール ルールをデプロイする必要があります。このルールは、Agent Engine から SWP へのトラフィックを明示的に許可し、他のすべての送信トラフィックを拒否します。
Vertex AI PSC-Interface VPC-SC に関する考慮事項
- VPC Service Controls が有効になっている場合でも、Agent Engine PSC インターフェースが機能するには、お客様の VPC 内でインターネット下り(外向き)接続を提供する必要があります。
安全なウェブプロキシ
Secure Web Proxy は、アウトバウンド トラフィック(HTTP/HTTPS)に対するきめ細かい制御とセキュリティを提供するマネージド クラウド ネイティブ サービスです。これは中央ゲートウェイとして機能し、PSC インターフェースでデプロイされた Agent Engine から開始された接続に対して、VM、GKE、インターネット、マルチクラウド環境などの VPC リソースへのセキュリティ ポリシーを適用できます。
解決できること
- データの引き出しを防止する: 不正なアップロードや悪意のあるサイトとの通信をブロックします。
- コンプライアンスを適用する: アウトバウンド トラフィックが組織のセキュリティ ポリシーとデータ処理ポリシーに準拠していることを確認します。
- 運用オーバーヘッドの削減: フルマネージド サービスである Secure Web Proxy を使用すると、独自のプロキシ VM のデプロイ、スケーリング、メンテナンスが不要になります。
- 詳細な可視性を提供: Transport Layer Security(TLS)で暗号化されたトラフィックの検査を有効にして、隠れた脅威を検出します。
詳しくは、次のリソースをご覧ください。
エージェントをデプロイする | Vertex AI の生成 AI | Google Cloud
Vertex AI リソースの Private Service Connect インターフェースを設定する | Google Cloud
作成するアプリの概要
このチュートリアルでは、Private Service Connect(PSC)インターフェースでデプロイされ、SWP と統合された包括的な Agent Engine を構築し、ADK ライブラリを使用して次の操作を行います。
- Agent Engine に DNS ピアリングをデプロイして、プロキシ構成で使用される SWP の完全修飾ドメイン名を解決します。
- RFC1918 アドレスを使用してコンシューマーの VPC にデプロイされたセキュア ウェブ プロキシを介して、パブリック サイト(https://api.frankfurter.app/)への接続を許可します。
- ネットワーク アタッチメント サブネットから SWP へのトラフィックを許可し、それ以外はすべて拒否します。
図 1

学習内容
- ネットワーク アタッチメントを作成する方法
- プロデューサーがネットワーク アタッチメントを使用して PSC インターフェースを作成する方法
- DNS ピアリングを使用してプロデューサーからコンシューマーへの通信を確立する方法
- インターネット下り(外向き)用の SWP をデプロイして使用する方法
- エージェント エンジンのネットワーク到達可能性を減らす外向きファイアウォール ルールを定義する方法
必要なもの
Google Cloud プロジェクト
IAM 権限
- Compute ネットワーク管理者 (roles/compute.networkAdmin)
- Compute インスタンス管理者 (roles/compute.instanceAdmin)
- Compute セキュリティ管理者(roles/compute.securityAdmin)
- DNS 管理者(roles/dns.admin)
- IAP で保護されたトンネル ユーザー(roles/iap.tunnelResourceAccessor)
- Logging 管理者(roles/logging.admin)
- Notebooks 管理者(roles/notebooks.admin)
- Project IAM 管理者(roles/resourcemanager.projectIamAdmin)
- サービス アカウント管理者(roles/iam.serviceAccountAdmin)
- Service Usage 管理者(roles/serviceusage.serviceUsageAdmin)
2. 始める前に
チュートリアルをサポートするようにプロジェクトを更新する
このチュートリアルでは、$variables を使用して、Cloud Shell での gcloud 構成の実装を支援します。
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 に次のリソースが作成されます。
- コンシューマー サブネット
- ネットワーク アタッチメント サブネット
- プロキシ専用サブネット
- ファイアウォール ルール
- Cloud 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 ネットワーク アタッチメント サブネットを作成する
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 内で、Secure Web Proxy やリージョン内部/外部アプリケーション ロードバランサなどの Envoy ベースのプロダクトに必要なプロキシ専用サブネットを作成します。–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 を作成する
Secure Web Proxy の明示モード(または明示プロキシ ルーティング モード)は、クライアント ワークロードが SWP の内部 IP アドレスまたは完全修飾ドメイン名とポートを転送プロキシとして使用するように明示的に構成する必要があるデプロイ方法です。
このポリシーには、セッション一致 host() == 'api.frankfurter.app' とアプリケーション一致 request.method == 'GET' に基づいて、セキュア ウェブプロキシを通過するトラフィックを制御するルールが含まれます。
以下の手順では、YOUR-PROJECT-ID をプロジェクト 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
Secure Web Proxy ルールを作成する
ポリシー内でルールを定義して、許可または拒否するトラフィックを指定します。ルールは優先度に基づいて評価されます。
Cloud Shell 内で、エージェント エンジンで使用されるインターネット エンドポイント api.frankfurter.app へのアクセスを許可する rule.yaml ファイルを作成します。
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
Secure Web Proxy ルールを作成する
明示的ルーティング モードでデプロイされる SWP インスタンスは、ゲートウェイ YAML ファイルで定義されているように、ADK プロキシ構成内で SWP の IP アドレスまたは FQDN を指定するために Agent Engine が必要となるように作成する必要があります。この構成では、インスタンスが対応するポリシー、ネットワーク、サブネットにもリンクされます。
Cloud Shell 内で、SWP のデプロイに使用する gateway.yaml ファイルを作成します。
次の変数(PROJECT_ID、REGION、NETWORK_NAME、PROXY_ONLY_SUBNET_NAME)を環境の詳細で更新したら、必ず YAML ファイルを保存してください。指定されたポート 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 インターフェースのコンシューマー側を表すリージョン リソースです。単一のサブネットをネットワーク アタッチメントに関連付けると、プロデューサーはそのサブネットから Private Service Connect インターフェースに IP を割り当てます。サブネットは、ネットワーク アタッチメントと同じリージョンに存在する必要があります。ネットワーク アタッチメントは、プロデューサー サービスと同じリージョンに存在する必要があります。
ネットワーク アタッチメントを作成する
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
Private Service Connect インターフェースの作成時にプロデューサーが使用する PSC ネットワーク アタッチメント名 psc-network-attachment をメモします。
Cloud Console で PSC ネットワーク アタッチメントの URL を表示するには、次の場所に移動します。
Network Services → Private Service Connect → Network Attachment → psc-network-attachment

6. 限定公開 DNS ゾーン
demo.com の Cloud DNS ゾーンを作成し、SWP の IP アドレスを指す A レコードを設定します。その後、DNS ピアリングが Agent Engine にデプロイされ、コンシューマーの 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"
DNS A レコードに使用される SWP の IP アドレスを取得して保存します。
Cloud Shell 内で、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 インターフェースからのアクセスを許可する Cloud Firewall ルールを作成する
次のセクションでは、PSC ネットワーク アタッチメントからのトラフィックがコンシューマー VPC の SWP サブネットにアクセスできるようにするファイアウォール ルールを作成します。セキュリティを強化するために、SWP IP アドレスを宛先として指定できます。
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 Notebook の作成について説明します。このノートブックは、インターネット下り(外向き)の明示的なプロキシをターゲットとする 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 内で、Artifact Registry 管理者のロールを使用してサービス アカウントを更新します。
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 インスタンスを作成する
次のセクションでは、前に作成したサービス アカウント notebook-sa を組み込んだ Vertex AI Workbench インスタンスを作成します。
Cloud Shell 内で private-client インスタンスを作成します。
gcloud workbench instances create workbench-tutorial --vm-image-project=cloud-notebooks-managed --vm-image-family=workbench-instances --machine-type=n1-standard-4 --location=us-central1-a --subnet-region=us-central1 --subnet=notebook-subnet --disable-public-ip --shielded-secure-boot=true --shielded-integrity-monitoring=true --shielded-vtpm=true --service-account-email=notebook-sa@$projectid.iam.gserviceaccount.com
既存の Secure Web Proxy に別のルールを追加して、このノートブック インスタンスからのトラフィックを転送します。
Cloud Shell で、テキスト エディタを使用して rule-notebook.yaml ファイルを作成します。YAML をプロジェクト ID で更新してください。
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 は、PSC インターフェースの作成に使用される PSC ネットワーク アタッチメント サブネットから IP アドレスを取得するなどのオペレーションをユーザーに代わって実行します。これを行うため、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"
11. Agent Engine をデプロイする
注: このセクションのタスクを完了するには、GCP コンソールと JupyterLab ノートブックを使用します。
次のセクションでは、次のタスクを実行するノートブックを作成します。
- Frankfurter API(https://api.frankfurter.app/)を使用して為替レート データを取得します
- FQDN swp.demo.com を使用して、コンシューマー VPC の SWP をターゲットとする明示的なプロキシ(proxy_server)を参照します。
- dnsPeeringConfigs の "domain": "demo.com." を定義します。
Vertex AI Workbench インスタンスでトレーニング ジョブを実行します。
- Google Cloud コンソールで、
Vertex AI → Workbenchに移動します。 - Vertex AI Workbench インスタンス名(workbench-tutorial)の横にある [JupyterLab を開く] をクリックします。JupyterLab で Vertex AI Workbench インスタンスが開きます。
File > New > Notebookを選択Kernel > Python 3を選択
必要な Python ライブラリをインストールする: pyyaml、google-cloud-aiplatform、cloudpickle、google-cloud-api-keys、langchain-google-vertexai など、Agent Engine に必要なライブラリをインストールします。
JupyterLab ノートブックで、新しいセルを作成し、SWP の IP アドレスを指定して次のコマンドを実行します。

!pip install --proxy http://10.10.10.5:8888 --upgrade google-cloud-aiplatform[agent_engines,adk]
次のコード スニペットで、環境に基づいて次の変数を定義します。
- PROJECT_ID
- BUCKET_NAME
- AGENT_NAME
このラボでは、変数 BUCKET_NAME と AGENT_NAME を使用して、グローバルに利用可能なストレージ バケットを初期化して構成します。
次のセクションでは、名前解決に DNS ピアリングが必要な PROXY_SERVER(swp.demo.com など)を定義します。この構成では、AGENT_PEER_DOMAIN は demo.com としてデプロイされます。これは、AGENT_PEER_NETWORK(consumer-vpc)内の前の手順で作成した限定公開 DNS ゾーンに対応しています。
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 ノートブックで新しいセルを作成し、次のコマンドを実行して、SWP の FQDN とポートに対応するプロキシ変数を作成します。
import os
os.environ["PROXY_SERVER_URL"] = "http://swp.demo.com:8888"
次のコードセルは、os.environ["PROXY_SERVER_URL"]. にマッピングされる PROXY_SERVER_TO_USE を使用して SWP を指定し、インターネット エンドポイント api.frankfurter.app にアクセスするための Agent Engine の明示的なプロキシ構成を示しています。
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(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 ノートブックで、新しいセルを作成し、DNS ピアリングに加えて Agent Engine で使用される psc インターフェース構成を呼び出す次のコマンドを実行します。
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
セルを実行すると、推論エンジン ID が生成されます。次のステップでは、生成された ID(この例では 3235268984265768960)が必要になります。
✅ Created agent engine: projects/9315891080/locations/us-central1/reasoningEngines/3235268984265768960
JupyterLab ノートブックで新しいセルを作成し、次のコードを実行します。必ず、前の出力のプロジェクト番号と Agent Engine 推論 ID で更新してください。
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)
USD から INR への換算レートに基づいて SWP を介してパブリック エンドポイント api.frankfurther.app への接続を検証する実行が成功した例。

12. PSC インターフェースの検証
Agent Engine で使用されているネットワーク アタッチメントの IP を表示するには、次の場所に移動します。
[ネットワーク サービス] → [Private Service Connect] → [ネットワーク アタッチメント] → [psc-network-attachment]
テナント プロジェクト(-tp で終わるプロジェクト名)を選択します。

ハイライト表示されたフィールドは、PSC ネットワーク アタッチメントから Agent Engine で使用される IP アドレスを示します。

13. SWP - Cloud Logging の検証
Cloud Logging を表示して、SWP によって実行されたインターネット下り(外向き)を検証できます。次の場所に移動します。
[モニタリング] → [ログ エクスプローラ]
クエリ resource.type=" networkservices.googleapis.com/Gateway" を挿入し、[クエリを実行] をクリックします。次に、宛先エンドポイント api.frankfurter.app を確認する例を示します。


次の Cloud Logging の例では、次のことを検証します。
Destination_range: Agent Engine PSC インターフェースの IP アドレス
Source_range: プロキシ専用サブネット Dest_ip: Secure Web Proxy の 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. 完了
お疲れさまでした。Private Service Connect インターフェースでデプロイされた Agent Engine を構成し、明示的なプロキシを介してインターネット Egress を実行して検証できました。
コンシューマー インフラストラクチャを作成し、プロデューサーがマルチ NIC VM を作成してコンシューマーとプロデューサーの通信をブリッジできるようにするネットワーク アタッチメントを追加しました。インターネット接続を許可する明示的なプロキシと DNS ピアリングを作成する方法を学習しました。
Cosmopup はチュートリアルが大好きです。
