mazyu36の日記

クラウドのことを中心に色々と。All posts are my own.

CDK で CloudFront VPC Origin を設定する

CDK v2.180.0 で CloudFront VPC Origin の L2 Construct がリリースされました。

github.com

以下の記事でAWS CDK で セルフホスト Langfuse を実装していましたが、早速 VPC Originを導入してみたので使い方を紹介します。

mazyu36.hatenablog.com

VPC Origin の L2 Construct の使い方の紹介が中心で、Langfuse の話はほぼ出てきません。

目次

アーキテクチャ

VPC Origin 導入後のLangfuseのアーキテクチャです。

前回のアーキテクチャからの変更点は以下です。

  • クライアントのリクエストは CloudFront が受付
  • ALB は VPC Origin 導入に伴い internal に変更。今回はCloudFront -> ALB(internal) に HTTP(ポート80)でアクセスする構成。

実装内容

全量は以下にあります。

以下ポイントのみ記載します。

github.com

ALBやリスナーを作成

ALBをinternalで作成し、リスナーはHTTPを使用するように設定します。

const alb = new elbv2.ApplicationLoadBalancer(this, 'ApplicationLoadBalancer', {
  vpc,
  vpcSubnets: vpc.selectSubnets({ subnets: vpc.privateSubnets }),  // VPC Originによりプライベートサブネットに配置が可能
  internetFacing: false,  // internal に設定
});

// HTTPを設定
const protocol = elbv2.ApplicationProtocol.HTTP;
const listener = alb.addListener('Listener', {
  protocol,
  open: false,
  defaultAction: elbv2.ListenerAction.fixedResponse(400),
});

Distribution および VPC Origin を作成

CloudFront 関連のリソースを作成します。VPC Orignは他のオリジンと同様にヘルパークラスが用意されているため、簡単に設定することができます。

VPC Origin のプロパティは最低限しか設定していません。他のプロパティはCDKのドキュメントをご参照ください。

const distribution = new cloudfront.Distribution(this, 'Distribution', {
  // omit
  defaultBehavior: {
    // VPC Origin (ALB) を設定
    origin: origins.VpcOrigin.withApplicationLoadBalancer(alb, {
      protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
      httpPort: 80,
    }),
    //omit
  },
  });

VPC Origin -> ALB のアクセス設定

ここが一癖あるポイントです。ALBのSGのインバウンドルール設定として以下が考えられます。

  1. CloudFront マネージドプレフィックスリストからのアクセスを許可する
  2. VPC Origin のSGからのアクセスを許可する

いずれも現状 CloudFormation では設定のための値を直接取得する手段がありません。そのためカスタムリソースを使うか、直接定義する必要があります。

CDKのドキュメントではカスタムリソースを使用し 2 を実現する方法が記載されています(コントリビューターの方に感謝)。

// VPC Origin の SG を取得するカスタムリソース
const getSg = new cr.AwsCustomResource(this, 'GetSecurityGroup', {
  onCreate: {
    service: 'ec2',
    action: 'describeSecurityGroups',
    parameters: {
      Filters: [
        { Name: 'vpc-id', Values: [vpc.vpcId] },
        { Name: 'group-name', Values: ['CloudFront-VPCOrigins-Service-SG'] },
      ],
    },
    physicalResourceId: cr.PhysicalResourceId.of('CloudFront-VPCOrigins-Service-SG'),
  },
  policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
    resources: ['*'],
  }),
});

// CloudFront Distributionが生成されるのを待つために依存関係を定義
getSg.node.addDependency(distribution);

// カスタムリソースで取得したSG の ID を元に VPC Origin の SG を  import
const sgVpcOrigins = ec2.SecurityGroup.fromSecurityGroupId(
  this,
  'VpcOriginsSecurityGroup',
  getSg.getResponseField('SecurityGroups.0.GroupId'),
);

// ALB の リスナーで VPC Origin の SG からのアクセスを許可
listener.connections.allowDefaultPortFrom(sgVpcOrigins);

これで設定は完了です。CloudFront 経由で ALB(internal) にアクセス可能となります。

まとめ

L2 Construct により VPC Origin が非常に簡単に設定できるようになりました。ぜひ使ってみてください。