mazyu36の日記

某SIer所属のクラウドエンジニアのブログ

VPC LatticeのService Networkは送信元のVPCと受信側のServiceを関連付ければ良い

前回のブログでVPC LatticeをAWS CDK(L1 Construct)で構築してみました。

mazyu36.hatenablog.com

とりあえず動作はしましたが、VPCとService Networkの関連付けや、Service NetworkとServiceの関連付けのところはあまりよくわかっていませんでした。

そのためドキュメントやAWS公式のブログの内容をもとに改めて確認したことをまとめます。

先に結論だけ記載しておくと以下でした。

  • 受信を行いたいリソースはVPC Lattice Serviceを作成し、Service Networkと関連付ける
  • 送信を行いたいリソースは所属するVPCをService Networkと関連づける(送信のみであればVPC Lattice Serviceの作成不要)

※水色がService Network-VPCの関連付け、緑色がService Network-Serviceの関連付けを示します。

目次

VPC Latticeの動作仕様確認

以下の公式のドキュメントにVPC Latticeがどのように動作するか示されています。

docs.aws.amazon.com

この中でService NetworkとService/VPCの関連付け要否については、以下の1文に集約されているかと思います。

Services that are associated with the service network can receive requests from clients whose VPCs are also associated with the service network.

Service Networkと関連づけられたServiceは、Service Networkと関連づけられたVPC内のクライアントからのリクエストを受け取れる。

つまり以下と理解しました。

  • 受信を行いたいリソースはVPC Lattice Serviceを作成し、Service Networkと関連付ける
  • 送信を行いたいリソースは所属するVPCをService Networkと関連づける(送信のみであればVPC Lattice Serviceの作成不要)

これの裏付けとしてドキュメントに以下の構成例が示されています。

このうち、送信と受信を行うリソースは以下です。

  • 送信:VPC3のリソース、VPC1のリソース
  • 受信:VPC1のリソース、VPC2のリソース

そのため先のルールに基づいて以下のようにServiceの作成や、Service Networkとの関連付けが行われています。

  • VPC1のリソース:送信も受信も行うため、Service1を作成し、VPC1およびService1をService Networkに関連付ける
  • VPC2のリソース:受信のみなので、Service2を作成しService2をService Networkに関連づける(VPC2の関連付けは不要※)
  • VPC3のリソース:送信のみなので、VPC3をService Networkに関連づける(Serviceの作成不要)

※については以下のように示されています。

Notice that VPC 2 does not have an arrow or a check mark that represents an association. This means that the service network owner or the service owner hasn't associated VPC 2 with the service network. This is because service 2, in this example, only needs to receive requests and send responses using the same request. In other words, service 2's targets don't need to be clients and don't need to make calls to other services in the service network.

AWS公式ブログのアーキテクチャも見てみる

AWS 公式ブログにおいてもVPC Latticeの詳細な解説記事が出ていました。こちらも見てみます。

aws.amazon.com

構成

ブログ記事のアーキテクチャは以下です。

(画像はAWS公式ブログより引用)

App1~4の4つのApp(Service)が存在しています。またApp1とApp2の間は双方向で通信、App3はApp1,2,4から通信という構成です。

つまり通信の送信を行うサービスと受信を行うサービスとしては以下になります

  • 送信:App1, App2, App4(App3は送信を行わない)
  • 受信:App1, App2, App3(App4は受信を行わない)

※App4は送信のみなので、厳密にはService4の作成は不要と思われますが、記事では作成されています。

上記のためサービス等の設計のみだと図に存在しない矢印である App4->App1、App4->App2の通信はできてしまいます。

そこを制御するために記事においては、App1はApp2からの通信のみ許可、App2はApp1からの通信のみ許可とするAuth Policy(IAMポリシー)を作成し、各サービスに関連付けています。

少し話がずれますが、アカウント間の通信の制御も可能であることが読み取れます(App1, App2, App3/4 で3つのアカウント間で通信。VPC LatticeのService Networkは後程登場するアカウント4で定義されている。)。

また、VPCのCIDRは被っていても良いです。App1(左上)とApp2(右上)のCIDRは10.0.0.0/16で被っています。これはリンクローカルアドレスを利用して実現しているようです。

To achieve this, VPC Lattice operates in the link-local address space in IPv4 and Unique Local Address space in IPv6, outside of the IP addresses you assign to your VPCs. The DNS records for VPC Lattice services resolve to IP addresses form 169.254.0.0/16 for IPv4, and fc00::/7 for IPv6. The VPC association with the service network provides connectivity to the link-local and unique local IP space.

ブログ記事の下部に通信の流れが記載されています。①、②で通信先のDNS名を元に名前解決を行い、③で返却されたリンクローカルアドレスを元に通信を行うことで実現していることが示されています。

(画像はAWS公式ブログより引用)

Service NetworkとServiceの関連付けについて

Service Networkに関連付けるServiceについては以下の図で示されています(AWS Account 4が増えており、こちらにService Networkが追加されています)。

緑色の矢印が関連付けを表しています。

(画像はAWS公式ブログより引用)

関連付けが行われているのはApp1, App2, App3の3つで、VPC LatticeのService間で受信側になっているServiceです。App4は送信のみなので関連付けは不要となっています。

Service NetworkとVPCの関連付けについて

Service NetworkとVPCの関連付けは下図の水色の矢印が該当します。

(画像はAWS公式ブログより引用)

関連付けが行われているのはApp1, App2, App4の3つのVPCで、VPC LatticeのService間で送信側になっているServiceが属するVPCです。App3のVPCは受信のみなので関連付けは不要となっています。

前回ブログ記事のアーキテクチャ見直し

上記までの理解をもとに前回のブログ記事で構築したアーキテクチャを見直します。

前提

以下が前回構築したアーキテクチャになります。AWSブログを参考に表現を少し修正しています。AWSブログと同様に緑の線がService Network-Serviceの関連付け、水色の線がService-VPCの関連付け、を表しています。

Serviceとしては以下が存在します。

  • EC2(Clinet):送信のみ行うService
  • EC2(Server):受信のみ行うService
  • Lambda:受信のみ行うService

またEC2はそれぞれ別のVPCに存在しています。

今は全てのService/VPCがService Networkに関連付けられている状態となっています。

関連付けの見直し

ドキュメント等から確認したService NetworkとVPC/Serviceの関連付けのルールとしては以下でした。

  • 受信を行いたいリソースはVPC Lattice Serviceを作成し、Service Networkと関連付ける
  • 送信を行いたいリソースは所属するVPCをService Networkと関連づける(送信のみであればVPC Lattice Serviceの作成不要)

上記を踏まえて見直すと下図の×の部分は不要ということになります。

  • EC2(Client)は受信を行わないので、Service自体不要(ServiceとService Networkの関連付けも不要)。
  • EC2(Server)は送信を行わないので、VPCとService Networkの関連付けは不要。

そのため見直すと冒頭に示した以下のアーキテクチャになります。

実際に変更して通信が成功するのか検証してみます。

実装変更

前回CDKで実装していたので該当箇所をコメントアウトするのみです。

github.com

具体的にはvpcLatticeConstruct.tsの以下2箇所をコメントアウトします。

  • EC2(Client)は受信を行わないので、Service自体不要(ServiceとService Networkの関連付けも不要)。 → Serviceの定義、Service-Service Networkの関連付けを削除
    /* EC2(Client)のServiceと、Service Networkの関連付けを全てコメントアウト
    const vpcLatticeServiceEc2 = new vpclattice.CfnService(this, 'VpcLatticeServiceEc2', {
      name: 'test-vpclattice-service-ec2',
      authType: 'NONE'
    })


    new vpclattice.CfnServiceNetworkServiceAssociation(this, 'VpcLatticeServiceNetworkServiceAssociationEc2', {
      serviceNetworkIdentifier: vpcLatticeServiceNetwork.attrId,
      serviceIdentifier: vpcLatticeServiceEc2.attrId
    })


    const vpcLatticeTargetGroupEc2 = new vpclattice.CfnTargetGroup(this, 'VpcLatticeTargetGroupEc2', {
      type: 'INSTANCE',
      targets: [{
        id: props.ec2Construct.bastionInstance.instanceId,
        port: 443
      }],
      config: {
        port: 443,
        protocol: 'HTTPS',
        vpcIdentifier: props.vpcConstruct.vpc.vpcId,
      },
      name: 'vpclattice-tg-ec2'
    })

    new vpclattice.CfnListener(this, 'VpcLatticeListenerEc2', {
      port: 443,
      protocol: 'HTTPS',
      serviceIdentifier: vpcLatticeServiceEc2.attrId,
      defaultAction: {
        forward: {
          targetGroups: [{
            targetGroupIdentifier: vpcLatticeTargetGroupEc2.attrId,
            weight: 100,
          }],
        },
      },
      name: 'vpclattice-listener-ec2'
    })
    */
  • EC2(Server)は送信を行わないので、VPCとService Networkの関連付けは不要。 → VPC-Service Networkの関連付けを削除。
    /* EC2(Server)の属するVPCと、Service Networkの関連付けをコメントアウト
    new vpclattice.CfnServiceNetworkVpcAssociation(this, 'VpcLatticeServiceNetworkSecondVpcAssociation', {
      vpcIdentifier: props.vpcConstruct.secondVpc.vpcId,
      serviceNetworkIdentifier: vpcLatticeServiceNetwork.attrId,
      securityGroupIds: [vpcLatticeServiceNetworkSecondSg.securityGroupId]
    })
    */

デプロイ

上記の状態でデプロイします。

Service NetworkのServiceの関連付けは2つになります(送信のみのEC2 Clientは関連付けない)。

またVPCの関連付けは1つのみになります(受信のみのEC2 Serverが所属するVPCは関連付けない)。

リクエストを投げてみる

では実際にEC2 Client -> EC2 Server/Lambdaにリクエストを投げてみます。

すると問題なく通りました。

設定内容として問題なさそうです。

で、VPC Latticeっていつ使うの?

VPC Latticeは使ってみたところ、なんとなく便利だしすごそうなのです。が、じゃあいつ使うか?となると、なかなか難しい気がします(あまりいいユースケースを思いついていない...

ここで先ほど確認したAWS公式ブログを見てみると1つのヒントが書いてありました。

Larger organizations usually have dedicated network or cloud administrator teams to manage network connectivity across multiple accounts and VPCs, and security teams to ensure that proper authentication, authorization, and encryption are enforced. This strategy can lead to a disjointed experience between admins and developers. Admins have to configure and maintain connectivity and security at the network layer, without having visibility into application dependencies and access patterns. In parallel, whether writing custom code or using a service mesh, developers need to reason about how the underlying network architecture affects their business logic.

大きな組織だとインフラ管理者と開発者が分断されており、ネットワーク管理者はアプリケーションを意識しないままネットワークを構築する必要がある、一方で開発者はネットワークがビジネスロジックに与える影響を推論する必要がある、というのが課題の一つと記載されています(これは確かに感じることはあります)。

Network or infrastructure admins can create and manage VPC Lattice service networks, configure service network level auth policies, and monitoring. Admins can choose to configure auth policies in a more generic, coarse-grained manner, to enforce foundational security controls. For example, as a network admin, you can write a coarse-grained policy that allows only authenticated requests from principals in your AWS Organization through the service network, and give service owners fine-grained control over their service-specific auth policies. Admins can associate VPCs and VPC Lattice services with one or more service networks. Alternatively, depending on the chosen operational model, admins can give service owners control to associate their VPCs and services by sharing VPC Lattice service networks using AWS RAM.

一方でVPC Latticeを使うとネットワーク管理者はService Networkレベルでアクセス許可のポリシーを設定し、開発者(サービスオーナー)ではServiceレベルでのポリシー設定を行うことができるとあります。

確かにアプリ開発者がServiceに閉じたネットワーク設定・アクセス許可設定をし、ネットワーク管理者がService Networkレベルの設定やServiceとService Networkの紐付けを行う、とすると責任分解が明確になりそうです。

VPC Latticeの動作仕様確認のところで見たドキュメントの図においても、Service NetworkとServiceでOwnerを分割できることが記載されています。

(画像はドキュメントからの引用)

従来の仕組みとは異なり、「Service間通信の設定」と「Serviceに閉じた通信の設定」の責務を分離し、後者をアプリ開発者(Service Owner)に委譲できるのが、VPC Latticeの1つのメリットと理解しました(Service OwnerがAWSVPC Latticeの知識をある程度持っていることが前提にはなるかと思います)。

他にいいユースケースがないかは考えてみたいと思います。

終わりに(AWS公式のWorkshopの紹介)

VPC LatticeのWorkShopがリリースされていました。サービス間通信の実装、通信制御の設定、アクセスログの設定と一通り試すことが可能です。

とりあえず触ってみたい方はこちらをやってみるのが良いかと思います。

catalog.us-east-1.prod.workshops.aws