VPC LatticeをTerraformで構築してVPC間接続してみた
こんにちは、ゲームソリューション部のsoraです。
今回は、VPC LatticeをTerraformで構築してVPC間接続してみたことについて書いていきます。
構成
以下のような構成をTerraformで構築していきます。
クライアント側はLatticeサービスネットワークへのVPCの関連付けをして、サービス側はサービスの関連付けでLatticeサービスを紐づけて、そのLatticeターゲットグループとしてECSタスクのIPアドレスを指定します。

Latticeの構成要素がなかなか理解できなかったため、AWSマネジメントコンソールの項目ベースで今回の構成のLattice部分を整理した図は以下です。

通信の流れは以下です。
ユーザーからブラウザで文字列を含めたリクエストを送付して、Latticeを経由して別のVPCのECSまで到達して、レスポンスを返す形です。
ユーザー (ブラウザ)
↓ http://<クライアント側のECSのPublic IP>:8080/forward?message=<任意の文字列>
クライアント側のECS (VPC-A,port 8080)
↓ http://provider-svc-xxx.vpc-lattice-svcs.ap-northeast-1.on.aws/process?message=hello
Lattice (Listener port 80)
↓ Target Groupにルーティング
サービス側のECS (VPC-B,port 8080) ※受け取った文字列に`response: `を追加してユーザーに返却
Terraformでの構築
AWS部分をTerraformで構築します。
ECS上で動くイメージも作成しましたが、簡易にレスポンスを返したりフォワードするだけなため割愛します。
Terraformコードの中でLatticeに関する部分を抜粋して説明していきます。
※説明の都合上、コードの順番は前後します。
サービスネットワークの作成・VPCの関連付け・サービスの関連付け
Lattice利用時にハブとなるリソースです。
サービスネットワークを作成して、クライアント側のVPCの関連付け、サービス側のサービスの関連付けを行います。
# サービスネットワークの作成
resource "aws_vpclattice_service_network" "main" {
name = "ecs-lattice-service-network"
auth_type = "NONE" # 今回は認証なし(AWS_IAMでIAM認証も設定可能)
tags = { Name = "ecs-lattice-service-network" }
}
## クライアント側のVPCをサービスネットワークへVPC関連付け
resource "aws_vpclattice_service_network_vpc_association" "consumer_vpc_assoc" {
service_network_identifier = aws_vpclattice_service_network.main.id
vpc_identifier = aws_vpc.vpc_a.id
security_group_ids = [aws_security_group.lattice_sg_a.id]
}
## サービス側のLatticeサービスをサービスネットワークへサービスの関連付け
resource "aws_vpclattice_service_network_service_association" "provider_assoc" {
service_identifier = aws_vpclattice_service.provider.id
service_network_identifier = aws_vpclattice_service_network.main.id
}
Latticeサービスの作成
サービス側のECSをLatticeと接続するために、Latticeサービスを作成します。
今回の構成では、クライアント側のECSからLatticeサービスへHTTPで通信して、Latticeターゲットグループに設定するサービス側のECSへは8080ポートへ通信する形で設定しています。
ちなみに、今回はECSタスクを1つにしましたが複数のECSタスクがあってターゲットが複数ある場合、Latticeターゲットグループにおけるルーティングアルゴリズムはラウンドロビンです。
## Latticeサービスの作成
resource "aws_vpclattice_service" "provider" {
name = "provider-svc"
auth_type = "NONE"
}
## Latticeターゲットグループの作成
resource "aws_vpclattice_target_group" "provider_tg" {
name = "provider-tg"
type = "IP" # ECSの場合はIP
config {
port = 8080 # ターゲット(サービス側のECS)のポート
protocol = "HTTP"
vpc_identifier = aws_vpc.vpc_b.id
ip_address_type = "IPV4"
health_check {
enabled = true
path = "/health"
protocol = "HTTP"
port = 8080
healthy_threshold_count = 2
unhealthy_threshold_count = 2
matcher {
value = "200"
}
}
}
}
## リスナーの設定
resource "aws_vpclattice_listener" "http" {
name = "http"
port = 80 # Latticeサービスが受け付けるポート
protocol = "HTTP"
service_identifier = aws_vpclattice_service.provider.id
default_action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.provider_tg.id
weight = 1
}
}
}
}
ECSとLatticeの統合
ECSタスクをLatticeターゲットグループに登録する設定を入れます。
ECSサービスにて、Latticeターゲットグループのターゲット自動登録設定を入れることで、ターゲットとなるECSタスクが再起動や増減したときもLatticeターゲットグループに自動反映されます。
Latticeのマネージドプレフィックスリストについては以下ドキュメントに記載があります。
## Latticeターゲットグループのターゲット自動登録設定
### ECSタスクロールには、Latticeターゲットグループへの追加が可能な権限が必要
resource "aws_ecs_service" "provider" {
name = "provider"
cluster = aws_ecs_cluster.provider.id
task_definition = aws_ecs_task_definition.provider.arn
desired_count = 1
launch_type = "FARGATE"
network_configuration {
subnets = [aws_subnet.private_b1.id, aws_subnet.private_b2.id]
security_groups = [aws_security_group.provider_sg.id]
assign_public_ip = false
}
# Latticeターゲットグループへの自動登録
vpc_lattice_configurations {
target_group_arn = aws_vpclattice_target_group.provider_tg.arn
port_name = "http" #portMappingsのnameと一致させる
role_arn = aws_iam_role.ecs_vpc_lattice_role.arn
}
}
## ECSがLatticeからの通信を受けることができるようにSGを設定
### マネージドプレフィックスリストを使用
data "aws_ec2_managed_prefix_list" "vpc_lattice" {
name = "com.amazonaws.${data.aws_region.current.name}.vpc-lattice"
}
resource "aws_security_group" "provider_sg" {
name = "provider-ecs-sg"
description = "Security group for Provider ECS"
vpc_id = aws_vpc.vpc_b.id
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
prefix_list_ids = [data.aws_ec2_managed_prefix_list.vpc_lattice.id]
description = "Allow from VPC Lattice"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "provider-ecs-sg" }
}
作成したリソースの確認
作成したリソースをAWSマネジメントコンソールで確認していきます。
まずサービスネットワークを確認すると、想定通り、クライアント側のVPCの関連付けとサービス側のLatticeサービスのサービスの関連付けがそれぞれ1になっています。

次にLatticeサービスを見ていきます。
ルーティングを見ると、リスナーがHTTP:80でLatticeターゲットグループであるprovider-tgに転送されるようになっています。

Latticeターゲットグループを見てみると、登録済みターゲットとしてECSタスクのIPアドレスが登録されていました。
ちなみに、自動の追加設定も入れているため、ECSサービスでタスクを2に増やすと、登録済みターゲットも自動で2つになります。

動作確認
ブラウザ上でhttp://<クライアント側のECSのPublic IP>:8080/forward?message=helloにアクセスしてみると、以下のように文字列を追加してresponse: helloと返ってきました。

最後に
今回は、VPC LatticeをTerraformで構築してVPC間接続してみたことを記事にしました。
どなたかの参考になると幸いです。







