IBM Cloud: Private Path Service(Beta)を試してみた


# 1. はじめに
[Private Path Service](https://cloud.ibm.com/docs/vpc?topic=vpc-private-path-service-intro&interface=ui&locale=en)のベータプログラムに参加して、その機能を確認してみたので、本稿で紹介する。なお、あくまで本サービスは現段階ではベータなので、GA時点では仕様が変更される可能性があるので注意してもらいたい。

# 2. Transit Gatewayではなぜダメなのか？

Transit Gatewayでは、**VPC上の全てのネットワーク情報**が、Transit Gatewayに接続している対象すべてにBGP advertiseされてしまう。これは、サービスを提供する上で外部に公開したくない内部ネットワーク情報もBGP advertiseされてしまうということである。

もちろん、ある程度はplefix filteringで互いの経路広告をフィルタリングすることもできるのだが、例えば以下のようにサービス提供側VPC(Provider VPC)と利用者側VPC(Consumer VPC)を1:1でTransit Gatewayで構成したとしても、

- サービス利用者とサービス提供者のaddress prefixが重複していないか？（特にサービス利用者がアクセスしようとしているサービス提供者のネットワークが、サービス利用者のネットワークと重複していないか？）
- サービス利用者間（この図においてはVPC-AとVPC-B）のaddress prefixが重複していないか？　（被ってしまうと、longest matchingでよりaddress prefix長が短い方としか通信できない）

など、互いのVPCのネットワーク設計を考慮しなければいけないため、一般的にTransit Gatewayはサービスを公開する用途には向いていない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/53bdaf37-96c5-8d39-1d23-9fd522ddd512.png)


# 3. Private Path Serviceとは

Private Path Serviceでは、サービス提供側VPC(Provider VPC)で提供されている特定のサービスのみを、利用者側VPC(Consumer VPC)に公開することができるという利点がある。

- Private Path Serviceでは、Transit Gatewayのように全てのネットワークが互いのVPCに公開されることはない。逆にいうと、Private Path Serviceを利用する上でのネットワーク設計において、サービス利用者(Consumer VPC)およびサービス提供者(Provider VPC)は、互いのネットワーク情報の詳細を知る必要はない。
- Private Path Serviceでは、サービス利用者(Consumer VPC)からサービス提供者(Provider VPC)への一方通行のアクセスのみが許可されている。
    - 利用者側VPC(Consumer VPC)のVPEにアクセスすると、IBM Cloud backbone内でインターネットに出て行くことなく、サービス提供側VPC(Provider VPC)のPrivate Path NLB(PPNLB)に通信が転送され、その後PPNLBのバックエンドメンバーにロードバランシングされる。
    - PPNLBはリージョナルサービスであり、AZに跨ってactive-active topologyで稼働する。仮にどこか１つのAZが停止してもサービスを継続提供可能。
    - Backend memberから見ると、往路のトラフィックのsource IPはConsumer VPCのIPアドレスではなく、Provider VPCにあるPPNLBに割り当てられたVIPになる。
    - Backend memberからの復路のトラフィックは、PPNLBを経由することなく、VPEにDSR(Direct Server Return)で戻る。
    -  Consumer VPCとProvider VPCは同一VPCであっても良い。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/528bf3ef-a00b-9cae-03bf-380c01549b81.png)


Private Pathの制限事項は以下の通り。

- https://cloud.ibm.com/docs/vpc?topic=vpc-ppsg-limitations&interface=ui
- https://cloud.ibm.com/docs/vpc?topic=vpc-nlb-limitations&interface=ui
- 主なポイントは
    - サービス利用者用VPC(Consumer VPC)、サービス提供者用VPC(Provider VPC)は同一リージョンである必要がある。
    - PPNLBのbackendとしてBM for VPCは選択できない。
    - TCPのみサポート。UDPはサポートしていない。
    - Direct Link/Transit Gateway経由でPrivate Path Serviceに紐付けたVPEに対してアクセスすることは（現時点では）できない。
    - PPNLBで、Security GroupやNetwork ACLを構成することはできない。

また、docsに明示的に記載はされていないが、あるPrivate Pathサービスに対して、１つのVPCには1つのVPEしか作成できないという制約もある（VPEもリージョナルサービスなので複数VPEを作成する意味はないので、この制約は妥当なものではあるが）。

```txt:あるPrivate Pathサービスに対して、１つのVPCには1つのVPEしか作成できない。
An error occurred and virtual private endpoint gateway 'vpe-privatepath-test02' wasn't created.
An endpoint gateway already exists for this service. There is just 1 endpoint gateway allowed for a service per VPC.
```

# 4. Private Path Service 利用のための一連の手順

1. Provider VPC: VSI上にサービスを作成する
2. Provider VPC: PPNLB(Private Path NLB)を作成し、上記のVSIをbackend serverとして登録する
3. Provider VPC: Private Path Serviceを作成し、Consumer VPCからの接続許可に対するポリシーを設定する。この状態では、Private Path Serviceは`Publish=No`の状態。
4. Consumer VPC（同一アカウント）: 上記のPrivate Path Serviceに対してVPEを作成する。
5. Provider VPC: Private Path Serviceにて、VPEからの接続リクエストを許可する。
6. Consumer VPC（同一アカウント）: VPEに対して別AZのreserved IPを割り当てる。
7. Consumer VPC（同一アカウント）: VPE経由での接続テストを行う。
      
      
    <br><br>もし、別アカウントのVPCにサービス公開したい場合は、Publish=Yesに変更する必要がある。<br><br><br>
    
      
      
8. Provider VPC: Private Path Serviceの`Publish=Yes`に変更する（一度Yesにすると戻せない）

   > https://cloud.ibm.com/docs/vpc?topic=vpc-pps-verify&interface=ui&locale=en
   > To verify that the Private Path service is fully functional before publishing it for consumer use, you must use the same account to create the VPE gateway as the account used to create the Private Path service. (After you publish your Private Path service, any account can be used to create the VPE gateway.)
   >
   > https://cloud.ibm.com/docs/vpc?topic=vpc-pps-activating&interface=ui
   > Important: After the service is published, it cannot be unpublished.
   > <br>

9. Consumer VPC（別アカウント）: 上記のPrivate Path Serviceに対してVPEを作成する。
10. Provider VPC: Private Path ServiceVPEからの接続リクエストを許可する。
11. Consumer VPC（別アカウント）: VPEに対して別AZのreserved IPを割り当てる。
12. Consumer VPC（別アカウント）: VPE経由での接続テストを行う。

以下では、1~7までの一連の手順を追ってみたいと思う。（8以降はほぼ同じなので今回は省略）

# 5. 手順

## 5-1. Provider VPC: VSI上にサービスを作成する

詳細手順は省略。今回はwebサーバーおよびSSHサービスが稼働していることとする。

```
[root@hub-spoke-test-syasuda1 ~]# curl localhost
This is PPS test
```

## 5-2. Provider VPC: Private Path NLB(PPNLB)を作成し、上記のVSIをbackend serverとして登録する

1. Load Balancerの注文画面にて、`Create`を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/24849ca8-563a-06cf-5c81-cdfde82b4d11.png)
2. NLBを選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/12594a58-1a2f-7b43-8649-ec352fdd98a5.png)
3. Typeとして`Private path`を選択。Tokyo1に存在するsubnetを選択する。**なお、先述の通り、PPNLBはリージョナルサービスであり、このsubnet上でPPNLBが稼働するという意味ではない。このsubnetはbackend serverに転送する際のsource IPとして利用される**。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/cda1527a-ad50-9586-ca46-558861ffe396.png)
4. ここはデフォルトのまま（後から設定をする）![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/a7f9c8be-6590-d3e2-550f-6e2b2b2aa6d0.png)
5. 注文完了後。Typeが`Private Path`になっている。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/0a365f69-db0f-3e5c-9622-9ef0612e2b15.png)
6. Frontend-listner/Backend-poolを作成し、公開対象のサービスが稼働するVSIをBackend poolに登録する（省略）。結果、以下のようになる。今回は任意のポート番号でアクセスできるように、Listner port rangesは`1-65535`で構成している。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/72ba590b-8cb7-1503-6292-5b8d630a1128.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/bbfde26d-8f20-678b-c737-dc91ab1518e3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/bb927d66-568e-ec7a-1535-5cbe7f7b0648.png)


## 5-3. Provider VPC: Private Path Serviceを作成する。

1. Create ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/0b19c125-819f-83a0-4558-abcc34aba3ed.png)
2. 以下を指定する。
   - リージョン、Private Path Service名、リソースグループなどを設定。
   - Provider VPCを選択し、先ほど作成したPPNLBを選択する。
   - service endpointのFQDNを指定。Consumer VPCからは、このFQDNでVPEにアクセス可能になる。
   - Zone Affinityの指定。有効にしておくと、Consumer VPCからのアクセス先であるVPEと同一ZoneにあるPPNLBにリクエストが転送される。このヒント情報には以下のように記載されている。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/90891fa6-b25a-289d-003d-1d4e6e78ce70.png)
   - Connection requestのdefault policy。Consumer VPCからの接続許可を求められた際のポリシーとして、
       1. 毎回レビューする(Review all requests)
       2. 常に許可する(Permit all requests)
       3. 常に拒否する(Deny all requests)
    の中から選択することができる。今回は1を選択した。

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/8c468ba2-e993-a22e-0914-3785cc1b377c.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/f282e29e-3b3e-d810-3859-179c31c63524.png)


作成後の状態は、以下の通り。
- Private Path Service一覧 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/864ee55b-9236-c6a9-649d-3995e6d3b2ef.png)
- まだこの状態では、`Published=No`。VPEを作成する際に、Private Path ServiceのCRN情報が必要になるので、控えておく。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/f5689368-e233-b9af-db4c-9f2d6a3e15a0.png)


## 5-4. Consumer VPC: VPEを作成する

1. Create ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/d1bd1e0e-8fb6-095a-0b33-2439ab804c0a.png)
2. 以下を指定する。
   - リージョン、VPE名、リソースグループなどを設定。
   - VPCはConsumer VPCを指定。
   - VPEに割り当てるSecurity Groupを指定
   - `Request connection to a service`では、`Non-IBM Cloud Service`を選択する。これによって、先ほど作成したPrivate Path Serviceを指定することができる。
   - Private Path Service CRNには、先ほど作成したPrivate Path ServiceのCRNを入力する。
   - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/ce680651-55de-dfc5-c159-fe42598f376c.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/149842c9-6c2b-a48c-39bd-2bd395fafefb.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/c74e1d6b-3e4a-2d6b-1705-152d127fbeb0.png)
3. 先ほど作成したVPEは以下の通り。まだ`Pending`状態になっている。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/d3ed2cac-cd4f-3ef2-1a8e-1156fe565a0b.png)


## 5-5. Provider VPC: Private Path Serviceにて、VPEからの接続リクエストを許可する

Provider VPCのPrivate Path Serviceにて、先ほどのVPEからの接続リクエストが来ているため、承認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/bcc246ac-9604-3369-5cd3-417689ba2539.png)
- レビュー待ちの接続リクエストは、`Requests to review`に表示される。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/755b86c6-377a-ca92-ad4a-981ad73fcb2c.png)
- 承認されたリクエストは、`Permitted`で表示される。なお、いったん承認された接続を、`Revoke`することも可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/891a386b-3e87-0b3a-4e62-f589b2be7e57.png)


これにより、Consumer VPCで作成された先ほどのVPEのステータスが`Pending`から`Stable`に変更した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/01fb2bc6-3b74-8c71-0c78-453899e1d2d2.png)

## 5-6. Consumer VPC: VPEに別zoneのreserved IPを割り当てる。

VPEの詳細画面における`Attached Resources`に移動する。VPE自体はリージョナルサービスだが、まだTokyo1のReserved IPが1つしか紐づいいていない。高可用性を保つため、Tokyo2/Tokyo3にもReserved IPを割り当てる。Reserved IPを今後も再利用できるように、Auto-releaseは無効にしておいた。

- before ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/e793a73f-aa64-5526-3daa-9ea1e1b1fe9f.png)
- after ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/30dec243-d32f-3fa9-ebfb-793e741bcc87.png)

## 5-7. Consumer VPC: 接続テスト

```txt:consumer VPCからのservice endpointに対する名前解決。VPEのReserved IPの１つが返ってくる。
$ dig web1.syasuda.pps

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.15 <<>> web1.syasuda.pps
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34896
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;web1.syasuda.pps.		IN	A

;; ANSWER SECTION:
web1.syasuda.pps.	900	IN	A	10.0.0.50

;; Query time: 2 msec
;; SERVER: 161.26.0.7#53(161.26.0.7)
;; WHEN: Wed May 15 17:51:10 JST 2024
;; MSG SIZE  rcvd: 66
```

```txt:consumer VPCからのservice endpointに対するweb access。
$ curl http://web1.syasuda.pps
This is PPS test!
```


```txt:consumer VPCからのservice endpointに対するSSH access。
$ ssh root@web1.syasuda.pps
The authenticity of host 'web1.syasuda.pps (10.0.0.50)' can't be established.
ECDSA key fingerprint is SHA256:dVIWnUPdqR08l8rj8ez0V/WtVYODR/0VWHLE/SzL9kA.
ECDSA key fingerprint is MD5:82:89:98:f8:df:81:00:c7:8b:e0:b8:3d:cc:7c:48:b7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'web1.syasuda.pps,10.0.0.50' (ECDSA) to the list of known hosts.
Last login: Wed May 15 04:52:12 2024 from 111.238.9.129
[root@hub-spoke-test-syasuda1 ~]#
```
```txt:ターゲットサーバーにとっては、Consumer VPCのVSIのIPアドレスではなく、PPNLBのVIPが接続元IPとなっている。
[root@hub-spoke-test-syasuda1 ~]# tail -f /var/log/httpd/access_log
（途中省略）
172.16.0.10 - - [15/May/2024:05:17:44 -0400] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
（途中省略）

[root@hub-spoke-test-syasuda1 ~]# tail -f /var/log/secure
（途中省略）
May 15 05:19:38 hub-spoke-test-syasuda1 sshd[12093]: Accepted publickey for root from 172.16.0.10 port 4096 ssh2: RSA SHA256:0pUqd7pCk8KQH30tsDMx6pTKD/G/DWoVjALradjauuQ
May 15 05:19:38 hub-spoke-test-syasuda1 sshd[12093]: pam_unix(sshd:session): session opened for user root(uid=0) by (uid=0)
（途中省略）
```