0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS PrivateLink: 従来パターン vs 新しいパターンを比較

Posted at

はじめに

AWS PrivateLink(以下 PrivateLink)が進化し、NLB やGateway Load Balancer なしで、VPC リソースへの直接的なプライベートアクセスが可能になったというアップデートが 2024 年の AWS re:Invent 2024 で発表されましたが、その比較を今更ですがしていきましょうという内容です。

主要な違い

項目 従来パターン(NLB使用) 新しいパターン(VPCリソース直接アクセス)
必要なコンポーネント エンドポイントサービス + NLB/GLB リソースゲートウェイ + リソース設定
ロードバランサー 必須(NLB または GLB) 不要
対象リソース 負荷分散可能なサービス 単一リソース(DB、IP、ドメイン等)
アクセス方法 インターフェースVPCエンドポイント リソースVPCエンドポイント

詳細比較

アーキテクチャ構成

従来パターン(NLB使用)

[Consumer VPC]
    ↓ (Interface VPC Endpoint)
[AWS PrivateLink]
    ↓
[Provider VPC]
    ↓ (Endpoint Service)
[Network Load Balancer]
    ↓
[Target Group]
    ↓
[バックエンドサービス/リソース]

新しいパターン(直接アクセス)

[Consumer VPC]
    ↓ (Resource VPC Endpoint)
[AWS PrivateLink]
    ↓
[Provider VPC]
    ↓ (Resource Gateway)
[Resource Configuration]
    ↓
[VPCリソース(RDS、IP、ドメイン等)]

設定手順

従来パターンの設定手順

プロバイダー側:

  1. Network Load BalancerまたはGateway Load Balancerの作成
  2. ターゲットグループの設定
  3. エンドポイントサービスの作成(ロードバランサーを指定)
  4. 接続許可の設定

コンシューマー側:

  1. インターフェースVPCエンドポイントの作成
  2. サービス名の指定
  3. セキュリティグループの設定

新しいパターンの設定手順

プロバイダー側:

  1. リソースゲートウェイの作成
  2. リソース設定の作成(単一リソースまたはグループ)
  3. AWS RAMでのリソース共有設定

コンシューマー側:

  1. リソースVPCエンドポイントの作成
  2. 共有リソースの指定
  3. セキュリティグループの設定

適用ユースケース

従来パターン 新しいパターンが
- 負荷分散が必要なサービス
- 高可用性が必要なアプリケーション
- 従来のSaaS
- 単一リソースへの直接アクセス
- 負荷分散不要なサービス
- リソース粒度での共有が必要

技術的特徴

特徴 従来パターン 新しいパターン
接続方向 単方向 単方向
プロトコル TCP/UDP(NLB)、任意(GLB) TCP/UDP
DNS解決 サポート サポート
セキュリティ セキュリティグループ、NACLs セキュリティグループ、NACLs
可用性 NLB/GLBによる冗長化 リソース自体の冗長化に依存

コスト比較

従来パターン 新しいパターン
- VPCエンドポイント料金(時間単位)
- データ処理料金(GB単位)
- Network Load Balancer料金(時間単位 + LCU)
- データ転送料金
- VPCエンドポイント料金(時間単位)
- データ処理料金(GB単位)
- データ転送料金

コストメリット: NLB料金が不要になることで、シンプルなリソースアクセスにおいてコスト削減が期待できます。

可用性とスケーラビリティ

従来パターン 新しいパターン
- 可用性: NLB/GLBの冗長化機能を活用
- スケーラビリティ: 自動スケーリング、ターゲット追加/削除
- 可用性: リソース自体の冗長化設計に依存
- スケーラビリティ: リソース固有のスケーリング方法

運用・管理

従来パターン 新しいパターン
- NLBのヘルスチェック監視
- ターゲットグループの管理
- ロードバランサーメトリクスの監視
- リソースゲートウェイの監視
- リソース設定の管理
- AWS RAMを通じた共有管理

選択指針

従来パターンを選ぶべき場合 新しいパターンを選ぶべき場合
- 複数のバックエンドサービスへの負荷分散が必要
- 既存のPrivateLinkベースのアーキテクチャを維持したい
- 高可用性とスケーラビリティが最重要
- データベースや特定リソースへの直接アクセスが必要
- 負荷分散機能が不要
よりシンプルなアーキテクチャとコスト削減を重視
- 細かいリソース単位での共有制御が必要

軽く体験してみる

構成は以下のクラスメソッドさんの「試してみた」にあるシングルアカウントの構成で実施します。(複数アカウントは所持していないので、マルチアカウントでのアクセスはごめんなさい)

ポイントは、Resource gateway と Resource Config で後他は基本なのでそれ程難しくなさそうですね。

今回は、AWS CDK で作成しました。なお、あまりコストをかけずやりたかったので、NATGateway などは配置していない点ご了承下さい。

lib/privatelink-vpc-resources-stack.ts
lib/privatelink-vpc-resources-stack.ts
import * as cdk from 'aws-cdk-lib';
import { TcpRetryEvent } from 'aws-cdk-lib/aws-appmesh';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as vpclattice from 'aws-cdk-lib/aws-vpclattice';
import { Construct } from 'constructs';

export class PrivateLinkVpcResourcesStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // ==============================================
    // プロバイダー側(リソース提供側)の設定
    // ==============================================
    
    // プロバイダーVPCの作成
    const providerVpc = new ec2.Vpc(this, 'ProviderVpc', {
      vpcName: 'PrivateLink-Provider-VPC',
      ipAddresses: ec2.IpAddresses.cidr('10.1.0.0/16'),
      maxAzs: 2,
      natGateways: 0,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'Private',
          subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
        }
      ]
    });

    // プロバイダー側のセキュリティグループ
    const providerSecurityGroup = new ec2.SecurityGroup(this, 'ProviderSecurityGroup', {
      vpc: providerVpc,
      description: 'Security group for provider resources',
    });

    // プロバイダー側EC2インスタンス(共有リソース)
    const providerInstance = new ec2.Instance(this, 'ProviderInstance', {
      vpc: providerVpc,
      vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: ec2.MachineImage.latestAmazonLinux2023(),
      securityGroup: providerSecurityGroup,
      userData: ec2.UserData.custom(`#!/bin/bash
sudo dnf update -y
sudo dnf install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
`),
    });

    // リソースゲートウェイ用のセキュリティグループ
    const resourceGatewaySecurityGroup = new ec2.SecurityGroup(this, 'ResourceGatewaySecurityGroup', {
      vpc: providerVpc,
      description: 'Security group for Resource Gateway',
    });

    // コンシューマーからのアクセスを許可
    resourceGatewaySecurityGroup.addIngressRule(
      ec2.Peer.ipv4('10.0.0.0/16'),
      ec2.Port.tcp(80),
    );

    // リソースゲートウェイからのアクセスを許可
    providerSecurityGroup.addIngressRule(
      resourceGatewaySecurityGroup,
      ec2.Port.tcp(80),
    );

    // リソースゲートウェイの作成
    const resourceGateway = new vpclattice.CfnResourceGateway(this, 'ResourceGateway', {
      name: 'test-resource-gateway',
      vpcIdentifier: providerVpc.vpcId,
      subnetIds: providerVpc.isolatedSubnets.map(subnet => subnet.subnetId),
      securityGroupIds: [resourceGatewaySecurityGroup.securityGroupId],
      ipAddressType: 'IPV4'
    });

    // リソース設定の作成(EC2インスタンスをリソースとして指定)
    const resourceConfiguration = new vpclattice.CfnResourceConfiguration(this, 'ResourceConfiguration', {
      name: 'ec2-b-resource-config',
      resourceConfigurationType: 'SINGLE',
      resourceConfigurationDefinition: {
        ipResource: providerInstance.instancePrivateIp
      },
      resourceGatewayId: resourceGateway.attrId
    });

    // ==============================================
    // コンシューマー側(リソース利用側)の設定
    // ==============================================

    // コンシューマーVPCの作成
    const consumerVpc = new ec2.Vpc(this, 'ConsumerVpc', {
      vpcName: 'PrivateLink-Consumer-VPC',
      ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
      maxAzs: 2,
      natGateways: 0,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'Public',
          subnetType: ec2.SubnetType.PUBLIC,
        }
      ]
    });

    // コンシューマー側のセキュリティグループ
    const consumerSecurityGroup = new ec2.SecurityGroup(this, 'ConsumerSecurityGroup', {
      vpc: consumerVpc,
      description: 'Security group for consumer resources',
    });

    // SessionManager用IAMロールの作成
    const sessionManagerRole = new iam.Role(this, 'SessionManagerRole', {
      assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore')
      ]
    });

    // コンシューマー側EC2インスタンス
    const consumerInstance = new ec2.Instance(this, 'ConsumerInstance', {
      vpc: consumerVpc,
      vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: ec2.MachineImage.latestAmazonLinux2023(),
      securityGroup: consumerSecurityGroup,
      role: sessionManagerRole,
    });

    // VPCエンドポイント用のセキュリティグループ
    const vpcEndpointSecurityGroup = new ec2.SecurityGroup(this, 'VpcEndpointSecurityGroup', {
      vpc: consumerVpc,
      description: 'Security group for VPC Endpoint to access PrivateLink resources',
    });

    // コンシューマーインスタンスからのアクセスを許可
    vpcEndpointSecurityGroup.addIngressRule(
      consumerSecurityGroup,
      ec2.Port.tcp(80),
    );

    // リソースVPCエンドポイントの作成
    const resourceVpcEndpoint = new ec2.CfnVPCEndpoint(this, 'ResourceVpcEndpoint', {
      vpcId: consumerVpc.vpcId,
      vpcEndpointType: 'Resource',
      subnetIds: consumerVpc.publicSubnets.map(subnet => subnet.subnetId),
      securityGroupIds: [vpcEndpointSecurityGroup.securityGroupId],
      resourceConfigurationArn: resourceConfiguration.attrArn,
      policyDocument: {
        Version: '2012-10-17',
        Statement: [
          {
            Effect: 'Allow',
            Principal: '*',
            Action: [
              'vpc-lattice:Invoke'
            ],
            Resource: '*'
          }
        ]
      }
    });

  }
}

AWS マネージメントコンソールから、VPC > エンドポイント > vpce-XXX の VPC エンドポイントを開き、IPv4 アドレスをメモしておき、curl でアクセスできると成功です。

スクリーンショット 2025-09-15 20.16.55.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?