TerraformでVPCピアリングを実装してみたよ
こんにちは、すずきです。
最近、あるタスクを達成するために、VPC1内のプライベートサブネットに設置したLambdaアプリケーションを、同一VPC内のパブリックサブネットに存在するNAT Gatewayを介して、VPC2内のパブリックサブネットにあるALB(接続先はプライベートサブネットのECS)のパブリックURLを利用するように設定しました。
しかし、ALBへのトラフィックはLambdaからのものだけで、以下の非機能要求を満たすために、VPCピアリングを介したプライベートな接続に変更することにしました。
コスト: NAT Gatewayを利用するよりもデータ転送量が少なくて済み、コスト削減につながる。
パフォーマンス: VPC間のネットワーク遅延を最小化でき、大量のデータ転送や低レイテンシを要求するアプリケーションに有効。
セキュリティ: 通信がAWS内のプライベートなネットワーク接続で行われるため、通信がインターネットに出るリスクを排除できる。
こちらの記事では、これらの要求を満たすためにTerraformを用いてVPCピアリングを実装する方法を紹介します。
実装
今回は以下のようなディレクトリ構成を採用しています。
各環境(dev, stg, prod)に対応するディレクトリと、再利用可能なモジュール(route_table, security_group, vpc_peering)を用意しています。
-- terraform-project/
-- environments/
-- dev/
-- backend.tf
-- main.tf
-- stg/
-- backend.tf
-- main.tf
-- prod/
-- backend.tf
-- main.tf
-- modules/
-- route_table/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README.md
-- security_group/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README.md
-- vpc_peering/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README.md
VPCピアリング
VPCピアリングはAWS内の2つのVPC間で直接的なネットワーク接続を作る機能です。
以下のvpc_peering/main.tfでは、SSMパラメータストアからVPCのIDを取得し、それらを用いてVPCピアリングを設定しています。
data "aws_ssm_parameter" "lambda_vpc_id" {
name = "/vpc/id/lambda"
}
data "aws_ssm_parameter" "ecs_vpc_id" {
name = "/vpc/id/ecs"
}
// 同一アカウント内でのVPCピアリングのため、接続と承認を一度に行う
resource "aws_vpc_peering_connection" "vpc_peering" {
vpc_id = data.aws_ssm_parameter.lambda_vpc_id.value
peer_vpc_id = data.aws_ssm_parameter.ecs_vpc_id.value
auto_accept = true
}
さらに、VPCピアリングのIDを他のモジュールで利用できるようにoutputs.tfで出力しています。
output "vpc_peering_connection_id" {
description = "Connection Id of VPC Peering"
value = aws_vpc_peering_connection.vpc_peering.id
}
ルートテーブル
次に、VPC内のネットワークトラフィックのルートを設定するルートテーブルを作成します。
ここでは、各VPCのCIDRブロックとVPCピアリングのIDを用いて、ピアリング接続を経由するルートを設定しています。
Lambdaが配置されているサブネットのルートテーブルをlambda_local_nat、ALBが配置されているサブネットのルートテーブルをecs_localとしています。
data "aws_ssm_parameter" "lambda_vpc_cidr" {
name = "/vpc/cidr/lambda"
}
data "aws_ssm_parameter" "ecs_vpc_cidr" {
name = "/vpc/cidr/ecs"
}
resource "aws_route_table" "lambda_local_nat" {
vpc_id = data.aws_ssm_parameter.lambda_vpc_id.value
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = data.aws_ssm_parameter.lambda_nat_gw_id.value
}
tags = {
Name = "lambda-vpc-private-local-nat-rtb"
}
}
// 既存ルートへの影響を考慮して分割
resource "aws_route" "peering_route" {
route_table_id = aws_route_table.lambda_local_nat.id
destination_cidr_block = data.aws_ssm_parameter.ecs_vpc_cidr.value
vpc_peering_connection_id = var.vpc_peering_connection_id
}
resource "aws_route_table" "ecs_local" {
vpc_id = data.aws_ssm_parameter.ecs_vpc_id.value
tags = {
Name = "ecs-vpc-private-local-rtb"
}
}
// 既存ルートへの影響を考慮して分割
resource "aws_route" "ecs_peering_route" {
route_table_id = aws_route_table.ecs_local.id
destination_cidr_block = data.aws_ssm_parameter.lambda_vpc_cidr.value
vpc_peering_connection_id = var.vpc_peering_connection_id
}
ルートテーブルモジュールでは、VPCピアリングのIDを入力として受け取るために、variables.tfで変数を定義しています。
variable "vpc_peering_connection_id" {
description = "Connection Id of VPC Peering"
type = string
}
セキュリティグループ
最後に、ALBのセキュリティグループを設定します。
これにより、特定のIP範囲からの通信だけを許可するというルールを作ることができます。
今回、Lambdaは2つのプライベートサブネットに存在するので、各サブネットのCIDRブロックを指定しています。
data "aws_ssm_parameter" "lambda_private_subnet_cidr1" {
name = "/subnet/private/cidr1/lambda"
}
data "aws_ssm_parameter" "lambda_private_subnet_cidr2" {
name = "/subnet/private/cidr2/lambda"
}
resource "aws_security_group_rule" "elb_sg_ingress_443_lambda" {
type = "ingress"
from_port = 443
to_port = 443
protocol = "tcp"
security_group_id = aws_security_group.elb_sg.id
cidr_blocks = [data.aws_ssm_parameter.lambda_private_subnet_cidr1.value, data.aws_ssm_parameter.lambda_private_subnet_cidr2.value]
}
プライベートDNSと証明書の設定
Terraformの実装は以上なのですが(あとはterraform applyするだけ)、VPCピアリングはプライベートな接続を扱うため、Lambdaのアプリケーション内でApplication Load Balancer(ALB)の接続先をパブリックURLからプライベートDNSに変更する必要があります。
加えて、HTTPS接続を行うためには、AWS Certificate Manager(ACM)のPrivate Certificate Authority(CA)を用いてプライベート証明書を作成し、その証明書をALBのリスナーに割り当てる作業が必要になります。
以下が設定手順です。
1.Private CAの作成
AWS Certificate Manager(ACM)のダッシュボードから「Private CAs」を選択し、「Create CA」をクリックします。
Root CAまたはSubordinate CAのタイプを選択し、CAの詳細を入力します。
その後、「Next」をクリックし、設定を確認します。
問題がなければ、「Confirm and create」をクリックして、Private CAを作成します。
2.プライベート証明書の発行
Private CAが作成されたら、「Certificate Manager」ダッシュボードに戻り、「Get started」をクリックします。
証明書の設定画面で、「Private」を選択し、「Request a certificate」をクリックします。
プライベートDNS名を含むドメイン名を入力し、詳細を設定します。
設定が完了したら、「Confirm and request」をクリックします。
3.ALBのリスナーに証明書を割り当てる
ALBの設定画面に移動し、対象のリスナーを選択します。
「Actions」ドロップダウンから「Change certificate」を選択し、作成したプライベート証明書を選択します。
採用情報
この記事が気に入ったらサポートをしてみませんか?