🌐
[Terraform] Fargate v1.4で必要なVPC endpoint設定
ECS/Fargateで、コンテナーで動くWebアプリケーションのインフラを構築したい場合で、よくあるのはセキュリティーを考慮して、Fargateはプライベートサブネット内に置きたいというケースがあると思います。
ただプライベートサブネットにあるFargateでも、ECRなど別リソースと通信したい場合に手っ取り早くNAT gatewayを使うでもいいですが、コスト面でNAT gatewayはよろしくないので、比較的低コストなVPC endpointを使う方法があります。
今回のユースケース
- NAT gatewayを使わずにECRからDockerイメージをpullしたい
- Fargate上で、AWS Systems Manager パラメータストア経由で環境変数を使用したい
- コンテナー内のログをCloudWatchに送信したい
Terraformによる設定
- S3は、Gateway型なので、ルートテーブルとの紐付けが必要
- それ以外は、Interface型なので、それぞれのエンドポイント用のセキュリティグループが必要
- 前提として、VPC, private subnet, route tableなど各種設定も必要
必要なエンドポイント
s3
ecr.dkr
ecr.api
logs
ssm
注:var.xxx
の部分は適時自身の環境で置き換えてもらえますと🙏🏻
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.app_network.id
service_name = "com.amazonaws.ap-northeast-1.s3"
vpc_endpoint_type = "Gateway"
}
resource "aws_vpc_endpoint_route_table_association" "private_s3" {
count = length(aws_subnet.app_private)
vpc_endpoint_id = aws_vpc_endpoint.s3.id
route_table_id = aws_route_table.app_private[count.index].id
}
resource "aws_security_group" "vpc_endpoint" {
name = "vpc_endpoint_sg"
vpc_id = aws_vpc.app_network.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.app_network.cidr_block]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.app_network.cidr_block]
}
}
resource "aws_vpc_endpoint" "ecr_dkr" {
vpc_id = aws_vpc.app_network.id
service_name = "com.amazonaws.ap-northeast-1.ecr.dkr"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.app_private[*].id
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
}
resource "aws_vpc_endpoint" "ecr_api" {
vpc_id = aws_vpc.app_network.id
service_name = "com.amazonaws.ap-northeast-1.ecr.api"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.app_private[*].id
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
}
resource "aws_vpc_endpoint" "logs" {
vpc_id = aws_vpc.app_network.id
service_name = "com.amazonaws.ap-northeast-1.logs"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.app_private[*].id
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
}
resource "aws_vpc_endpoint" "ssm" {
vpc_id = aws_vpc.app_network.id
service_name = "com.amazonaws.ap-northeast-1.ssm"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.app_private[*].id
security_group_ids = [aws_security_group.vpc_endpoint.id]
private_dns_enabled = true
}
resource "aws_vpc" "app_network" {
cidr_block = var.vpc.vpc
enable_dns_hostnames = true
enable_dns_support = true
instance_tenancy = "default"
}
resource "aws_subnet" "app_private" {
count = length(var.vpc.private_subnets)
vpc_id = aws_vpc.app_network.id
cidr_block = var.vpc.private_subnets[count.index].cidr_block
availability_zone = var.vpc.private_subnets[count.index].availability_zone
tags = {
Name = "${var.terraform_environment}_private_${var.vpc.private_subnets[count.index].name}"
}
}
resource "aws_route_table" "app_private" {
count = length(aws_subnet.app_private)
vpc_id = aws_vpc.app_network.id
}
resource "aws_route_table_association" "app_private" {
count = length(aws_subnet.app_private)
subnet_id = aws_subnet.app_private[count.index].id
route_table_id = aws_route_table.app_private[count.index].id
}
必要な設定は以上。
Discussion