AWS PrivateLinkの使い方を解説する

MMMサーバサイドエンジニアの柳沼です。好きなAZはap-northeast-1aです。

2017年11月8日に、AWS VPCの新機能 AWS PrivateLink が発表されました。
まあまあ地味な機能なのであんまり盛り上がってはいませんが、使い方を紹介します。

なにができるのか?

要するに、 インターネットに出ずにEC2からKinesisに繋ぐ EC2やELBのAPIをインターネットに出ずに叩く などのことが実現できるようになります。
EC2からAWS CLIを使用してAWSのAPIを叩く際、APIのリクエストのトラフィックはインターネットを通ります。そのため、インターネットゲートウェイがないとインターネットに出られず、APIが叩けない事になります。
しかし、PrivateLinkを使えば、インターネットに出ずにEC2のAPIを叩くことができるようになります。
今まではS3・DynamoDBへはVPCエンドポイントを経由して同様のことができましたが、その機能の拡張だと捉えて良さそうです。

仕組み

そもそも、従来のS3へつなぐためのVPCエンドポイントは、実体はゲートウェイでした。
しかし、PrivateLinkの実体はVPC(サブネット)内のENIです。つまり、PrivateLink自体がIPアドレスを持ち、VPC内に直接エンドポイントが作成されます。
インターネットに出ることなく、PrivateLinkがAWSサービス(前述のEC2のAPIなど)とプライベートなコネクションを持つことができます。

(出典)
こちらの図が最高にわかりやすいです。

なにが嬉しいのか?

  • インターネットに出なくても良い
  • (ENIなので)セキュリティグループが使える
  • Direct Connectを使えば、オンプレから一切インターネットに出る必要がない!!!

やってみよう

今回は以下の様なことをやってみます。

  • プライベートサブネットにふたつのEC2インスタンスを立てる
  • 当該プライベートサブネットにEC2用のPrivateLinkを作る
  • セキュリティグループで、片方のインスタンスからのみ繋げるようにする
  • セキュリティグループで許可されたEC2インスタンスからのみEC2のAPIが叩けることを確認する

構築手順

事前準備

まずは、VPCとサブネットをごく普通に、思い思いのやり方で作ります。
以下のように作成しました。

VPC

サブネット

大事なのは、サブネットのルートテーブルです。
要件として、プライベートである必要があるため、インターネットゲートウェイは外しておきます。
ただし、今回はサブネット内のインスタンスにSSHしたいため、断腸の思いで以下のようなルートテーブルを作成しました。

SSHの戻りのトラフィックを受け付けるために、筆者の環境のIPアドレスへのルーティングのみインターネットを通るようにしておきます。

次に、インスタンスを作っておきます。
いい感じにつくればOKです。
以下のように作りました。

どちらのインスタンスも、先程作ったサブネットに入れておきます。

次に、PrivateLinkにアタッチするためのセキュリティグループを作ります。
このセキュリティグループで、どちらかのインスタンスからのみアクセスできるような設定を行います。
以下のように作ります。

ポイントは、 HTTPSを許可すること プライベートIPを指定すること です。
前者は、EC2のAPIのリクエストはHTTPSでやり取りしているため、後者は、AWS内のプライベートなコネクションを使用するためです。

PrivateLinkを作る

PrivateLinkを作っていきます。
VPCコンソールの エンドポイント を選択します。

すると、以下のような画面になります。

今回は、EC2のAPIを叩きたいので、以下のように設定します。

サブネットとセキュリティグループは先程作ったものを指定します。
また、後述しますが、 Enable for this endpoint はチェックを入れておきます。(入れていなくてもOKです。)

ここまで作れば、準備はOKです。

検証する

検証していきます。
インスタンスを新しく作っているので、 ~/.aws/credentials については新しく作るか、 aws configure を叩くかして設定しておいてください。

セキュリティグループを閉じているインスタンス

1
$ aws ec2 describe-availability-zones --region us-east-1

HTTPSConnectionPool(host='vpce-09e3f81544e4090f1-c6clcpks.ec2.us-east-1.vpce.amazonaws.com', port=443): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<botocore.awsrequest.AWSHTTPSConnection object at 0x7fd7e70f9ad0>, 'Connection to vpce-09e3f81544e4090f1-c6clcpks.ec2.us-east-1.vpce.amazonaws.com timed out. (connect timeout=60)'))

タイムアウトしました。
インターネットへのルーティングがなく、PrivateLinkからも許可されていないためです。

セキュリティグループを開けているインスタンス

1
$ aws ec2 describe-availability-zones --region us-east-1
{
    "AvailabilityZones": [
        {
            "State": "available",
            "ZoneName": "us-east-1a",
            "Messages": [],
            "RegionName": "us-east-1"
        },
        {
            "State": "available",
            "ZoneName": "us-east-1b",
            "Messages": [],
            "RegionName": "us-east-1"
        },
        {
            "State": "available",
            "ZoneName": "us-east-1c",
            "Messages": [],
            "RegionName": "us-east-1"
        },
        {
            "State": "available",
            "ZoneName": "us-east-1d",
            "Messages": [],
            "RegionName": "us-east-1"
        },
        {
            "State": "available",
            "ZoneName": "us-east-1e",
            "Messages": [],
            "RegionName": "us-east-1"
        },
        {
            "State": "available",
            "ZoneName": "us-east-1f",
            "Messages": [],
            "RegionName": "us-east-1"
        }
    ]
}

インターネットへのルーティングがなくても、EC2のAPIが叩けました!!!

ちなみに

前述の Enable Private DNS Name ですが、もしチェックを入れないと以下のようなコマンドを叩く必要があります。

1
$ aws ec2 describe-availability-zones --region us-east-1 --endpoint-url https://vpce-xxxxxxxxxxxxxxxxx-xxxxxxxx.ec2.us-east-1.vpce.amazonaws.com

チェックが入っていると、APIリクエスト先である ec2.us-east-1.amazonaws.com のVPC内のルックアップが、
作成したPrivateLinkのIPアドレスに解決されます。

まとめ

地味な機能ですが、インターネットに出たくない状況では使えそうです。

参考資料

このエントリーをはてなブックマークに追加