Private Service Connectを使用して、EC2からBigQueryにVPN経由でアクセスする方法 (Part3: PSC/DNS設定編)

AWS/Google Cloud間をVPNで接続し、EC2からBigQueryへVPN経由でアクセスする方法を試してみました。Private Service Connectを使用して、Google CloudのVPN内にエンドポイントを作成してGoogle Cloud APIへプライベート接続が可能です。また、Google Cloud APIのDNSをAWSでも使えるようにしてみました。この記事では、GCPにPrivate Service ConnectエンドポイントとDNSを設定し、AWSからBigQueryのAPIをコールするための設定内容を記載します。
2021.10.11

データアナリティクス事業本部の笠原です。

AWSとGCPをVPN接続して、EC2からBigQueryへアクセスする方法を試してみました。

以下、3つの記事に分けて掲載いたします。

  1. 環境準備編
  2. VPN構築編
  3. PSC/DNS設定編 (この記事)

この記事では、Private Service ConnectエンドポイントとDNS設定を行い、EC2からVPN経由でBigQueryへのアクセスを行います。

構成内容

前回は以下のようにVPN接続設定まで行いました。

本記事では以下のようにPrivate Service ConnectエンドポイントとDNS設定を行い、EC2からBigQueryへVPN経由でアクセスしたいと思います。

GCP側の設定が大半ですが、AWS側もDNSの名前解決のための設定が必要です。

設定項目

今回設定した内容を記載します。AWS設定は基本CLIコマンドになってます。GCPはマネジメントコンソールでの設定になってますが、 gcloud コマンドも記載してます。

GCP設定

BigQueryへVPN経由でアクセスするための設定を行います。

必要なロールの確認

Private Service Connectエンドポイント作成には、以下のIAMロールが必要になります。

  • Computeネットワーク管理者 ( roles/compute.networkAdmin )
  • Service Directory編集者 ( roles/servicedirectory.editor )
  • DNS管理者 ( roles/dns.admin )

APIは自動で有効にならないため、事前にGoogle APIを有効化する必要があります。 Google Cloud Consoleの [APIとサービス]ページで行いましょう。

すでにVMインスタンスやVPCの作成で「Compute Engine API」は有効になっているはずなので、残りの以下2つを有効化しておきます。

  • プロジェクトで Service Directory API を有効にする
  • プロジェクトで Cloud DNS API を有効にする

gcloud services enable servicedirectory.googleapis.com
gcloud services enable dns.googleapis.com

Private Service Connect (PSC) エンドポイント作成

[ネットワークサービス] ⇒ [Private Service Connect] から、「エンドポイントを接続」で設定します。

  • 対象: 全てのGoogle API
  • エンドポイント名: awsconnpscep
    • 「英小文字/空白なし/20文字以内」で設定する必要があります。
  • ネットワーク: aws-vpn-test-vpc
  • IPアドレス: IPアドレスを作成
    • 名前: psced-address
    • 説明: <空欄でOK>
    • IPアドレス: 10.164.128.1
      • GCPのVPC内のサブネットCIDR以外のIPアドレス範囲からIPアドレスを指定する必要があります。
        • 今回GCPで使用しているサブネットのCIDRは 10.146.0.0/24 です。この範囲と被らないように設定します。
      • もちろんAWSのVPCのCIDRとも被らないようにします。
        • 今回AWSでのVPC CIDRは 10.128.0.0/20 です。
  • Service Directory
    • リージョン: asia-northeast1
    • 名前空間: 自動割り当て済みの名前空間 goog-psc-aws-vpn-test-vpc-XXXXXXXXXX

エンドポイントを追加すると、一覧に表示されます。

以下は gcloud コマンドで実行する際に、以下の順で実行します。

## IPアドレスの割り当て
gcloud compute addresses create psced-address \
    --global \
    --purpose=PRIVATE_SERVICE_CONNECT \
    --addresses=10.164.128.1 \
    --network=aws-vpn-test-vpc
## エンドポイントをGoogle APIおよびサービスに転送するための転送ルールを作成
gcloud compute forwarding-rules create awsconnpscep \
    --global \
    --network=aws-vpn-test-vpc \
    --address=psced-address \
    --target-google-apis-bundle=all-apis \
    --service-directory-registration=projects/<プロジェクト名>/locations/asia-northeast1

以下のリンクを参考にしました。

PSCエンドポイントの動作確認

GCPのVMインスタンスにSSHログインし、以下のコマンド実行します。

## GCPのVMインスタンス上で実行
curl -v 10.164.128.1/generate_204

HTTPレスポンス204が返ってくればOKです。

< HTTP/1.1 204 No Content
< Content-Length: 0

PSCエンドポイント経由でのAPIにアクセスするため、以下のコマンドを実行してみます。 なお、URLは <API名>-<PSCエンドポイント名>.p.googleapis.com となります。

nslookup bigquery-awsconnpscep.p.googleapis.com
Server:         169.254.169.254
Address:        169.254.169.254#53

Non-authoritative answer:
Name:   bigquery-awsconnpscep.p.googleapis.com
Address: 10.164.128.1

Addressが、PSCエンドポイントのIPアドレスになっていればOKです。 ちなみに、 bigquery.googleapis.com だと、インターネット側に公開されているアクセスポイントになります。

## まだ bigquery.googleapis.com はインターネット側へのアクセスとなる。
nslookup bigquery.googleapis.com
Server:         169.254.169.254
Address:        169.254.169.254#53
Non-authoritative answer:
Name:   bigquery.googleapis.com
Address: 172.217.175.74
Name:   bigquery.googleapis.com
Address: 2404:6800:4004:80e::200a
## digでも確認
dig A +noall +answer bigquery.googleapis.com
bigquery.googleapis.com. 300    IN      A       172.217.31.138

ついでに、GCPのVMインスタンスから bq コマンドでPSCエンドポイント経由でBigQueryにアクセスしてみます。 ただし、VMインスタンスに付与しているアクセス権限が足りないはずなので、現状そのままBigQueryにアクセスしてもエラーが返ってきます。

$ bq --api=https://bigquery-awsconnpscep.p.googleapis.com query --use_legacy_sql=false 'SELECT * FROM INFORMATION_SCHEMA.SCHEMATA;'

BigQuery error in query operation: Access Denied: BigQuery BigQuery: Missing required OAuth scope. Need BigQuery or Cloud Platform read scope.

まずはVMインスタンスにBigQueryへのアクセス権限を付与します。 一旦VMインスタンスを停止し、VMインスタンスの編集から「アクセススコープ」を「各APIにアクセス権を設定」にしてから、BigQueryを「有効」にします。

gcloud コマンドでの設定は以下の通りです。

gcloud compute instances stop aws-vpn-test-instance-1 --zone=asia-northeast1-a
gcloud beta compute instances set-scopes aws-vpn-test-instance-1 --scopes=bigquery --zone=asia-northeast1-a
gcloud compute instances start aws-vpn-test-instance-1 --zone=asia-northeast1-a

アクセス権設定したら、以下のように成功するはずです。

bq --api=https://bigquery-awsconnpscep.p.googleapis.com query --use_legacy_sql=false 'SELECT * FROM INFORMATION_SCHEMA.SCHEMATA;'
$ bq --api=https://bigquery-awsconnpscep.p.googleapis.com query --use_legacy_sql=false 'SELECT * FROM INFORMATION_SCHEMA.SCHEMATA;'
Waiting on bqjob_r751acca68385d28_0000017c5f19c1b6_1 ... (0s) Current status: DONE

Cloud Routerのカスタムルートアドバタイズ設定

このままだとAWS側にはPSCエンドポイントのIPアドレスへのルーティングがないため、AWSからPSCエンドポイントへアクセスできません。 そのため、BGPセッションにてPSCエンドポイントのルート情報をAWS側に通知してあげる必要があります。

Cloud Routerで設定する方法とBGPセッションで設定する方法の2通りあるが、今回はCloud Routerで設定しました。

Cloud Routerのページにて更新するCloud Routerを選択し、ルーターの詳細ページで「編集」をクリックします。

  • アドバタイズされたルート: カスタムルートの作成
  • すべてのサブネットのアドバタイズ: 「Cloud Routerに表示されるすべてのサブネットにアドバタイズする」にチェック
  • カスタム範囲
    • カスタムルートを追加
      • ソース: カスタムIP範囲
      • IPアドレス範囲: 10.164.128.1/32
        • PSCエンドポイントのIPアドレスを指定

gcloud compute routers update aws-vpn-test-connect-aws-router \
    --project=<プロジェクト名> \
    --advertisement-mode custom \
    --set-advertisement-groups=all_subnets \
    --set-advertisement-ranges=10.164.128.1/32 \
    --region=asia-northeast1

これによって、AWSのプライベートサブネットに関連付けされているルートテーブルに、PSCエンドポイントアドレスへのルートがアドバタイズされます。

以下のページを参考にしました。

Cloud DNSで限定公開ゾーンを追加

今回は、 googleapis.com をAWSからVPN経由でアクセスさせたいので、GCPのCloud DNSに限定公開ゾーンを追加します。

Cloud DNSページから「ゾーンを作成」をクリックします。

  • ゾーンのタイプ: 非公開
  • ゾーン名: restrictedgoogleapis
  • DNS名: googleapis.com.
  • オプション: デフォルト (限定公開)
  • ネットワーク: aws-vpn-test-vpc

gcloud beta dns --project=<プロジェクト名> \
    managed-zones create restrictedgoogleapis \
    --description="" \
    --dns-name="googleapis.com." \
    --visibility="private" \
    --networks="aws-vpn-test-vpc"

DNSゾーンを作成すると、以下のゾーンの詳細画面になります。

以下のページを参考にしました。

Cloud DNSでレコードセットを追加

ゾーンの詳細画面で「レコードセットを追加」をクリック。CNAMEレコードとAレコードを作成します。

CNAMEレコード

  • DNS名: *.googleapis.com.
  • リソースレコードのタイプ: CNAME
  • TTL: 5分
  • ルーティングポリシー: デフォルトのレコードタイプ
  • 正規名: awsconnpscep.googleapis.com.
    • <PSCエンドポイント名>.googleapis.com. を指定する

gcloud beta dns --project=<プロジェクト名> record-sets transaction start --zone="restrictedgoogleapis"
gcloud beta dns --project=<プロジェクト名> record-sets transaction add awsconnpscep.googleapis.com. --name="*.googleapis.com." --ttl="300" --type="CNAME" --zone="restrictedgoogleapis"
gcloud beta dns --project=<プロジェクト名> record-sets transaction execute --zone="restrictedgoogleapis"

Aレコード

  • DNS名: awsconnpscep.googleapis.com.
    • PSCエンドポイント名を指定する
  • リソースレコードのタイプ: A
  • TTL: 5分
  • ルーティングポリシー: デフォルトのレコードタイプ
  • IPv4アドレス: 10.164.128.1
    • PSCエンドポイントIPアドレスを指定する

gcloud beta dns --project=<プロジェクト名> record-sets transaction start --zone="restrictedgoogleapis"
gcloud beta dns --project=<プロジェクト名> record-sets transaction add 10.164.128.1 --name="awsconnpscep.googleapis.com." --ttl="300" --type="A" --zone="restrictedgoogleapis"
gcloud beta dns --project=<プロジェクト名> record-sets transaction execute --zone="restrictedgoogleapis"

受信サーバポリシー作成

AWSからDNSフォワーディングの問い合わせ先となる、受信サーバーのポリシーを作成します。 Cloud DNSの「DNSサーバーのポリシー」タブを開き、「ポリシーの作成」をクリックします。

  • 名前: aws-vpn-test-api-policy
  • 受信クエリ転送: オン
  • ネットワーク: aws-vpn-test-vpc

gcloud beta dns --project=<プロジェクト名> policies create aws-vpn-test-api-policy \
    --description="" \
    --networks=aws-vpn-test-vpc \
    --enable-inbound-forwarding

作成したら、ポリシー詳細画面の「使用リソース」タブで表示されている「受信クエリ転送IP」をメモしておきます。 このIPはAWS側のRoute53 Resolverの設定で必要になります。

今回は 10.146.0.3 でした。

gcloud コマンドで受信クエリ転送IPを確認する場合は以下の通りです。

gcloud compute addresses list \
    --filter='name ~ ^dns-forwarding.*' \
    --format='csv[no-heading](address, subnetwork)'

以下のページを参考にしました。

Cloud DNS サーバー ポリシーを適用する  |  Google Cloud

確認

GCPのVMインスタンス上で以下のコマンドを実行してみます。

dig A +noall +answer bigquery.googleapis.com
bigquery.googleapis.com. 300    IN      CNAME   awsconnpscep.googleapis.com.
awsconnpscep.googleapis.com. 300 IN     A       10.164.128.1

bigquery.googleapis.com が、PSCエンドポイントのDNSおよびIPを示していればOKです。

以降はAWS側の設定を行えば完了となります。 GCPのVMインスタンスは不要になるため、削除しても問題ありません。

AWS側設定

今回は Route53 Resolver の Outbound Endpoint を使用して、AWS ⇒ GCPの名前解決ができるようにします。

Route53 Resolverの設定については以下の記事に詳細があります。

作業前の確認

EC2にログインして、DNSの内容を確認します。

dig A +noall +answer bigquery.googleapis.com
bigquery.googleapis.com. 18 IN  A   142.250.199.106

これから dig で返されるIPアドレスがPSCエンドポイントのIPアドレスにしていきます。

エンドポイント用セキュリティグループの作成

事前に、Route53 Resolver の Outbound Endpoint 用のセキュリティグループを作成します。

  • セキュリティグループ名: bigquery_vpn_test-resolver-outep-sg
  • VPC: bigquery_vpn_test
  • インバウンドルール
    • DNS (TCP)
      • プロトコル: TCP
      • ポート範囲: 53
      • ソース: 10.146.0.0/24
        • GCPのサブネットCIDR
    • DNS (UDP)
      • プロトコル: UDP
      • ポート範囲: 53
      • ソース: 10.146.0.0/24
        • GCPのサブネットCIDR
  • アウトバウンドルール: 全てのトラフィック許可
## セキュリティグループ作成
aws ec2 create-security-group --group-name bigquery_vpn_test-resolver-outep-sg --description "sg for resolver outbound endpoint" --vpc-id vpc-028bdb0ee3a9213b4
#=> GroupId: sg-06f1fadb3f9ce5ae9
## ルール追加
aws ec2 authorize-security-group-ingress --group-id sg-06f1fadb3f9ce5ae9 --protocol tcp --port 53 --cidr 10.146.0.0/24
## ルール追加
aws ec2 authorize-security-group-ingress --group-id sg-06f1fadb3f9ce5ae9 --protocol udp --port 53 --cidr 10.146.0.0/24

Route53 Resolver エンドポイント作成

Route 53の「リゾルバー」 ⇒ 「アウトバウンドエンドポイント」からOutboundエンドポイントを作成します。

なお、リージョンをあらかじめ東京リージョンに指定しておきましょう。

  • エンドポイント名: bigquery_vpn_test-outbound-endpoint
  • VPC: bigquery_vpn_test
  • セキュリティグループ: bigquery_vpn_test-resolver-outep-sg
    • 先ほど作成したセキュリティグループを指定
  • IPアドレス
    • IPアドレス#1
      • アベイラビリティゾーン: ap-northeast-1d
      • サブネット: bigquery_vpn_test_private_subnet-1
      • IPアドレス: 自動的に選択されたIPアドレスを使用します。
    • IPアドレス#2
      • アベイラビリティゾーン: ap-northeast-1d
      • サブネット: bigquery_vpn_test_private_subnet-1
      • IPアドレス: 自動的に選択されたIPアドレスを使用します。
    • 補足:
      • 2つ指定しなければならない
      • AZを分けて指定すれば良いが、同じAZで指定することも可能
      • IPアドレスは「自動的に選択されたIPアドレスを使用します。」を選択すれば良い
        • ENIのIPアドレスがアタッチされる

CLIで作成する場合は、 --creator-request-id で任意の文字列を指定する必要があります。 今回は日時文字列を指定しました。

## Outbound Endpointの作成
## creator request id は任意の日時文字列にした。例:'20211011091020'
## IPアドレスはプライベートサブネットのCIDRから2つ指定した。
aws route53resolver create-resolver-endpoint \
    --creator-request-id `date +'%Y%m%d%H%M%S'` \
    --name "bigquery_vpn_test-outbound-endpoint" \
    --security-group-ids "sg-06f1fadb3f9ce5ae9" \
    --direction OUTBOUND \
    --ip-addresses SubnetId=subnet-03e945e9c28079b4f,Ip=10.128.1.16 SubnetId=subnet-03e945e9c28079b4f,Ip=10.128.1.176
#=> Id: rslvr-out-1537836dcab040e79

Route53 Resolver ルール作成

Outboundトラフィックのルールを作成します。

  • 名前: bigquery_vpn_test-forwarding-rule
  • ルールタイプ: 転送
  • ドメイン名: googleapis.com.
  • このルールを使用するVPC: bigquery_vpn_test
  • アウトバウンドエンドポイント: bigquery_vpn_test-outbound-endpoint
    • 先ほど作成したRoute53 Resolver Outbound Endpoint を指定
  • ターゲットIPアドレス
    • IPアドレス: 10.146.0.3
      • GCP側の受信サーバポリシーで作成した受信クエリ転送IPを指定
    • ポート: 53
## Route53 Resolver ルールの作成
aws route53resolver create-resolver-rule \
    --creator-request-id `date +'%Y%m%d%H%M%S'` \
    --name "bigquery_vpn_test-forwarding-rule" \
    --rule-type FORWARD \
    --domain-name "googleapis.com." \
    --target-ips Ip=10.146.0.3,Port=53 \
    --resolver-endpoint-id rslvr-out-1537836dcab040e79
#=> Id: rslvr-rr-ae99d14c2f409d646
## Route53 Resolver ルールのVPC関連付け
aws route53resolver associate-resolver-rule \
    --resolver-rule-id rslvr-rr-ae99d14c2f409d646 \
    --vpc-id vpc-028bdb0ee3a9213b4

EC2で確認

EC2にログインして、以下のコマンドを実行します。

dig A +noall +answer bigquery.googleapis.com
bigquery.googleapis.com. 300    IN  CNAME   awsconnpscep.googleapis.com.
awsconnpscep.googleapis.com. 300 IN A   10.164.128.1

PSCエンドポイントIPアドレスが返ってくればOKです。

nslookup でも確認してみます。

nslookup bigquery.googleapis.com
Server:     10.128.0.2
Address:    10.128.0.2#53

Non-authoritative answer:
bigquery.googleapis.com canonical name = awsconnpscep.googleapis.com.
Name:   awsconnpscep.googleapis.com
Address: 10.164.128.1

bigquery.googleapis.com がPSCエンドポイントのIPアドレス宛に名前解決できていることを確認できました。

さらに bq コマンドを使って、BigQueryにアクセスしてみましょう。

bq query --use_legacy_sql=false 'SELECT * FROM INFORMATION_SCHEMA.SCHEMATA;'
Waiting on bqjob_r1bd6b79af8f060f7_0000017c5fb9a5c4_1 ... (0s) Current status: R
Waiting on bqjob_r1bd6b79af8f060f7_0000017c5fb9a5c4_1 ... (0s) Current status: DONE

以上で、AWSからVPN経由でBigQueryにアクセスする方法になります。

まとめ

今回はCLIベースでの構築ができるようにAWS/GCPでCLIコマンドを用意しました。

Webコンソール上での操作やCfn/CDKなどのツールに慣れている方は適宜読み替えていただければと思います。今回の設定では、BigQuery以外でもGoogle StorageにもVPN経由でアクセスできるようになっているので、VPN経由でどうしてもアクセスが必要な場合はご参考になるかと思います。

また、GCPのネットワーク構築は今回初めてなので、とても勉強になりました。

AWSも今回CLIベースで全て操作したので、普段使わないコマンドを調べながら実施したので、AWSの勉強にもなりました。