NTTドコモR&Dの技術ブログです。

Azure × Google Cloud 間を HA VPN+BGP+PSC でつなぐ Vertex AI プライベート接続ガイド

Azure × Google Cloud 間を HA VPN+BGP+PSC でつなぐ Vertex AI プライベート接続ガイド(Advent Calendar 2025)


はじめに

こんにちは、NTTドコモ サービスデザイン部の朴 多感(Dakam Park)と申します。

本記事では、Azure と Google Cloud を HA VPN(トンネル 2 本)+ BGP で安全かつ冗長に接続し、 さらに Private Service Connect(PSC) を用いて Vertex AI などの Google API に、 インターネットを経由せずプライベート IP のまま到達する構成 を構築していきます。

本記事は「必須編」「発展編」の 2 段階に分けており、 インフラに不慣れな方でも、手を動かしながら少しずつ理解を深められる構成にしています。


本記事の前提とゴール

想定読者

  • インフラをこれから学びたい新卒・若手エンジニア
  • 「VPN=リモート接続に使うもの」程度の知識はある人
  • Azure か GCP のどちらか片方だけ触ったことがある人

前提スキル

  • 基本的な Linux コマンドを少し触ったことがある(cd, mkdir, bash など)
  • Azure CLI / gcloud でログインし、プロジェクト(サブスクリプション)を選んだことがある
  • 10.0.0.0/24 のような表記が「IP の範囲」を表していることを知っている

※不安な場合も、まずは 必須編(第 1 章)を写経しながら雰囲気を掴む読み方で進めれば大丈夫です。

環境情報

  • Google Cloud CLI 548.0.0
  • Azure CLI 2.80.0

この構成で目指すゴール

  • Azure の VNet と Google Cloud の VPC を VPN トンネル 2 本(HA 構成) で冗長接続する
  • BGP で両クラウド間のサブネット経路を自動交換できるようにする
  • PSC を使って、Vertex AI などの Google API を 社内 IP(例: 10.1.2.1)から閉域で呼び出せるようにする

読み方の目安

  • 必須編(第 1 章) → ゴール:Azure と GCP の VM 間で Ping が通る

  • 発展編(第 2 章) → ゴール:Vertex AI(Gemini)をインターネット経由ではなく閉域で利用できる


全体イメージ

[ Azure (japaneast) ]                           [ Google Cloud (asia-northeast1) ]
VNet 10.0.0.0/16                                VPC 10.1.0.0/16
  ├─ Subnet 10.0.0.0/24                           ├─ Subnet 10.1.1.0/24
  ├─ VM: azure-test-vm (10.0.x.x)                 ├─ VM: gcp-test-vm (10.1.1.x, no external IP)
  └─ VPN Gateway (Active-Active)                  ├─ HA VPN Gateway (IF0/IF1)
       - PIP1, PIP2                                ├─ Cloud Router (ASN 65534)
       - ASN 65515                                └─ PSC: 10.1.2.1 → Google APIs (Vertex AI)

Azure VPN GW (PIP1,PIP2)
   == IPsec Tunnel #1 ==                           HA VPN IF0
   == IPsec Tunnel #2 ==                           HA VPN IF1

BGP (/30 APIPA):
  #1: 169.254.21.1 (Az) <-> 169.254.21.2 (GCP)
  #2: 169.254.22.1 (Az) <-> 169.254.22.2 (GCP)

到達イメージ:
  10.0.0.0/16 ↔ 10.1.1.0/24(両クラウドの VM 間で Ping が通る)
  10.0.0.0/16 → 10.1.2.1(PSC 経由で Vertex AI に HTTPS)

やさしい用語解説

  • VNet / VPC Azure / GCP における「社内ネットワーク」です。 オフィスの LAN をクラウド上に構成するイメージです。

  • VPN トンネル 2 つのネットワークを接続する「暗号化された専用通路」です。 2 本用意しておくことで、片方が障害となってももう一方で通信を継続できる(これが HA 構成)という特徴があります。

  • BGP ルーター同士が「このネットワークは自分の向こう側にある」と互いに教え合うためのルーティングプロトコルです。 ルーター群を表す番号が ASN(Autonomous System Number) です。

  • APIPA(169.254.x.x) VPN トンネルの内部だけで使うために予約されているアドレス帯です。 BGP では、/30 という「4 個だけ入る小さなネットワーク」を使い、そのうち 2 個をトンネルの両端に割り当てます。

    例:169.254.21.0/30 の場合

  169.254.21.0  … ネットワークアドレス(利用しない)
  169.254.21.1  … Azure 側
  169.254.21.2  … GCP 側
  169.254.21.3  … ブロードキャスト(利用しない)

このように「.1 を Azure」「.2 を GCP」として使うことで、 トンネルの両端で向かい合っている 1 対 1 の“部屋番号” のように扱えます。

  • PSC(Private Service Connect) Vertex AI などの Google API への プライベートな入口 を VPC 内に作る仕組みです。 例:10.1.2.1 に HTTPS アクセスすると、裏側では Vertex AI まで転送されます。

準備編:変数定義

以降のコマンドで使用する値を変数にまとめておくことで、 同じ構成を何度でも再現しやすく なります。

「★」が付いている行は、自身の環境に合わせて必ず変更してください。

コマンド

# --- Azure(★自分の環境に合わせて変更)
RESOURCE_GROUP_NAME="azure-to-google-resgroup"   # ★任意のリソースグループ名
LOCATION="japaneast"                             # ★Azure リージョン

AZURE_VNET_NAME="azure-to-google-network"
AZURE_VNET_ADDRESS_PREFIX="10.0.0.0/16"
AZURE_SUBNET_NAME="default"
AZURE_SUBNET_PREFIX="10.0.0.0/24"
AZURE_GATEWAY_SUBNET_PREFIX="10.0.255.0/27"
AZURE_GATEWAY_NAME="azure-to-google-gateway"
AZURE_ASN=65515                                  # Azure 側 BGP ASN(GCP 側と異なる値にする)
AZURE_BGP_IP_0="169.254.21.1"
AZURE_BGP_IP_1="169.254.22.1"

# --- Google Cloud(★ここも自分のプロジェクトに変更)
PROJECT_ID="dcm-park-host"                       # ★VPC / Vertex AI などをまとめて作成する単一プロジェクト

GCP_REGION="asia-northeast1"
GCP_ZONE="asia-northeast1-c"
GCP_NETWORK="google-to-azure-vpc"
GCP_SUBNET_NAME="subnet-asia-northeast1"
GCP_SUBNET_RANGE="10.1.1.0/24"
GCP_VPN_GATEWAY_NAME="ha-vpn-gw-a"
GCP_ROUTER_NAME="cloud-router"
GCP_EXTERNAL_VPN_GATEWAY_NAME="azure-peer-gw"
GCP_ASN=65534                                    # GCP 側 BGP ASN(Azure 側と異なる値にする)
GOOGLE_BGP_IP_0="169.254.21.2"
GOOGLE_BGP_IP_1="169.254.22.2"

# --- PSC / Vertex AI 用(発展編で使用)
PSC_FORWARDING_NAME="psc-endpoint"
PSC_INTERNAL_IP="10.1.2.1"                       # PSC 用のプライベート IP (/32)
VERTEX_REGION="asia-northeast1"
VERTEX_MODEL_ID="gemini-2.5-pro"

# --- 共通(★本番環境では秘密情報を直接書かない)
SHARED_KEY="***REPLACE_WITH_SECRET***"           # ★VPN の事前共有鍵(PSK)
ADMIN_USERNAME="park"                            # ★Azure VM の管理ユーザー名

ここがポイント

  • 「★」付きの箇所のみ変更すれば、基本的には同じ構成を再現できます。
  • AZURE_ASNGCP_ASN必ず異なる番号 を設定します(同じだと BGP セッションが確立しません)。
  • SHARED_KEY は本番環境では Secret Manager / Key Vault などに保存し、 ここに平文で記載しないようにしてください。

必須編:Azure と GCP を HA VPN+BGP でつなぐ

1-1. Azure のネットワークと VPN ゲートウェイ

Azure VPN ゲートウェイの BGP 設定

Azure 側に以下のリソースを作成し、Azure 側の VPN 入口 を準備します。

  • VNet(社内ネットワーク)
  • 仮想マシン用サブネット
  • VPN ゲートウェイ用サブネット
  • Active-Active な VPN ゲートウェイ(Public IP 2 個つき)

コマンド

# RG / VNet / Subnet / GatewaySubnet
az group create \
    --name "$RESOURCE_GROUP_NAME" \
    --location "$LOCATION"

az network vnet create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "$AZURE_VNET_NAME" \
    --address-prefixes "$AZURE_VNET_ADDRESS_PREFIX" \
    --subnet-name "$AZURE_SUBNET_NAME" \
    --subnet-prefixes "$AZURE_SUBNET_PREFIX"

az network vnet subnet create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --vnet-name "$AZURE_VNET_NAME" \
    --name "GatewaySubnet" \
    --address-prefixes "$AZURE_GATEWAY_SUBNET_PREFIX"

# Active-Active 用の Public IP ×2(Standard)
az network public-ip create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-vpn-pip1" \
    --allocation-method Static \
    --sku Standard

az network public-ip create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-vpn-pip2" \
    --allocation-method Static \
    --sku Standard

# VPN Gateway(RouteBased/BGP/Active-Active)
az network vnet-gateway create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "$AZURE_GATEWAY_NAME" \
    --public-ip-addresses "azure-vpn-pip1" "azure-vpn-pip2" \
    --vnet "$AZURE_VNET_NAME" \
    --gateway-type Vpn \
    --vpn-type RouteBased \
    --sku VpnGw1 \
    --asn "$AZURE_ASN" \
    --no-wait

# (--- virtual network gateway 作成完了まで 20 分くらいかかります。作成完了してから下記を実行 ---)

# BGP(APIPA /30 の片側を Azure に割り当て)
az network vnet-gateway update \
  --resource-group "$RESOURCE_GROUP_NAME" \
  --name "$AZURE_GATEWAY_NAME" \
  --set bgpSettings.bgpPeeringAddresses\[0\].customBgpIpAddresses='["'"$AZURE_BGP_IP_0"'"]' \
        bgpSettings.bgpPeeringAddresses\[1\].customBgpIpAddresses='["'"$AZURE_BGP_IP_1"'"]' \
  --no-wait

# Azure 側の Public IP を取得(後で GCP から参照)
AZURE_GW_PIP_0=$(az network public-ip show \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-vpn-pip1" \
    --query "ipAddress" \
    --output tsv)

AZURE_GW_PIP_1=$(az network public-ip show \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-vpn-pip2" \
    --query "ipAddress" \
    --output tsv)

ここがポイント

  • VPN ゲートウェイ用サブネット名は 必ず GatewaySubnet である必要があります(予約名)。
  • Active-Active 構成では Public IP が 2 個必要 です。
  • Public IP は VPN ゲートウェイの SKU に合わせて Standard を指定します。
  • --vpn-type RouteBased を付与しないと BGP 非対応のゲートウェイになってしまいます。
  • APIPA(169.254.21.1 / 22.1)は後続の GCP 側とペアにして BGP セッションを張るため、 Azure と GCP で整合性が取れていること が重要です。
  • VPN ゲートウェイの作成には 10〜30 分程度かかる場合があります。 後続のコマンドがエラーとなる場合は、ポータルや CLI で状態を確認してください。

1-2. GCP のネットワーク、HA VPN、Cloud Router

GCP Cloud VPN ゲートウェイと Cloud Router 設定

GCP 側に以下を作成し、GCP 側の VPN 入口 を準備します。

  • VPC ネットワーク
  • サブネット
  • HA VPN ゲートウェイ
  • BGP を利用する Cloud Router

コマンド

gcloud config set project "$PROJECT_ID"

# VPC / Subnet
gcloud compute networks create "$GCP_NETWORK" \
    --subnet-mode custom \
    --bgp-routing-mode global

gcloud compute networks subnets create "$GCP_SUBNET_NAME" \
    --network "$GCP_NETWORK" \
    --region "$GCP_REGION" \
    --range "$GCP_SUBNET_RANGE"

# HA VPN Gateway(IF0/IF1)
gcloud compute vpn-gateways create "$GCP_VPN_GATEWAY_NAME" \
    --network "$GCP_NETWORK" \
    --region "$GCP_REGION"

GOOGLE_INTERFACE_0=$(gcloud compute vpn-gateways describe "$GCP_VPN_GATEWAY_NAME" \
    --region "$GCP_REGION" \
    --format="get(vpnInterfaces[0].ipAddress)")

GOOGLE_INTERFACE_1=$(gcloud compute vpn-gateways describe "$GCP_VPN_GATEWAY_NAME" \
    --region "$GCP_REGION" \
    --format="get(vpnInterfaces[1].ipAddress)")

# 対向(Azure)を外部 VPN GW として登録
gcloud compute external-vpn-gateways create "$GCP_EXTERNAL_VPN_GATEWAY_NAME" \
    --interfaces 0="$AZURE_GW_PIP_0",1="$AZURE_GW_PIP_1"

# Cloud Router(ASN 65534)
gcloud compute routers create "$GCP_ROUTER_NAME" \
    --region "$GCP_REGION" \
    --network "$GCP_NETWORK" \
    --asn "$GCP_ASN"

ここがポイント

  • --bgp-routing-mode=global とすることで、将来的に別リージョンへサブネットを追加した場合でも BGP 経路を共有しやすくなります。
  • vpn-gateways describe で取得している IP は、Azure から見た「GCP 側の入口」として後で利用します。
  • external-vpn-gateways は、対向の VPN 装置(ここでは Azure VPN Gateway)を GCP 上に表現するためのリソースです。
  • Cloud Router の ASN(GCP_ASN)は Azure 側 ASN(AZURE_ASN)と 必ず異なる番号 を設定します。

1-3. トンネル 2 本と BGP セッションの作成

GCP VPN トンネルと BGP セッション設定

  • Azure ↔ GCP 間に 暗号化トンネル(IPsec)が 2 本 設定されます。
  • Cloud Router と Azure VPN Gateway 間で BGP セッションによる経路交換 が可能な状態になります。

コマンド

# IPsec トンネル ×2(IKEv2 / PSK)
gcloud compute vpn-tunnels create "azure-tunnel-1" \
    --region "$GCP_REGION" \
    --peer-external-gateway "$GCP_EXTERNAL_VPN_GATEWAY_NAME" \
    --peer-external-gateway-interface 0 \
    --ike-version 2 \
    --shared-secret "$SHARED_KEY" \
    --router "$GCP_ROUTER_NAME" \
    --vpn-gateway "$GCP_VPN_GATEWAY_NAME" \
    --interface 0

gcloud compute vpn-tunnels create "azure-tunnel-2" \
    --region "$GCP_REGION" \
    --peer-external-gateway "$GCP_EXTERNAL_VPN_GATEWAY_NAME" \
    --peer-external-gateway-interface 1 \
    --ike-version 2 \
    --shared-secret "$SHARED_KEY" \
    --router "$GCP_ROUTER_NAME" \
    --vpn-gateway "$GCP_VPN_GATEWAY_NAME" \
    --interface 1

# Cloud Router の /30 IF と BGP ピア
gcloud compute routers add-interface "$GCP_ROUTER_NAME" \
    --interface-name "azure-tunnel-1-int" \
    --vpn-tunnel "azure-tunnel-1" \
    --ip-address "$GOOGLE_BGP_IP_0" \
    --mask-length 30 \
    --region "$GCP_REGION"

gcloud compute routers add-bgp-peer "$GCP_ROUTER_NAME" \
    --peer-name "azure-bgp-peer-1" \
    --peer-asn "$AZURE_ASN" \
    --interface "azure-tunnel-1-int" \
    --peer-ip-address "$AZURE_BGP_IP_0" \
    --region "$GCP_REGION"

gcloud compute routers add-interface "$GCP_ROUTER_NAME" \
    --interface-name "azure-tunnel-2-int" \
    --vpn-tunnel "azure-tunnel-2" \
    --ip-address "$GOOGLE_BGP_IP_1" \
    --mask-length 30 \
    --region "$GCP_REGION"

gcloud compute routers add-bgp-peer "$GCP_ROUTER_NAME" \
    --peer-name "azure-bgp-peer-2" \
    --peer-asn "$AZURE_ASN" \
    --interface "azure-tunnel-2-int" \
    --peer-ip-address "$AZURE_BGP_IP_1" \
    --region "$GCP_REGION"

ここがポイント

  • --peer-external-gateway-interface で 「Azure 側の Public IP と GCP 側 IF の組み合わせ」をインデックスで指定しています。
  • BGP 用 IP として 169.254.21.2 / 22.2 を Cloud Router 側に、 169.254.21.1 / 22.1 を Azure 側に割り当てた /30 ペアを利用しています。
  • add-bgp-peer--peer-ip-address には 対向側(Azure 側)の APIPA を指定します。
  • 2 本のトンネルを同様に設定することで、片方に障害が発生しても BGP 経路が維持される 冗長構成 になります。

1-4. Azure 側での「対向」登録と VPN 接続

GCP VPN トンネル/ゲートウェイと BGP IP 設定

GCP Cloud Router の ASN と BGP IP 設定

Azure ローカルネットワークゲートウェイの BGP 設定

Azure から見た GCP 側の VPN 装置 を Local Network Gateway として登録し、 2 本の VPN 接続(IPsec)を確立します。

コマンド

# Local Network Gateway ×2(対向=GCP IF0/IF1)
az network local-gateway create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-to-google-lng1" \
    --gateway-ip-address "$GOOGLE_INTERFACE_0" \
    --bgp-peering-address "$GOOGLE_BGP_IP_0" \
    --asn "$GCP_ASN"

az network local-gateway create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-to-google-lng2" \
    --gateway-ip-address "$GOOGLE_INTERFACE_1" \
    --bgp-peering-address "$GOOGLE_BGP_IP_1" \
    --asn "$GCP_ASN"

# 接続(BGP 有効 / PSK)
az network vpn-connection create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-to-gcp-connection1" \
    --vnet-gateway1 "$AZURE_GATEWAY_NAME" \
    --local-gateway2 "azure-to-google-lng1" \
    --shared-key "$SHARED_KEY" \
    --enable-bgp

az network vpn-connection create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-to-gcp-connection2" \
    --vnet-gateway1 "$AZURE_GATEWAY_NAME" \
    --local-gateway2 "azure-to-google-lng2" \
    --shared-key "$SHARED_KEY" \
    --enable-bgp

ここがポイント

  • Local Network Gateway は「Azure から見た GCP 側の VPN 入口」を表すリソースです。 --gateway-ip-address に HA VPN のインターフェース IP(GOOGLE_INTERFACE_0/1)を指定します。
  • --bgp-peering-address には GCP 側の APIPA(169.254.21.2 / 22.2)を指定します。
  • vpn-connection create--enable-bgp を付与することで、 PSK で保護されたトンネル上に BGP セッションが乗る構成となります。
  • APIPA を用いた BGP では、Cloud Router 側からセッションを張りに行く動作になります。 GCP 側の設定に不備があると BGP は確立しないため、GCP 側の設定を優先して確認すると切り分けしやすくなります。

1-5. ファイアウォールと VM による疎通確認

1-5-1. GCP ファイアウォール

GCP VPC ファイアウォールルール設定

Azure(10.0.0.0/16)から GCP VPC への 基本的な通信(TCP/UDP/ICMP) を許可し、 VPN 上のトラフィックがファイアウォールで遮断されないようにします。

コマンド

gcloud compute firewall-rules create "allow-azure-to-gcp" \
    --network "$GCP_NETWORK" \
    --allow tcp,udp,icmp \
    --source-ranges "$AZURE_VNET_ADDRESS_PREFIX"

ここがポイント

  • GCP のファイアウォールでは、--source-ranges で「どこから来た通信を許可するか」を指定します。
  • 本記事では検証目的のため広めに許可していますが、本番環境ではポート(例: 22/TCP)や IP 範囲を絞ることを推奨します。

1-5-2. テスト用 VM の作成

Azure/GCP VM 一覧とファイアウォール設定

両クラウドにテスト用 VM を用意し、VPN 越しに Ping などで疎通確認できる状態とします。

コマンド

# Azure
az vm create \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-test-vm" \
    --location "$LOCATION" \
    --image "Ubuntu2204" \
    --size "Standard_B1s" \
    --vnet-name "$AZURE_VNET_NAME" \
    --subnet "$AZURE_SUBNET_NAME" \
    --admin-username "$ADMIN_USERNAME" \
    --generate-ssh-keys

# GCP(外部 IP なし)
gcloud compute instances create "gcp-test-vm" \
    --zone "$GCP_ZONE" \
    --machine-type "e2-micro" \
    --subnet "$GCP_SUBNET_NAME" \
    --no-address \
    --image-family "debian-11" \
    --image-project "debian-cloud" \
    --tags "allow-ssh"

IAP 経由での SSH を行う場合は、以下のようなファイアウォールルールを作成しておくと分かりやすいです。

gcloud compute firewall-rules create allow-ssh-from-iap \
    --network "$GCP_NETWORK" \
    --allow tcp:22 \
    --source-ranges 35.235.240.0/20 \
    --target-tags allow-ssh

ここがポイント

  • Azure 側は検証用途のため、安価な Standard_B1s を利用しています。
  • GCP 側は --no-address により 外部 IP を持たない VM として作成しています。この VM には IAP(Identity-Aware Proxy)経由で SSH することを前提としています。
  • --tags "allow-ssh" は、SSH 用ファイアウォールルールの対象をこの VM にだけ絞り込むためのネットワークタグです。
  • ファイアウォールルールの --source-ranges 35.235.240.0/20 は、Cloud IAP が GCE への TCP 転送時に 送信元 IP として使用する固定レンジ です。このレンジからの 22/TCP を許可することで、外部 IP を持たない gcp-test-vm に対してもブラウザや gcloud compute ssh から IAP 経由で SSH 接続できるようになります。

1-5-3. Ping による VPN の動作確認

Azure VM から GCP VM への ping 実行結果

GCP VM から Azure VM への ping 結果

Azure → GCP、GCP → Azure の 両方向の Ping を確認し、 VPN と BGP が正しく動作しているかを検証します。

コマンド

AZURE_VM_IP=$(az vm list-ip-addresses \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-test-vm" \
    --query "[].virtualMachine.network.privateIpAddresses[0]" \
    --output tsv)
GCP_VM_IP=$(gcloud compute instances describe "gcp-test-vm" \
    --zone "$GCP_ZONE" \
    --format="get(networkInterfaces[0].networkIP)")

# Azure → GCP
az vm run-command invoke \
    --resource-group "$RESOURCE_GROUP_NAME" \
    --name "azure-test-vm" \
    --command-id RunShellScript \
    --scripts "ping -c 4 $GCP_VM_IP"

# GCP → Azure(IAP 経由する場合は 35.235.240.0/20 の許可が必要)
gcloud compute ssh "gcp-test-vm" \
    --zone "$GCP_ZONE" \
    --command "ping -c 4 $AZURE_VM_IP"

ここがポイント

  • az vm run-command invoke を利用すると、ローカルから SSH せずに Azure VM 内でコマンドを実行できます。
  • gcloud compute ssh は、外部 IP を持たない VM にも IAP 経由で SSH できます。 別途、35.235.240.0/20 からの SSH を許可するファイアウォールルールが必要です。
  • 片方向だけ Ping が通らない場合は、ファイアウォール設定と BGP 経路(特に戻り経路) を重点的に確認すると原因の切り分けがしやすくなります。

ここまで(1-5 節)で「必須編」は完了となります。 Azure と GCP の VM 間で Ping が通っていれば、クラウド間 VPN+BGP の一連の流れは概ね把握できている状態です。


発展編:PSC で Vertex AI を閉域化する

2-1. PSC(Private Service Connect)で Vertex AI を閉域化

2-1-1. PSC エンドポイントの作成

PSC エンドポイントとロードバランサの IP 設定

GCP VPC 内に Google API 用のプライベート IP(例: 10.1.2.1) を用意し、 その IP 宛ての HTTPS 通信が Vertex AI などの Google API に転送されるようにします。

コマンド

gcloud config set project "$PROJECT_ID"
gcloud services enable dns.googleapis.com

# PSC 用の内部 IP を予約
gcloud compute addresses create "${PSC_FORWARDING_NAME}-ip" \
    --addresses "$PSC_INTERNAL_IP" \
    --purpose "PRIVATE_SERVICE_CONNECT" \
    --global \
    --network "$GCP_NETWORK"

# Google APIs バンドルへ転送(VPC SC を利用しない場合は all-apis も選択可能)
gcloud compute forwarding-rules create vertexai \
  --global \
  --network "$GCP_NETWORK" \
  --address "${PSC_FORWARDING_NAME}-ip" \
  --target-google-apis-bundle "vpc-sc"

ここがポイント

  • --purpose PRIVATE_SERVICE_CONNECT を指定することで、この IP が PSC 専用であることを示しています。
  • --target-google-apis-bundle "vpc-sc" は、VPC Service Controls との連携を前提とした API 群に対して PSC を張る指定です。VPC SC を利用せず「すべての API を閉域化したい」場合には all-apis を選択することも可能です。
  • この時点では 「GCP 内の 10.1.2.1 に来た通信を Google API に転送する入口」 ができただけです。 Azure からアクセスできるようにするには、この後にファイアウォールと BGP のアドバタイズ設定が必要です。
  • GCE から PSC 経由で Google API を呼ぶ場合は、対象サブネットに Private Google Access を有効化しておく必要があります(Azure 側からのアクセスには不要)。
gcloud compute networks subnets update "$GCP_SUBNET_NAME" \
    --region "$GCP_REGION" \
    --enable-private-ip-google-access

(CLI の仕様は今後変更される可能性があるため、詳細は gcloud help compute forwarding-rules create などで最新情報を確認してください。)


2-1-2. PSC 向けファイアウォールと /32 アドバタイズ

PSC 用ファイアウォールと Cloud Router のアドバタイズ

Azure から 10.1.2.1:443 への HTTPS 通信が通るようにし、 その応答が Azure 側に戻る経路も確保します。

コマンド

# Azure → PSC(10.1.2.1):443 を許可
gcloud compute firewall-rules create "allow-azure-to-psc" \
    --network "$GCP_NETWORK" \
    --allow tcp:443 \
    --source-ranges "$AZURE_VNET_ADDRESS_PREFIX" \
    --destination-ranges "$PSC_INTERNAL_IP/32" \
    --priority=1000 \
    --direction=INGRESS \
    --description="Allow Azure subnet to access PSC endpoint on port 443"

# Cloud Router で 10.1.2.1/32 をアドバタイズ(戻り経路の担保)
gcloud compute routers update "$GCP_ROUTER_NAME" \
  --project "$PROJECT_ID" \
  --region "$GCP_REGION" \
  --advertisement-mode "custom" \
  --set-advertisement-groups "all_subnets"

gcloud compute routers update "$GCP_ROUTER_NAME" \
  --project "$PROJECT_ID" \
  --region "$GCP_REGION" \
  --add-advertisement-ranges "$PSC_INTERNAL_IP/32"

ここがポイント

  • ファイアウォールで --destination-ranges "$PSC_INTERNAL_IP/32" を指定し、 PSC の IP のみをピンポイントで許可しています。
  • Cloud Router の --add-advertisement-ranges/32 プレフィックスをアドバタイズすることで、 「10.1.2.1 宛てのトラフィックは GCP 側へ向かう」という経路を Azure に伝えます。 これがない場合、Vertex AI からの応答が Azure に戻れず通信が失敗します。

2-1-3. DNS を PSC に向ける(2 つのやり方)

Vertex AI API の有効化画面

Vertex AI を呼び出す際に利用する

<リージョン>-aiplatform.googleapis.com (例:asia-northeast1-aiplatform.googleapis.com

が、PSC の IP アドレス 10.1.2.1 を返すようにします。

ここでは、次の 2 パターンを紹介します。

  1. お試し用:単一 VM の /etc/hosts を書き換える方法
  2. 本番寄り:Azure Private DNS Zone で VNet 全体を PSC に向ける方法

2-1-3-1. お試し用:/etc/hosts で強制的に PSC へ向ける

Azure VM での /etc/hosts 設定

  • 特定の VM(例:Azure の azure-test-vm)だけ、 asia-northeast1-aiplatform.googleapis.com10.1.2.1 に向けます。
  • まずは「PSC & VPN 経由で Vertex AI に届くか」を素早く確認したいとき向けです。

コマンド(Vertex AI を叩く VM の中で実行)

echo "10.1.2.1 ${VERTEX_REGION}-aiplatform.googleapis.com" | sudo tee -a /etc/hosts

ここがポイント

  • 対象の VM のみ書き換わるため、「とりあえず動かす検証」には十分です。
  • 他の VM やオンプレからの名前解決には影響しません。
  • 本番では「誰かが /etc/hosts を書き換え忘れていた」といったヒューマンエラーになりがちなので、 後述の Private DNS Zone による統一を推奨します。

2-1-3-2. 本番寄り:Azure Private DNS Zone で VNet 全体を PSC に向ける

Azure Private DNS ゾーンの A レコードと VNet リンク

  • Azure の VNet 内から asia-northeast1-aiplatform.googleapis.com を引いたときに、 常に 10.1.2.1(PSC)を返すようにします。
  • これにより、VNet 内のどの VM からでも同じ挙動になります。

前提

    1. 準備編で定義した次の変数を利用します。
RESOURCE_GROUP_NAME="azure-to-google-resgroup"
AZURE_VNET_NAME="azure-to-google-network"
VERTEX_REGION="asia-northeast1"
PSC_INTERNAL_IP="10.1.2.1"

コマンド(ローカル端末や Azure Cloud Shell などから実行)

# Private DNS Zone 名をリージョン付きで定義
DNS_ZONE_NAME="${VERTEX_REGION}-aiplatform.googleapis.com"

# 1) Private DNS Zone を作成
az network private-dns zone create \
  --resource-group "$RESOURCE_GROUP_NAME" \
  --name "$DNS_ZONE_NAME"

# 2) ルート(@)レコードとして PSC の IP を登録
az network private-dns record-set a add-record \
  --resource-group "$RESOURCE_GROUP_NAME" \
  --zone-name "$DNS_ZONE_NAME" \
  --record-set-name "@" \
  --ipv4-address "$PSC_INTERNAL_IP"

# 3) VNet と DNS ゾーンをリンク
az network private-dns link vnet create \
  --resource-group "$RESOURCE_GROUP_NAME" \
  --zone-name "$DNS_ZONE_NAME" \
  --name "link-${AZURE_VNET_NAME}" \
  --virtual-network "$AZURE_VNET_NAME" \
  --registration-enabled false

ここがポイント

  • DNS ゾーン名を asia-northeast1-aiplatform.googleapis.com にしているので、 そのゾーンの「@ レコード」がちょうど asia-northeast1-aiplatform.googleapis.com → 10.1.2.1 という意味になります。
  • --registration-enabled false は、 「このゾーンは VM 名の自動登録には使わず、あくまで名前解決専用」とする指定です。
  • 設定後、VNet 内の VM から
  nslookup asia-northeast1-aiplatform.googleapis.com

を実行し、10.1.2.1 が返ってくることを確認してください。


どちらを使うべき?

  • まずは動作確認だけしたい → 2-1-3-1 の /etc/hosts 方式で十分です。
  • チームで共有する検証環境/本番環境にしたい → 2-1-3-2 の Private DNS Zone 方式で、VNet 内の誰がどこから叩いても同じパスになります。

2-2. Vertex AI(Gemini)を PSC 経由で呼び出す

Azure 側(VPN で GCP に接続されたネットワーク)から https://asia-northeast1-aiplatform.googleapis.com へアクセスした際、 実際には 10.1.2.1(PSC)に到達し、そこから Vertex AI まで 閉域で 転送される構成を確認します。

※ 以下のサンプルは、Azure 側のテスト用 VM(azure-test-vm の Linux)から実行する想定です。


2-2-1. gcloud SDK のインストールと認証(ADC)

まずは gcloud コマンドを使えるようにし、Vertex AI 呼び出しで利用する ADC を取得します。 Cloud Shell など、すでに gcloud が入っている環境では SDK インストール部分はスキップ可能です。

コマンド

# SDK インストール(Cloud Shell なら不要)
curl https://sdk.cloud.google.com | bash
exec -l "$SHELL"

# 認証 (ADC 用)
gcloud auth application-default login

ここがポイント

  • curl https://sdk.cloud.google.com | bash で gcloud SDK 本体をインストールします。
  • exec -l "$SHELL" はインストール直後にパスを反映させるための再ログイン相当の処理です。
  • gcloud auth application-default loginアプリケーション デフォルト認証(ADC) を設定し、 後続の gcloud auth application-default print-access-token からアクセストークンを取得できるようにします。

2-2-2. Vertex AI(Gemini)呼び出し(プロジェクト設定〜API 有効化〜リクエスト送信)

Azure VM から Vertex AI API への curl 実行

続いて、プロジェクトやリージョン・モデル ID の設定、Vertex AI API の有効化、 アクセストークン取得、Gemini 呼び出しまでを 1 つの流れで 実行します。

コマンド

# プロジェクト/リージョン/モデル
PROJECT_ID="dcm-park-host"          # ★自分のプロジェクト ID に変更
VERTEX_REGION="asia-northeast1"
VERTEX_MODEL_ID="gemini-2.5-pro"

# gcloud のデフォルトプロジェクト設定(必要なら)
gcloud config set project "$PROJECT_ID"

# Vertex AI API を有効化(初回のみ)
gcloud services enable aiplatform.googleapis.com

# アクセストークン取得 (ADC)
ACCESS_TOKEN=$(gcloud auth application-default print-access-token)

# モデル呼び出し(PSC 経由の閉域アクセス)
curl -s -X POST \
  -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \
  "https://${VERTEX_REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${VERTEX_REGION}/publishers/google/models/${VERTEX_MODEL_ID}:generateContent" \
  -d '{"contents":{"role":"user","parts":[{"text":"What is the capital of Japan?"}]}}'

ここがポイント

  • gcloud config set project で、以降の gcloud / Vertex AI 呼び出しのデフォルトプロジェクトを明示します。
  • gcloud services enable aiplatform.googleapis.comプロジェクト単位で一度だけ必要な API 有効化 です。
  • gcloud auth application-default print-access-token で、2-2-1 で設定した ADC をもとにアクセストークンを発行しています。
  • curl の宛先ホスト名はあくまで https://${VERTEX_REGION}-aiplatform.googleapis.com のままですが、 2-1-3 で設定した DNS により PSC の IP(例: 10.1.2.1)に名前解決される ことで、 インターネットではなく VPN+GCP VPC+PSC を通る閉域経路 で Vertex AI(Gemini)に到達します。

おまけ:経路の簡易確認コマンド(任意)

PSC 経由アクセスの nc・nslookup・tcpdump 結果

PSC・VPN・DNS の動作確認をしたい場合は、次のコマンドを併用すると把握しやすくなります。

# PSC IP に 443/TCP で到達できるか
nc -zv 10.1.2.1 443

# DNS が PSC を向いているか
nslookup asia-northeast1-aiplatform.googleapis.com
dig asia-northeast1-aiplatform.googleapis.com

# 必要に応じて、DNS / 通信をまとめて確認
sudo tcpdump -i any -n '(port 53 or host asia-northeast1-aiplatform.googleapis.com)'

これらを併用すると、

  • 「名前解決が 10.1.2.1(PSC)を返しているか」
  • 「実際に 10.1.2.1:443 へ接続に行っているか」

を手早く確認できます。


Cleanup(後片付け)

検証が終わったら、そのまま放置しておくと VPN ゲートウェイや VM などの料金が継続して発生 してしまいます。
以下のスクリプトで、本記事で作成したリソースをまとめて削除できます。

⚠️ 注意

  • Azure 側は リソースグループごと削除 しています。この RG を他用途でも使っている場合は実行しないでください。

  • 各コマンドは、すでにリソースを手動削除済みの場合にはエラーになりますが、その場合は無視して構いません。

  • PROJECT_ID などを本番環境と共用している場合、API の無効化や VPC 削除には十分注意してください。

########################################
# 0. 変数定義(必要に応じて書き換え)
#    ★が付いている行は、自身の環境に合わせて必ず変更してください。
########################################

# --- Azure
RESOURCE_GROUP_NAME="azure-to-google-resgroup"   # ★任意のリソースグループ名
AZURE_VNET_NAME="azure-to-google-network"

# --- Google Cloud
PROJECT_ID="dcm-park-host"          # ★自分のプロジェクト ID に変更
GCP_REGION="asia-northeast1"
GCP_ZONE="asia-northeast1-c"
GCP_NETWORK="google-to-azure-vpc"
GCP_SUBNET_NAME="subnet-asia-northeast1"
GCP_VPN_GATEWAY_NAME="ha-vpn-gw-a"
GCP_ROUTER_NAME="cloud-router"
GCP_EXTERNAL_VPN_GATEWAY_NAME="azure-peer-gw"

# --- PSC / Vertex AI
PSC_FORWARDING_NAME="psc-endpoint"
PSC_INTERNAL_IP="10.1.2.1"
VERTEX_REGION="asia-northeast1"

# --- Azure Private DNS (2-1-3-2 を実施した場合のみ使用)
DNS_ZONE_NAME="${VERTEX_REGION}-aiplatform.googleapis.com"

########################################
# 1. Azure cleanup
########################################

# (1) リソースグループごと削除(この RG が検証専用の場合)
az group delete \
  --name "$RESOURCE_GROUP_NAME" --yes --no-wait

# ★注意: NetworkWatcherRG は他のリソースでも共有されている場合があるため、
# 自分の環境で削除して良いか確認してから実行してください。
# az group delete --name "NetworkWatcherRG" --yes --no-wait


########################################
# 2. GCP cleanup
########################################

# プロジェクト選択
gcloud config set project "$PROJECT_ID"

# 2-1. テスト用 VM 削除
gcloud compute instances delete "gcp-test-vm" \
  --zone="$GCP_ZONE"

# 2-2. ファイアウォールルール削除
gcloud compute firewall-rules delete \
  allow-azure-to-gcp \
  allow-ssh-from-iap \
  allow-azure-to-psc

# 2-3. PSC 関連削除
gcloud compute forwarding-rules delete "vertexai" \
  --global

gcloud compute addresses delete "${PSC_FORWARDING_NAME}-ip" \
  --global

# 2-4. Cloud VPN / Cloud Router 関連削除

# VPN トンネル 2 本
gcloud compute vpn-tunnels delete \
  "azure-tunnel-1" "azure-tunnel-2" \
  --region="$GCP_REGION"

# Cloud Router の BGP ピア削除
gcloud compute routers remove-bgp-peer "$GCP_ROUTER_NAME" \
  --region="$GCP_REGION" \
  --peer-name="azure-bgp-peer-1"

gcloud compute routers remove-bgp-peer "$GCP_ROUTER_NAME" \
  --region="$GCP_REGION" \
  --peer-name="azure-bgp-peer-2"

# Cloud Router のインターフェース削除
gcloud compute routers remove-interface "$GCP_ROUTER_NAME" \
  --region="$GCP_REGION" \
  --interface-name="azure-tunnel-1-int"

gcloud compute routers remove-interface "$GCP_ROUTER_NAME" \
  --region="$GCP_REGION" \
  --interface-name="azure-tunnel-2-int"

# Cloud Router 本体削除
gcloud compute routers delete "$GCP_ROUTER_NAME" \
  --region="$GCP_REGION"

# External VPN Gateway / HA VPN Gateway 削除
gcloud compute external-vpn-gateways delete "$GCP_EXTERNAL_VPN_GATEWAY_NAME"

gcloud compute vpn-gateways delete "$GCP_VPN_GATEWAY_NAME" \
  --region="$GCP_REGION"

# 2-5. VPC サブネットと VPC ネットワーク削除
gcloud compute networks subnets delete "$GCP_SUBNET_NAME" \
  --region="$GCP_REGION"

gcloud compute networks delete "$GCP_NETWORK"


########################################
# 3. (任意)有効化した API を無効化
########################################

# dns.googleapis.com を無効化
gcloud services disable dns.googleapis.com

# Vertex AI API を無効化
gcloud services disable aiplatform.googleapis.com

関連する公式ドキュメント

Google Cloud

Azure


おわりに

本記事では、Azure と Google Cloud を HA VPN+BGP で接続し、 その上に PSC を組み合わせる構成を整理してご紹介しました。

ここまでの手順を通じて、クラウド間 VPN+BGP による疎通から、 PSC 経由で Vertex AI を閉域利用するところまでを、一通り手を動かしながら構築できます。

インフラに慣れていない方であっても、 「このステップが終わると何ができるのか」「どの点に注意すべきか」を意識しながら進めていただくことで、 構成全体のイメージとコマンドの意味が自然と結びついていくのではないかと思います。

本記事が、新卒やインフラ初心者の方が クラウド間ネットワーク設計に一歩踏み出すきっかけ となれば幸いです。

※ 記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。