创建AWS VPC终端节点时出现DuplicateSubnetsInSameZone错误
我正尝试用Terraform将db、api、frontend三个服务部署到AWS,每个服务在两个可用区(eu-west-2a、eu-west-2b)各有一个私有子网:
private-api-a: eu-west-2aprivate-api-b: eu-west-2bprivate-db-a: eu-west-2aprivate-db-b: eu-west-2bprivate-frontend-a: eu-west-2aprivate-frontend-b: eu-west-2b
为让ECS任务访问ECR和CloudWatch,我定义了以下VPC终端节点配置:
resource "aws_vpc_endpoint" "ecr_dkr" { vpc_id = aws_vpc.vpc.id service_name = "com.amazonaws.eu-west-2.ecr.dkr" vpc_endpoint_type = "Interface" private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] subnet_ids = [ aws_subnet.private-api-a.id, aws_subnet.private-api-b.id, aws_subnet.private-db-a.id, aws_subnet.private-db-b.id, aws_subnet.private-frontend-a.id, aws_subnet.private-frontend-b.id ] tags = { "Name" = "$ecr-dkr" } } resource "aws_vpc_endpoint" "ecr_api" { vpc_id = aws_vpc.vpc.id service_name = "com.amazonaws.eu-west-2.ecr.api" vpc_endpoint_type = "Interface" private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] subnet_ids = [ aws_subnet.private-api-a.id, aws_subnet.private-api-b.id, aws_subnet.private-db-a.id, aws_subnet.private-db-b.id, aws_subnet.private-frontend-a.id, aws_subnet.private-frontend-b.id ] tags = { "Name" = "ecr-api" } } resource "aws_vpc_endpoint" "cloudwatch_api" { vpc_id = aws_vpc.vpc.id service_name = "com.amazonaws.eu-west-2.logs" vpc_endpoint_type = "Interface" private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] subnet_ids = [ aws_subnet.private-api-a.id, aws_subnet.private-api-b.id, aws_subnet.private-db-a.id, aws_subnet.private-db-b.id, aws_subnet.private-frontend-a.id, aws_subnet.private-frontend-b.id ] tags = { "Name" = "cloudwatch-api" } } resource "aws_vpc_endpoint" "s3" { vpc_id = aws_vpc.vpc.id service_name = "com.amazonaws.eu-west-2.s3" vpc_endpoint_type = "Gateway" route_table_ids = [ aws_route_table.private-api.id, aws_route_table.private-db.id, aws_route_table.private-frontend.id ] tags = { "Name" = "s3" } }
执行部署时,除S3网关终端节点外,其余接口类型终端节点都抛出错误:
creating EC2 VPC Endpoint (com.amazonaws.eu-west-2.ecr.dkr): DuplicateSubnetsInSameZone:...
仅指定单个服务的两个子网时可正常运行,但不清楚如何在多服务多子网场景下解决这个问题。
接口类型VPC终端节点要求每个可用区仅关联一个子网,当前配置在同一个可用区下添加了多个子网(比如eu-west-2a下有private-api-a、private-db-a、private-frontend-a三个子网),这违反了AWS的限制规则。
解决思路如下:
方法1:为每个可用区选择一个子网关联终端节点
接口终端节点在每个AZ只需要一个子网即可,所有同AZ内的服务子网都能通过该终端节点访问AWS服务,无需重复添加。修改子网列表,每个AZ保留一个子网即可,示例:
subnet_ids = [ aws_subnet.private-api-a.id, # eu-west-2a aws_subnet.private-api-b.id # eu-west-2b ]
只要这些子网所属的路由表能覆盖所有服务的私有子网,所有ECS任务就能通过终端节点访问ECR和CloudWatch。
方法2:按服务拆分VPC终端节点(不推荐,增加资源冗余)
如果必须让每个服务子网单独关联终端节点,可以为每个服务分别创建接口终端节点,每个终端节点仅关联对应服务的两个子网。比如为api服务创建单独的ecr_dkr终端节点:
resource "aws_vpc_endpoint" "ecr_dkr_api" { vpc_id = aws_vpc.vpc.id service_name = "com.amazonaws.eu-west-2.ecr.dkr" vpc_endpoint_type = "Interface" private_dns_enabled = true security_group_ids = [aws_security_group.vpc_endpoints.id] subnet_ids = [ aws_subnet.private-api-a.id, aws_subnet.private-api-b.id ] tags = { "Name" = "ecr-dkr-api" } } # 同理为db、frontend服务创建对应的终端节点
但这种方式会创建多个相同服务的终端节点,增加资源成本和管理复杂度,因此优先推荐方法1。
内容的提问来源于stack exchange,提问作者Alex

