kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

AWS PrivateLinkで、異なるAWSアカウントの複数の重複するVPCレンジを接続する一例

自分用メモです。

前回、Organizations+SSOを使って、開発・ステージング・本番を複数アカウントで別々に管理するのをやりました。

で、実際にはここからVPCを作ってサブネット作って・・・みたいに環境を作っていくことになりますが、環境は分けたとしてもVPCIPアドレスは同じにしたいですよね。こんな感じに。

f:id:kun432:20200705015551p:plain

環境がアカウントレベルで別れているのでお互いに影響も与えることもない上、アカウントが別れているので同じIPセグメントを使えて環境ごとに設定を変えたりすることもない、とても便利です。その上、請求はOrganizationsとして一括でまとめれる。言うことないです。

でも逆にこういうふうに共通的なVPCを作りたくなる場合もあるかと思います。

f:id:kun432:20200705021254p:plain

VPC同士をつなぐにはいくつかの方法がありますが、ポイントは開発・ステージング・本番はIPセグメントが同じだということですね。VPC ピアリングは重複するIPセグメントのVPCだとつなげません。上記の例だとピアリングするVPC同士というわけではないのでいけそうな気がするのですが、VPCピアリングはIPルーティングなのでどこかで異なるセグメントにする必要が出て来るだろうと思っています。公式ドキュメントにも複数VPCを接続する場合の例が載っていますが、重複するVPC内の異なるサブネットと接続してたりして回避しているように見えます。

それだとせっかくアカウントを分けてVPCを同じIPセグメントにしたのに、意味がないです。ということで、IPセグメントが重複するVPC間でも接続が可能な PrivateLink を使ってやってみます。

構成

目指す構成はこうなります。

f:id:kun432:20200705025121p:plain

前提条件

  • 確認方法として、共通サービス用AWSアカウント内に確認用のEC2インスタンスを立ててapacheを動かして、他のAWSアカウントのVPCのEC2インスタンスSSHしてcurlで確認します。
  • Organizations+SSOで、各AWSアカウントならびにSSOアカウントを用意しておきます。検証のため、権限セットはとりあえずPowerUserAccessにしますが、実際には要件に合わせて設定してください。
  • 各環境でVPC・サブネット・セキュリティグループ・ルートテーブルはよしなに設定する必要があります。本来ならばサブネットやセキュリティグループの設定はもっと細かくすべきですが、今回はSSHで確認をするので、すべてパブリックサブネットにしてインターネットからのアクセスも可能にしてやります。

共通サービス側の設定

VPCの作成

VPCを作ります。172.16.0.0/16の「shared-vpc」というVPCを作りました。

f:id:kun432:20200705182802p:plain

上記VPC内にサブネットを作ります。検証なのでap-northeast-1aに/24のサブネット「shared-vpc-subnet-a」を一つだけ作りました。

f:id:kun432:20200705182947p:plain

インターネットゲートウェイを作ります。これはEC2インスタンスSSHでログインするためのもので、他のVPCからの通信を受けるためには必須ではありません。

f:id:kun432:20200705183059p:plain

作成したインターネットゲートウェイVPCにアタッチしておきます。

f:id:kun432:20200705183319p:plain

ルートテーブルを作成します。

f:id:kun432:20200705185854p:plain

サブネット「shared-vpc-subnet-a」と関連付けしておきます。

f:id:kun432:20200705190024p:plain

f:id:kun432:20200705190337p:plain

ルートを編集して、インターネットゲートウェイのルートを追加しておきます。

f:id:kun432:20200705190557p:plain

f:id:kun432:20200705190639p:plain

VPCはこれで終わりです。

EC2インスタンスの作成

EC2インスタンスを作成します。AMIはAmazon Linux 2を選択。

f:id:kun432:20200705183845p:plain

インスタンスタイプは検証なのでt2.microを選択。

f:id:kun432:20200705183916p:plain

先ほど作成したVPC「shared-vpc」のサブネット「shared-vpc-subnet-a」に配置します。パブリックIPも付与するようにしておきます。

f:id:kun432:20200705184120p:plain

ストレージとタグはそのまま進めます。

f:id:kun432:20200705184528p:plain

f:id:kun432:20200705184608p:plain

セキュリティグループの設定です。SSHは自分のIPからのみアクセス許可に変更、あとapacheを立てるのでVPC内からHTTPを許可するルールを追加しておきます。

f:id:kun432:20200705185134p:plain

起動します。キーペアはよしなに。

f:id:kun432:20200705185238p:plain

SSHでログインして、apacheを立ち上げておきます。

$ ssh -i ./shared-service-vpc-ec2.pem ec2-user@XXX.XXX.XXX.XXX
[ec2-user@ip-XXX.XXX.XXX.XXX ~]$ sudo yum install -y httpd
[ec2-user@ip-XXX.XXX.XXX.XXX ~]$ sudo systemctl start httpd
[ec2-user@ip-XXX.XXX.XXX.XXX ~]$ echo "ok" | sudo tee -a /var/www/html/index.html
[ec2-user@ip-XXX.XXX.XXX.XXX ~]$ curl http://localhost
ok

EC2の準備も完了です。

NLBの作成

次にNLBです。「ロードバランサーの作成」をクリックします。

f:id:kun432:20200705195015p:plain

Network Load Balancerを選択します。

f:id:kun432:20200705195051p:plain

「shared-vpc-nlb」という名前のNLBを設定していきます。

  • PrivateLinkで受けるので「内部」を選択
  • apacheが待ち受けているEC2へ流すのでリスナーはTCP:80
  • NLBのVPCおよびAZ、それに紐付いているサブネットを設定していきます。
  • NLBのIPはサブネットから払い出すこととします。

全部設定したら次に進みます。

f:id:kun432:20200705195108p:plain

セキュリティ設定はそのまま進みます。

f:id:kun432:20200705195501p:plain

ターゲットグループの設定です。NLBから流したいEC2インスタンスグループののポートやヘルスチェックを指定します。

f:id:kun432:20200705195526p:plain

ターゲットグループに登録するターゲットを追加します。さきほど作成したEC2インスタンスが見えているはずですのでこれを追加します。

f:id:kun432:20200705195830p:plain

確認画面が表示されますので、「作成」します。

f:id:kun432:20200705200005p:plain

念のため、作成したNLBがActiveになっていること、ターゲットグループへのヘルスチェックがhealthyになっていることを確認しておいてください。

f:id:kun432:20200705200700p:plain

f:id:kun432:20200705200711p:plain

PrivateLinkの設定

PrivateLinkの設定です。アカウントをまたいだPrivateLinkの場合、

  • 接続先(共有サービス側)でVPCエンドポイントサービスを作成しNLBを紐付け、接続元アカウントを接続許可するホワイトリストに追加
  • 接続元(各環境側)でVPCエンドポイントを作成し、接続先への接続許可承認を申請
  • 接続先(共有サービス側)で接続リクエストを承認

という一連の承認プロセスを経て、接続ができるようになります。

まずは、接続先となる共有サービス側で設定を行っていきます。

VPCの設定画面で「エンドポイントサービス」をクリックして、「エンドポイントサービスの作成」をクリックします。

f:id:kun432:20200705202255p:plain

作成したNLBを選択して、「サービスの作成」をクリックします。「エンドポイントの承諾が必要」にチェックを入れておくと承認が必要になりますが、このチェックを外すとホワイトリストに登録されているアカウントからエンドポイントを作成すると自動的に接続されます。今回はチェックを入れておきます。

f:id:kun432:20200705202342p:plain

エンドポイントサービスが作成されました。作成されたエンドポイントサービスの「ホワイトリストに登録されたプリンシパル」タブを開いて、「ホワイトリストプリンシパルを追加する」をクリックします。

f:id:kun432:20200705202642p:plain

追加するアイデンティティに、接続許可するAWSアカウントのARNを登録していきます。「arn:aws:iam::AWSアカウントID:root」のフォーマットで登録します。

f:id:kun432:20200705203619p:plain

これで準備完了です。VPCエンドポイントサービスの画面を開いて、作成したVPCエンドポイントサービスの「サービス名」をメモしておいてください。各環境側から接続する際に必要になります。

f:id:kun432:20200705221010p:plain

各環境側の設定

では各環境側の設定をやっていきます。開発/ステージング/本番共通の手順になるのと、ここまでの手順とかぶるところもあるので割愛します。

  • VPC: 10.0.0.0/16
  • サブネット: ap-northeast-1a
  • インターネットゲートウェイを作成してVPCにアタッチ
  • ルートテーブル作成
    • 上記VPCに作成
    • 上記サブネットに関連付け
    • 0.0.0.0/0をインターネットゲートウェイにルーティング
  • EC2
    • Amazon Linux 2
    • t2.micro
    • 上記VPCのサブネットに配置
    • パブリックIPも割り当てておく
    • セキュリティグループ
      • 自IPからのSSHだけ許可
      • 同じセキュリティグループ内からのHTTPを許可

VPCエンドポイントの作成

VPCのメニューから「エンドポイント」をクリック、「エンドポイントの作成」をクリックします。

f:id:kun432:20200705213305p:plain

エンドポイント作成画面で、共通サービス側のVPCエンドポイントサービスの作成時にメモしておいた「サービス名」を入力して「検証」をクリックします。共通サービス側でホワイトリストで許可されていれば、サービスが見つかりました、と表示されます。

f:id:kun432:20200705214910p:plain

各環境側のVPC・サブネット・セキュリティグループと紐付けます。最後に「エンドポイントの作成」をクリックします。

f:id:kun432:20200705215334p:plain

エンドポイントが作成されましたが、「承諾の保留中」となっていますね。接続先側のVPCエンドポイントサービスで承諾を必須としている場合、承諾が行われるまでは使えませんので、共通サービス側で承諾しましょう。

f:id:kun432:20200705220123p:plain

共通サービス側のVPCエンドポイントサービスの画面で、「エンドポイント接続」タブに接続元アカウントとエンドポイントが表示されていますので、これを選択して、アクションから「接続リクエストの承諾」を選択します。

f:id:kun432:20200705220225p:plain

承諾します。

f:id:kun432:20200705220437p:plain

承諾直後は「保留中」になっていますが、数分立つと「利用可能」に変わります。これで各環境からの接続が可能な状態になりました。

f:id:kun432:20200705220647p:plain

各環境側に戻るとVPCエンドポイントが利用可能になりました。また、ここでDNS名が表示されていますね。これでアクセスが可能になります。

f:id:kun432:20200705222120p:plain

各環境側のEC2インスタンスSSHしてcurlを叩いてみましょう。

$ ssh -i ~/Downloads/dev-vpc-ec2pem.pem ec2-user@XXX.XXX.XXX.XXX
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ curl vpce-XXXXXXXXXXXXXXXX-XXXXXXXX.vpce-svc-XXXXXXXXXXXXXXXX.ap-northeast-1.vpce.amazonaws.com
ok

接続できました!残りは割愛しますが、同様に接続ができると思います。ただ、共通サービス側のapacheで確認してみたところ、どこからアクセスが来ているかを区別することはできませんでした。そこはもう少し追いかけてみたいと思います。

まとめ

Organizations+SSOでアカウントを分けつつも、IPアドレス帯は共通的にアクセスしたい、という場合には役に立つのではないでしょうか。

参考

基本的にここにすべて載ってますw 単にOrganizations+SSOの環境で写経しただけですね・・・