问题描述
在使用AWS ECS集群(使用Docker容器)启动两个应用程序的情况下,用户希望将一个应用程序通过公共IP暴露给外部(通过AWS负载均衡器实现),而另一个应用程序只能在内部访问,因此它不会有任何公共IP,只能在内部访问。用户考虑使用Docker容器之间通过本地主机(localhost)通信的方式,但是这只在将两个应用程序运行在同一个EC2实例上时适用。如果将它们运行在不同的实例上但使用相同的负载均衡器,或者将它们运行在同一AWS区域的不同实例上,用户想知道如何在ECS中配置只能通过本地主机访问的应用程序。
解决方案
请注意以下操作可能涉及版本差异或涉及风险,执行前务必做好备份。
使用awsvpc网络模式
使用awsvpc
网络模式可以满足用户的需求,这允许容器使用各自的网络栈并分配独立的Elastic Network Interface(ENI)。
以下是一些操作步骤,展示了如何在ECS中配置只能通过本地访问的应用程序:
- 创建一个VPC,包含至少两个子网:一个私有子网和一个公共子网。
- 配置VPC的路由表,确保私有子网中的流量可以通过NAT网关访问互联网。
- 配置安全组,允许从公共子网的负载均衡器访问前端应用程序的端口。
- 使用
awsvpc
网络模式创建ECS任务定义,确保容器只会监听本地主机(localhost)。 - 在ECS服务中使用这些任务定义启动前端和后端应用程序。
示例Terraform代码:
resource "aws_vpc" "example" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "private_subnet" {
vpc_id = aws_vpc.example.id
cidr_block = "10.0.1.0/24"
}
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.example.id
cidr_block = "10.0.2.0/24"
}
resource "aws_security_group" "frontend_sg" {
name_prefix = "frontend-"
vpc_id = aws_vpc.example.id
// 配置允许来自负载均衡器的流量访问前端应用程序的端口
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group" "backend_sg" {
name_prefix = "backend-"
vpc_id = aws_vpc.example.id
// 配置允许来自前端应用程序的流量访问后端应用程序的端口
ingress {
from_port = 8081
to_port = 8081
protocol = "tcp"
security_groups = [aws_security_group.frontend_sg.id]
}
}
resource "aws_ecs_task_definition" "frontend" {
family = "frontend"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
execution_role_arn = "" # 通用的执行角色ARN
// 定义前端应用程序容器配置,确保容器监听本地主机
container_definitions = jsonencode([{
name = "frontend-container"
image = "your_frontend_image:latest"
portMappings = [{
containerPort = 8080
hostPort = 8080
}]
}])
}
resource "aws_ecs_service" "frontend" {
name = "frontend"
cluster = "my-ecs-cluster"
task_definition = aws_ecs_task_definition.frontend.arn
desired_count = 2 # 高可用性
launch_type = "FARGATE"
network_configuration {
security_groups = [aws_security_group.frontend_sg.id]
subnets = [aws_subnet.public_subnet.id] # 公共子网
}
load_balancer {
target_group_arn = "" # AWS负载均衡器的目标组ARN
container_name = "frontend-container"
container_port = 8080
}
}
resource "aws_ecs_task_definition" "backend" {
family = "backend"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
execution_role_arn = "" # 通用的执行角色ARN
// 定义后端应用程序容器配置,确保容器监听本地主机
container_definitions = jsonencode([{
name = "backend-container"
image = "your_backend_image:latest"
portMappings = [{
containerPort = 8081
hostPort = 8081
}]
}])
}
resource "aws_ecs_service" "backend" {
name = "backend"
cluster = "my-ecs-cluster"
task_definition = aws_ecs_task_definition.backend.arn
desired_count = 2 # 高可用性
launch_type = "FARGATE"
network_configuration {
security_groups = [aws_security_group.backend_sg.id]
subnets = [aws_subnet.private_subnet.id] # 私有子网
}
// 使用Service Discovery来解析容器内部的服务地址
service_registries {
registry_arn = aws_service_discovery_service.backend.arn
}
}
注意事项
- 在
awsvpc
网络模式下,每个容器都会有自己的ENI,确保VPC中有足够的IP地址空间。 - 安全组需要正确配置,允许前端和后端容器之间的通信。
- 此示例使用了Fargate launch type,如果使用EC2 launch type,需要根据EC
正文完