如何为专用于 Fargate 任务的一组私有和 public 子网重用弹性 IP
How to reuse Elastic IPs for a set of private and public subnets dedicated to Fargate tasks
我得到以下设置来创建 Fargate 设置的网络要求:
resource "aws_vpc" "main" {
cidr_block = var.cidr
tags = {
Environment = var.environment
DO_NOT_DELETE = true
CreatedBy = "terraform"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
data "aws_availability_zones" "region_azs" {
state = "available"
}
locals {
az_count = length(data.aws_availability_zones.region_azs.names)
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index)
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
tags = {
Name = "public-subnet-${data.aws_availability_zones.region_azs.names[count.index]}"
AvailabilityZone = data.aws_availability_zones.region_azs.names[count.index]
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "private"
DO_NOT_DELETE = true
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index + local.az_count )
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
map_public_ip_on_launch = true
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
DO_NOT_DELETE = true
Type = "public"
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "public"
}
}
resource "aws_route" "public" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
resource "aws_route_table_association" "public" {
count = local.az_count
subnet_id = element(aws_subnet.public.*.id, count.index)
route_table_id = aws_route_table.public.id
}
resource "aws_nat_gateway" "main" {
count = local.az_count
allocation_id = element(aws_eip.nat.*.id, count.index)
subnet_id = element(aws_subnet.public.*.id, count.index)
depends_on = [aws_internet_gateway.main]
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_eip" "nat" {
count = local.az_count
vpc = true
tags = {
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_route_table" "private" {
count = local.az_count
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Type = "private"
Vpc = aws_vpc.main.id
}
}
resource "aws_route" "private" {
count = local.az_count
route_table_id = element(aws_route_table.private.*.id, count.index)
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = element(aws_nat_gateway.main.*.id, count.index)
}
resource "aws_route_table_association" "private" {
count = local.az_count
subnet_id = element(aws_subnet.private.*.id, count.index)
route_table_id = element(aws_route_table.private.*.id, count.index)
}
resource "aws_security_group" "alb" {
name = "${var.resources_name_prefix}-alb-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_security_group" "ecs_tasks" {
name = "${var.resources_name_prefix}-ecs-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 3000
to_port = 3000
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
这对几个可用性区域来说效果很好,但现在我正在为每个区域的每个 AZ 中的 运行 任务动态创建子网,我正在达到每个区域的弹性 IP 的限制。
所以我在尝试创建堆栈时遇到了这个错误:
Error creating EIP: AddressLimitExceeded: The maximum number of addresses has been reached.
status code: 400
我想知道以下部分:
resource "aws_nat_gateway" "main" {
count = local.az_count
allocation_id = element(aws_eip.nat.*.id, count.index)
subnet_id = element(aws_subnet.public.*.id, count.index)
depends_on = [aws_internet_gateway.main]
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_eip" "nat" {
count = local.az_count
vpc = true
tags = {
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
如果可行,可以构建为在内部使用单个 EIP 和路由。
我稍微修改了你的代码,但还是一团糟。例如,所有私有子网都称为“public”。它现在创建了两个 NAT。显然,如果您有子网,比方说,6 个 AZ,将有一些 cross-AZ 流量到达这些 NAT。
或者,不要创建跨越这么多可用区的 VPC。通常只有 two-three 个 AZ 用于 VPC。拥有更多,并不是真正需要的。
最后,如果您想保留您的原始设置,您可以请求 AWS 支持为您提供更多的 EIP。
resource "aws_vpc" "main" {
cidr_block = var.cidr
tags = {
Environment = var.environment
DO_NOT_DELETE = true
CreatedBy = "terraform"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
data "aws_availability_zones" "region_azs" {
state = "available"
}
locals {
az_count = length(data.aws_availability_zones.region_azs.names)
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index)
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
tags = {
Name = "private-subnet-${data.aws_availability_zones.region_azs.names[count.index]}"
AvailabilityZone = data.aws_availability_zones.region_azs.names[count.index]
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "private"
DO_NOT_DELETE = true
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index + local.az_count )
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${data.aws_availability_zones.region_azs.names[count.index]}"
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
DO_NOT_DELETE = true
Type = "public"
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "public"
}
}
resource "aws_route" "public" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
resource "aws_route_table_association" "public" {
count = local.az_count
subnet_id = element(aws_subnet.public.*.id, count.index)
route_table_id = aws_route_table.public.id
}
resource "aws_nat_gateway" "main" {
count = 2
allocation_id = element(aws_eip.nat.*.id, count.index)
subnet_id = element(aws_subnet.public.*.id, count.index)
depends_on = [aws_internet_gateway.main]
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_eip" "nat" {
count = 2
vpc = true
tags = {
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_route_table" "private" {
count = local.az_count
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Type = "private"
Vpc = aws_vpc.main.id
}
}
resource "aws_route" "private" {
count = local.az_count
route_table_id = element(aws_route_table.private.*.id, count.index)
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = element(aws_nat_gateway.main.*.id, count.index)
}
resource "aws_route_table_association" "private" {
count = local.az_count
subnet_id = element(aws_subnet.private.*.id, count.index)
route_table_id = element(aws_route_table.private.*.id, count.index)
}
resource "aws_security_group" "alb" {
name = "${var.resources_name_prefix}-alb-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_security_group" "ecs_tasks" {
name = "${var.resources_name_prefix}-ecs-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 3000
to_port = 3000
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
我得到以下设置来创建 Fargate 设置的网络要求:
resource "aws_vpc" "main" {
cidr_block = var.cidr
tags = {
Environment = var.environment
DO_NOT_DELETE = true
CreatedBy = "terraform"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
data "aws_availability_zones" "region_azs" {
state = "available"
}
locals {
az_count = length(data.aws_availability_zones.region_azs.names)
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index)
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
tags = {
Name = "public-subnet-${data.aws_availability_zones.region_azs.names[count.index]}"
AvailabilityZone = data.aws_availability_zones.region_azs.names[count.index]
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "private"
DO_NOT_DELETE = true
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index + local.az_count )
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
map_public_ip_on_launch = true
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
DO_NOT_DELETE = true
Type = "public"
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "public"
}
}
resource "aws_route" "public" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
resource "aws_route_table_association" "public" {
count = local.az_count
subnet_id = element(aws_subnet.public.*.id, count.index)
route_table_id = aws_route_table.public.id
}
resource "aws_nat_gateway" "main" {
count = local.az_count
allocation_id = element(aws_eip.nat.*.id, count.index)
subnet_id = element(aws_subnet.public.*.id, count.index)
depends_on = [aws_internet_gateway.main]
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_eip" "nat" {
count = local.az_count
vpc = true
tags = {
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_route_table" "private" {
count = local.az_count
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Type = "private"
Vpc = aws_vpc.main.id
}
}
resource "aws_route" "private" {
count = local.az_count
route_table_id = element(aws_route_table.private.*.id, count.index)
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = element(aws_nat_gateway.main.*.id, count.index)
}
resource "aws_route_table_association" "private" {
count = local.az_count
subnet_id = element(aws_subnet.private.*.id, count.index)
route_table_id = element(aws_route_table.private.*.id, count.index)
}
resource "aws_security_group" "alb" {
name = "${var.resources_name_prefix}-alb-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_security_group" "ecs_tasks" {
name = "${var.resources_name_prefix}-ecs-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 3000
to_port = 3000
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
这对几个可用性区域来说效果很好,但现在我正在为每个区域的每个 AZ 中的 运行 任务动态创建子网,我正在达到每个区域的弹性 IP 的限制。
所以我在尝试创建堆栈时遇到了这个错误:
Error creating EIP: AddressLimitExceeded: The maximum number of addresses has been reached.
status code: 400
我想知道以下部分:
resource "aws_nat_gateway" "main" {
count = local.az_count
allocation_id = element(aws_eip.nat.*.id, count.index)
subnet_id = element(aws_subnet.public.*.id, count.index)
depends_on = [aws_internet_gateway.main]
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_eip" "nat" {
count = local.az_count
vpc = true
tags = {
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
如果可行,可以构建为在内部使用单个 EIP 和路由。
我稍微修改了你的代码,但还是一团糟。例如,所有私有子网都称为“public”。它现在创建了两个 NAT。显然,如果您有子网,比方说,6 个 AZ,将有一些 cross-AZ 流量到达这些 NAT。
或者,不要创建跨越这么多可用区的 VPC。通常只有 two-three 个 AZ 用于 VPC。拥有更多,并不是真正需要的。
最后,如果您想保留您的原始设置,您可以请求 AWS 支持为您提供更多的 EIP。
resource "aws_vpc" "main" {
cidr_block = var.cidr
tags = {
Environment = var.environment
DO_NOT_DELETE = true
CreatedBy = "terraform"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
data "aws_availability_zones" "region_azs" {
state = "available"
}
locals {
az_count = length(data.aws_availability_zones.region_azs.names)
}
resource "aws_subnet" "private" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index)
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
tags = {
Name = "private-subnet-${data.aws_availability_zones.region_azs.names[count.index]}"
AvailabilityZone = data.aws_availability_zones.region_azs.names[count.index]
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "private"
DO_NOT_DELETE = true
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index + local.az_count )
availability_zone = data.aws_availability_zones.region_azs.names[count.index]
count = local.az_count
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${data.aws_availability_zones.region_azs.names[count.index]}"
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
DO_NOT_DELETE = true
Type = "public"
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
Type = "public"
}
}
resource "aws_route" "public" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
resource "aws_route_table_association" "public" {
count = local.az_count
subnet_id = element(aws_subnet.public.*.id, count.index)
route_table_id = aws_route_table.public.id
}
resource "aws_nat_gateway" "main" {
count = 2
allocation_id = element(aws_eip.nat.*.id, count.index)
subnet_id = element(aws_subnet.public.*.id, count.index)
depends_on = [aws_internet_gateway.main]
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_eip" "nat" {
count = 2
vpc = true
tags = {
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_route_table" "private" {
count = local.az_count
vpc_id = aws_vpc.main.id
tags = {
Environment = var.environment
CreatedBy = "terraform"
Type = "private"
Vpc = aws_vpc.main.id
}
}
resource "aws_route" "private" {
count = local.az_count
route_table_id = element(aws_route_table.private.*.id, count.index)
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = element(aws_nat_gateway.main.*.id, count.index)
}
resource "aws_route_table_association" "private" {
count = local.az_count
subnet_id = element(aws_subnet.private.*.id, count.index)
route_table_id = element(aws_route_table.private.*.id, count.index)
}
resource "aws_security_group" "alb" {
name = "${var.resources_name_prefix}-alb-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
ingress {
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}
resource "aws_security_group" "ecs_tasks" {
name = "${var.resources_name_prefix}-ecs-sg"
vpc_id = aws_vpc.main.id
ingress {
protocol = "tcp"
from_port = 3000
to_port = 3000
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
egress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Environment = var.environment
CreatedBy = "terraform"
Vpc = aws_vpc.main.id
}
}