AWS PrivateLinkの真実：VPCエンドポイントとの関係性を徹底解説

# 1. 背景
VPCエンドポイントを紹介する記事で「インターフェース型エンドポイント (AWS `PrivateLink`)」のような表現や、「`PrivateLink`とは、AWSへのAPIアクセスをインターネットを経由せずに行えるインターフェースタイプのVPCエンドポイントです。インターフェースタイプは`PrivateLink`と呼ばれています」といった説明をよく目にしたことがあるのではないでしょうか。

https://devlog.arksystems.co.jp/2018/05/11/4896/

このような説明により、<font color="red">`PrivateLink`がインターフェースVPCエンドポイントと同義だと誤解</font>してしまう方が多いのではないかと懸念されます。
本記事では、AWS VPCエンドポイントの種類、その使い分け、そしてVPCエンドポイントと`PrivateLink`の関係について整理します。

:::note info
AWS VPCエンドポイントには以下の3種類があります。
- ゲートウェイエンドポイント（Gateway Endpoint）
- インターフェースエンドポイント（Interface Endpoint）
- Gateway Load Balancer エンドポイント（GWLB Endpoint）

Gateway Load Balancer エンドポイントは、VPC内のトラフィックを `Gateway Load Balancer`にルーティングするためのエンドポイントです。これにより、セキュリティアプライアンスやその他のネットワークサービスを、スケーラブルかつ高可用性の方法で展開することが可能になります。
つまり、Gateway Load Balancer エンドポイントは`Gateway Load Balancer`を利用するという前提の話で、他の2つのエンドポイントとは全く異なる性質を持っているため、詳細は別の記事で説明します。
:::

`PrivateLink`とVPCピアリングの使い分けは以下の記事をご参考ください。

https://qiita.com/dennis_wang/items/0964a346df78e51d6633

# 2. ゲートウェイ型エンドポイント
## 2.1 ゲートウェイ型エンドポイントの仕組み
https://dev.classmethod.jp/articles/vpc-endpoint-gateway-type/

**概要：**
- ゲートウェイ型エンドポイントを使用すると、VPC内のリソース(プライベートサブネット内でプライベートIPアドレスを持っているリソース)はパブリックインターネットを経由せずに直接`S3`や`DynamoDB`にアクセスできます。
- S3やDynamoDBへのトラフィックをAWSの内部ネットワークを通じて直接ルーティングするため、`NAT Gateway`やパブリックIPアドレスは不要です。
- トラフィックはインターネットを経由せず、AWSのネットワーク内に留まるため、プライベートIPからパブリックIPへの変換は必要ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/55632af4-9fd3-bbec-bfb6-7dda02542934.png)


**特徴：**
- 対象サービス：<font color="red">`S3`と`DynamoDB`のみ</font>
- エンドポイントを作成するとVPCのルートテーブルに<font color="red">特別なルートが自動的に追加</font>
    - インターネットゲートウェイやVPNゲートウェイと同じように、<font color="red">ルーティングによりその条件にあった場合、ゲートウェイを通る</font>という形になります。ゲートウェイ型のVPCエンドポイントを設定した場合、ルーティングにも変更が加えられます。
- VPC内のリソースからのみ利用可能、VPC外からの利用は不可能(<font color="red">アウトバンドのみ</font>)
    - VPC外のリソースは、VPCのルートテーブルにアクセスできないため、エンドポイントを直接利用することはできません。
- <font color="red">完全無料</font>


:::note info
1. 歴史的経緯:
    - ゲートウェイ型エンドポイントは、インターフェース型エンドポイントよりも先に導入されました。
    - 当初は`S3`と`DynamoDB`へのプライベートアクセスを提供するために設計されました。
    - ゲートウェイ型はルートテーブルを使用して実装されており、DNSの成熟を待つ必要がありませんでした
    - インターフェース型エンドポイントはより新しい技術でAWS PrivateLinkを使用し、柔軟性が高いですが、コストがかかります。
2. <font color="red">`S3`は2021年2月から、`DynamoDB`は2024年3月からインターフェース型エンドポイントも利用可能になった</font>。
:::

## 2.2 ゲートウェイ型エンドポイントを検証
全体図：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/bdfe20a4-deab-047e-8eef-28df50d34cfa.png)

### 2.2.1 事前準備
1. VPC作成
    - `VPC and more`を選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/05d39c11-6a49-531e-f734-a80e6d7a9ae6.png)
    - わかりやすくするために、AZを一つだけに指定し、S3 Gateway型のVPC endpointは後ほど手動で作るため、こちらで一旦OFFにする
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/ce7ccade-c5ce-5f30-9694-922edbbcabda.png)
    - 生成されるリソースのリスト：
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/1f58d2e3-83b4-1265-9e5f-cd6f7de45d68.png)
        - VPC: １個
        - Subnet: 
            - public subnet用：1個
            - private subnet用：１個
        - Route table: 
            - public subnet用：1個
            - private subnet用：１個
        - Internet Gateway: １個(public subnet用)

1. public subnetとprivate subnetそれぞれに1つのEC2インスタンス作成(新規作成する時に、同じ`key-pair`を選択する必要がある)
1. ローカル端末のみに秘密鍵を保持し、`SSH Agent Forwarding`によるbastionサーバー経由でprivate subnetにあるEC2にアクセス。詳細なやり方は以下の記事をご参考

https://qiita.com/dennis_wang/items/3173f1fe33e40c190f97#5-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AEsshconfig%E3%81%A7%E8%A8%AD%E5%AE%9A%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95


### 2.2.2 VPCエンドポイントなしの状態でS3のバケットリストを取得
1. bastion server(public subnet): 
<font color="red">**Internet Gateway経由でインターネットにアクセス可能だから、pingもできるし、S3のバケット一覧取得もできる**</font>
    ```
    [ec2-user@ip-10-0-20-223 ~]$ ping google.co.jp
    PING google.co.jp (142.251.42.131) 56(84) bytes of data.
    64 bytes from nrt12s45-in-f3.1e100.net (142.251.42.131): icmp_seq=1 ttl=56 time=1.25 ms
    64 bytes from nrt12s45-in-f3.1e100.net (142.251.42.131): icmp_seq=2 ttl=56 time=1.28 ms
    64 bytes from nrt12s45-in-f3.1e100.net (142.251.42.131): icmp_seq=3 ttl=56 time=1.32 ms
    ^C
    --- google.co.jp ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2002ms
    rtt min/avg/max/mdev = 1.248/1.281/1.319/0.029 ms
    
    [ec2-user@ip-10-0-20-223 ~]$ aws s3 ls
    2024-06-24 06:53:51 databricks-workspace-stack-bucket
    ```
2. private subnetのEC2から：
<font color="red">**インターネットに直接アクセスできないから、当然pingもできないし、S3のバケット一覧取得もできない**</font>
    ```
    [ec2-user@ip-10-0-30-163 ~]$ ping google.co.jp
    PING google.co.jp (142.251.222.3) 56(84) bytes of data.
    
    ^C
    --- google.co.jp ping statistics ---
    22 packets transmitted, 0 received, 100% packet loss, time 21810ms
    
    [ec2-user@ip-10-0-30-163 ~]$ aws s3 ls
    
    ```
### 2.2.3 ゲートウェイ型エンドポイント経由でS3のバケットリストを取得
1. endpoint作成
    - S3用の<font color="red">private subnetための</font>gateway型endpointを選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/a3ed7d5d-502f-1329-3b96-bab9b6d4177c.png)
    - **private subnet**の`route table`を選択して、endpoint作成
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/4735a321-6f39-01b3-6379-8af29e1239fa.png)
    - 作ったものを確認
         ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/8ef71895-a8b5-8795-05e1-d3e126cf11ac.png)
        -  **private subnet**の`route table`に以下のrouteが自動的に追加された
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/a421b89c-bce6-4d81-f45e-2b62ce51e324.png)
        - Destiationをクリックすると、`Prifix list`が表示される
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/b2b255c1-4179-2237-4ae4-37f910bb7575.png)
        - `Prifix list`の中身：
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/661f2489-b94f-9be2-8477-60fed8d6de7a.png)
    
        :::note info
        - こちらの`Prefix list`はAWSによって管理され、自動的に更新されます。
        - `Prefix list`の名前はリージョン＋サービスで固定されています。例えば、東京リージョンのS3を利用しているすべてのユーザーは`pl-61a54008`という`Prefix list`を使用します。
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/bedc9457-4b59-4733-ec1f-0ab46121e001.png)
        
        - リージョン固有：各AWSリージョンに特有のS3 IPアドレス範囲が含まれる。
        - 以下のコマンドで東京リージョンのS3のパブリックIP一覧を取得できた。原因はまだ不明ですが、上記の`Prefix list`よりも数個多いようです。
            ```
            ~ % curl https://ip-ranges.amazonaws.com/ip-ranges.json | jq -r '.prefixes[] | select(.region=="ap-northeast-1") | select(.service=="S3") | .ip_prefix'
            
            52.219.68.0/22
            52.219.162.0/23
            52.219.16.0/22
            52.219.195.0/24
            3.5.152.0/21
            52.219.0.0/20
            52.219.20.0/24
            52.219.136.0/22
            52.219.201.0/24
            52.219.172.0/22
            52.219.200.0/24
            52.219.152.0/22
            52.219.150.0/23
            52.219.196.0/22
            35.72.164.240/28
            35.73.115.0/28
            ```
1. <font color="red">private subnetのEC2からendpoint経由でS3のバケットリストが取得できた</font>
    ```
        [ec2-user@ip-10-0-30-163 ~]$ ping google.co.jp
        PING google.co.jp (142.251.42.131) 56(84) bytes of data.
        64 bytes from nrt12s45-in-f3.1e100.net (142.251.42.131): icmp_seq=1 ttl=56 time=1.25 ms
        64 bytes from nrt12s45-in-f3.1e100.net (142.251.42.131): icmp_seq=2 ttl=56 time=1.28 ms
        64 bytes from nrt12s45-in-f3.1e100.net (142.251.42.131): icmp_seq=3 ttl=56 time=1.32 ms
        ^C
        --- google.co.jp ping statistics ---
        3 packets transmitted, 3 received, 0% packet loss, time 2002ms
        rtt min/avg/max/mdev = 1.248/1.281/1.319/0.029 ms
    
        
        [ec2-user@ip-10-0-30-163 ~]$ aws s3 ls
        2024-06-24 06:53:51 databricks-workspace-stack-bucket
    ```


# 3. インターフェース型エンドポイント
インターフェース型エンドポイントは`Elastic Network Interface (ENI) `を介することで、インターネットを経由せずにAWSのプライベートネットワーク経由で直接AWSサービスにアクセスできるVPCエンドポイントの一種です。
インターフェース型エンドポイント中の`インターフェース`は、`ENI `を指しています。つまり、<font color="red">インターフェースVPCエンドポイントの正体は`ENI`</font>です。
`ENI`は、物理的な環境における`Network Interface Card (NIC)`に相当します。VPC内のリソースとAWSサービス間の通信を仲介する役割を果たします。
<font color="red">インターフェース型エンドポイントの仕組みやインターフェースVPCエンドポイントを利用してSystem Managerからprivate subnetにあるEC2インスタンスにアクセスするケース</font>については以下をご参考：

https://qiita.com/dennis_wang/items/02396659ba65ba0aa0e2#523-%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AE%E8%A7%A3%E8%AA%AC


インターフェース型VPCエンドポイントのイメージとしては以下のような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/b98f6ff4-564e-fc89-fd8b-d9fc88e1c9ff.png)

- 作成時にENIのプライベートIPアドレスも指定可能
    - ENIには、サブネットのアドレス範囲(CIDR内で空いているIP)からプライベートIPアドレスが割り当てられます。
    - これにより、VPC内のリソースが固定のプライベートIPアドレスを使用してAWSサービスにアクセスできるようになります。
- IPを指定しない場合はAWS側でサブネットのCIDR内で空いているIPがランダムに付与される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/7e415904-4a93-4f51-94d6-76b84e61c782.png)


# 4. VPCエンドポイントのまとめ
AWS のゲートウェイエンドポイントとインターフェースエンドポイントを総合的に比較した結果を以下の表にまとめました。

| 特徴 | ゲートウェイエンドポイント | インターフェースエンドポイント |
|------|---------------------------|--------------------------------|
| サポートするサービス | <font color="red">`S3`と`DynamoDB`のみ</font> | <font color="red">`S3`、`DynamoDB`も含まれる</font>多数のAWSサービスとパートナーサービス |
| 接続方式(正体) | <font color="red">ルートテーブル</font>を使用 | <font color="red">ENI</font>を使用 |
| AWS PrivateLink の使用 | 使用しない | <font color="red">使用する</font> |
| コスト | <font color="red">完全無料</font> | <font color="red">時間単位の料金 + データ通信量</font> |
| セキュリティ制御 | VPCエンドポイントポリシー | <font color="red">ENIに割り当てるセキュリティグループ(細かい制御可能)</font> |
| 可用性 | リージョン内のすべてのAZで自動的に高可用性 | 各AZに個別に作成する必要あり |
| オンオプレからのアクセス | <font color="red">VPC内からのみアクセス可能</font> | <font color="red">可能</font> |
| IPアドレス | 不要 | プライベートIPアドレスを使用 |
| DNS設定 | 不要 | 必要 |
| パフォーマンス | 低レイテンシー | やや高いレイテンシー |
| セットアップの複雑さ | 比較的シンプル | やや複雑 |
| クロスリージョンアクセス | 不可 | <font color="red">可能</font> |
| オンプレミス接続 | 不可能 | <font color="red">可能</font>(Direct ConnectやVPN経由) |

# 5. `S3`と`DynamoDB`におけるゲートウェイ型とインターフェース型エンドポイントの使い分け
<font color="red">`S3`は2021年2月から、`DynamoDB`は2024年3月からインターフェース型エンドポイントも利用可能になった</font>。使い分けのベストプラクティスはいかになる：
1. <font color="red">コスト重視の場合はゲートウェイ型を選択</font>:
    - ゲートウェイ型エンドポイント：<font color="red">完全無料</font>
    - インターフェース型エンドポイント：時間単位の料金(<font color="red">通信しなくても課金</font>) + データ転送量に応じた料金
2. <font color="red">VPC内からのアクセスのみの場合はゲートウェイ型</font>:
    - VPC内のリソースから`S3`や`DynamoDB`にアクセスする場合、ゲートウェイ型で十分
3. <font color="red">オンプレミスや他のregionからのアクセスが必要な場合はインターフェース型</font>:
ゲートウェイ型はVPC外からのアクセスを許可しませんが、インターフェース型はオンプレミスや他のAWSリージョンからのアクセスが可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/ed840401-2463-e0b1-2d68-f8e51d03b872.png)

    - リージョンをまたぐ接続：
    リージョン間でVPCピアリング接続を行う場合、インターフェイス型エンドポイントを選択する必要があります。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/f2422747-a9b3-657f-eea9-6e69673c7de6.png)
    - オンプレミスからのプライベートな接続：
    通信元がオンプレミス環境の場合、ゲートウェイ型エンドポイントは利用できません。オンプレミスとAWSの通信は専用線やVPNを経由し、インターフェイス型エンドポイントを選択することでプライベートな接続が可能になります。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/acce1d3c-ff00-e17c-2dfe-b61e7100a22c.png)

https://note.shiftinc.jp/n/n388b9bf3e2b6

# 6.`PrivateLink`とインターフェースVPCエンドポイントの関係
1. AWS `PrivateLink`の定義:
    - <font color="red">`AWS PrivateLink`は単独のサービスメニューではありません</font>。AWSコンソールの検索ボックスに`PrivateLink`と入力しても直接的な結果は表示されません。
    - 実際には、AWS `PrivateLink`は<font color="red">以下の要素を組み合わせた技術やアーキテクチャの総称</font>：
        - インターフェースVPCエンドポイント（サービス利用側のVPC内で作成）
        - VPCエンドポイントサービス（サービス提供側のVPC内で作成）
    - VPCとサポートされているAWSサービス、他のAWSアカウントによってホストされているサービス、およびAWS Marketplaceのサービス間のプライベート接続を確立するために利用される。

2. `PrivateLink`の構成要素:
    1. VPCから他のAWSアカウントによってホストされているサービスや、AWS上で稼働している第三者提供のSaaSサービスへの接続の場合：
        - インターフェースVPCエンドポイント（サービス利用側のVPC内で作成）
        - <font color="red">VPCエンドポイントサービス（サービス提供側のVPC内で作成）</font>
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/ca75acfa-0b9e-affa-c938-d900575337ca.png)
    
    2. VPCからサポートされているAWSサービスへの接続の場合:
        - インターフェースVPCエンドポイントのみを使用
        - <font color="red">VPCエンドポイントサービスは不要</font>
        ![image-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/200cb10a-aa12-21dc-b13c-8826185ac135.png)

        :::note info
        AWSサービスへの接続では、AWSが既にサービス側のインフラストラクチャを管理しているため、VPCエンドポイントサービスを別途作成する必要がありません。AWSが提供するエンドポイントに直接接続することができます。


3. インターフェースVPCエンドポイントとの関係:
    - <font color="red">`PrivateLink`がインターフェースVPCエンドポイントと同義ではありません</font>。
    - <font color="red">インターフェースVPCエンドポイントはAWS `PrivateLink`の一部であり、サービス利用側のVPC内に作成されるコンポーネント</font>です。

4. VPCエンドポイントとの関係:
    - VPCエンドポイントには、インターフェース型、ゲートウェイ型、Gateway Load Balancer型の3種類があり、このうちAWS `PrivateLink`を使用するのは以下の二種類です。
        - インターフェース型エンドポイント
        - Gateway Load Balancer型エンドポイント
    - ゲートウェイ型エンドポイント（`S3`や`DynamoDB`で使用）はAWS `PrivateLink`を使用しません。
         <font color="red">ゲートウェイ型エンドポイントは、ルートテーブルのエントリを使用してトラフィックをルーティングします。これはENIを使用する`PrivateLink`とは根本的に異なるアプローチです。</font>


7. `PrivateLink`のエンドポイントサービスに利用できるロードバランサー
- AWS `PrivateLink`のエンドポイントサービスは、基本的に`Network Load Balancer（NLB）`のみがサポートされています。これは、AWSの仕様上、エンドポイントサービスはNLBを前提として設計されているためです。
    - 理由と背景(エンドポイントサービスの要件)：
        - 高いスループットと低遅延を実現するために、TCPレベルの負荷分散が必要です。
        - NLBはTCP/UDPのレベルで動作し、これに最適化されているため、エンドポイントサービスの前段に使われます。
        - `ALB（Application Load Balancer）`はレイヤー7（HTTP/HTTPS）の負荷分散を行うため、エンドポイントサービスの作成には対応していません。つまり、ALBはエンドポイントサービスのターゲットとしてはサポートされていません。
- NLBはTCP:80, 443でリッスン可能なので、REST APIの公開要件も満たせます。
- ただし、NLBのターゲットグループとしてALBを登録する新機能が提供されており、NLB経由でALBの公開が可能です。
- 構成例
    - ALBでREST API（HTTP/HTTPS）を公開
        - ALBのリスナー: 80（HTTP）、443（HTTPS）
    - NLBのターゲットグループにALBを登録
        - NLBのリスナー: TCP:80、TCP:443
        - ターゲットタイプ: ALB
    - NLBでPrivateLinkエンドポイントサービスを作成
    - 利用者はインターフェースVPCエンドポイント経由でNLBにアクセスし、ALBのAPIに到達