在AWS中仅通过本地访问Docker实例

71次阅读
没有评论

问题描述

在使用AWS ECS集群(使用Docker容器)启动两个应用程序的情况下,用户希望将一个应用程序通过公共IP暴露给外部(通过AWS负载均衡器实现),而另一个应用程序只能在内部访问,因此它不会有任何公共IP,只能在内部访问。用户考虑使用Docker容器之间通过本地主机(localhost)通信的方式,但是这只在将两个应用程序运行在同一个EC2实例上时适用。如果将它们运行在不同的实例上但使用相同的负载均衡器,或者将它们运行在同一AWS区域的不同实例上,用户想知道如何在ECS中配置只能通过本地主机访问的应用程序。

解决方案

请注意以下操作可能涉及版本差异或涉及风险,执行前务必做好备份。

使用awsvpc网络模式

使用awsvpc网络模式可以满足用户的需求,这允许容器使用各自的网络栈并分配独立的Elastic Network Interface(ENI)。

以下是一些操作步骤,展示了如何在ECS中配置只能通过本地访问的应用程序:

  1. 创建一个VPC,包含至少两个子网:一个私有子网和一个公共子网。
  2. 配置VPC的路由表,确保私有子网中的流量可以通过NAT网关访问互联网。
  3. 配置安全组,允许从公共子网的负载均衡器访问前端应用程序的端口。
  4. 使用awsvpc网络模式创建ECS任务定义,确保容器只会监听本地主机(localhost)。
  5. 在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

正文完