【问题标题】:Mapping multiple containers to an application load balancer in Terraform在 Terraform 中将多个容器映射到应用程序负载均衡器
【发布时间】:2017-06-05 22:58:51
【问题描述】:

我正在使用 Terraform 在 AWS 云上使用 ECS 设置容器集群,但在映射负载均衡器以将流量引导到集群上运行的多个容器时遇到了问题。

为简化起见,假设我正在使用两个容器运行服务/任务:webrequester 在 5600 上侦听,restserver 在 5000 上侦听。我需要请求 /api/* 的流量去端口 5000 上的 restserver 和默认流量去到 5600 上的 webrequester。无论我正在运行的容器主机实例的数量如何,这都应该有效。

我最好的理解是我需要创建一个aws_alb_target_group_attachment 来建立这个关联并将它的target_id 设置为Container ID。它是否正确?如果是这样,我如何在 Terraform 中获取容器 ID?我已经创建了一个集群、服务、任务、应用程序负载均衡器以及使它们运行所需的所有实体,但我不知道哪些实体(如果有的话)可以让我访问容器 ID。

以下是我认为 Terraform 脚本的相关部分:

resource "aws_ecs_cluster" "main" {
  name = "jsapps-am${var.am_number}${var.cluster_iteration}"
}

resource "aws_alb_target_group" "https_default" {
  name     = "https-default-tg"
  port     = 443
  protocol = "HTTPS"
  vpc_id   = "${var.vpc_id}"
}

resource "aws_alb" "main" {
  name            = "af-${var.am_number}${var.cluster_iteration}-alb"
  subnets         = ["${var.vpc_subnets}"]
  security_groups = ["${aws_security_group.lb_sg.id}"]
}

resource "aws_alb_listener" "front_end" {
  load_balancer_arn = "${aws_alb.main.id}"
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2015-05"
  certificate_arn   = "${var.https_certificate_arn}"

  default_action {
    target_group_arn = "${aws_alb_target_group.https_default.id}"
    type             = "forward"
  }
}

data "template_file" "task_definition" {
  template = "${file("${path.module}/task-definition.json")}"

  vars {
    image_url        = "${var.task_url}"
    container_name   = "webrequester"
    port_num         = "${var.webrequester_port}"
  }
}

resource "aws_ecs_task_definition" "jsapps" {
  family                = "jsapps_taskdef"
  container_definitions = "${data.template_file.task_definition.rendered}"
}

resource "aws_ecs_service" "jsapps" {
  name            = "jsapps-svc"
  cluster         = "${aws_ecs_cluster.main.id}"
  task_definition = "${aws_ecs_task_definition.jsapps.arn}"
  desired_count   = 1
  iam_role        = "${aws_iam_role.ecs_service.name}"

  load_balancer {
    target_group_arn = "${aws_alb_target_group.https_default.id}"
    container_name   = "webrequester"
    container_port   = "${var.webrequester_port}"
  }

  depends_on = [
    "aws_iam_role_policy.ecs_service",
    "aws_alb_listener.front_end",
  ]
}

【问题讨论】:

标签: amazon-web-services terraform


【解决方案1】:

您可以尝试使用 docker provisioner 与 docker host 一起工作,大声思考。

另外,您是否检查过负载均衡器内部集群?它应该对一组容器的流量进行负载平衡。

【讨论】:

    【解决方案2】:

    在首选设置中,您可以将动态主机端口附加到在 ECS 容器实例上运行的容器。原因很简单:您希望能够灵活地在单个实例上运行多个公开相同端口的容器。如果您使用静态主机端口进行绑定,这将不起作用(因为该端口已被占用)。在蓝/绿部署的情况下,这会妨碍。

    您可以通过在任务定义中定义您的容器端口来做到这一点。所以这部分就是你需要的所有端口映射:

    "portMappings": [
      {
        "containerPort": ${service_port}
      }
    ]
    

    您的 ALB 当然需要知道要使用哪个端口,并且由于该端口是由 Docker 随机分配的,因此您无法预先配置此端口。这就是您使用目标组从负载均衡器向其发送流量的原因。如果您正确设置aws_ecs_serviceload_balancer 部分,您的ECS 代理将在启动新容器时注册容器实例+(动态)端口。

    所以...在您的 ALB 设置中,您不关心容器正在侦听的端口,您只关心需要向哪些目标组发送流量。为此,您添加一个带有默认规则和一个额外规则(指定 /api/* 路径)的aws_alb_listener。对于这两个规则,您指定正确的目标组和type="forward",工作就完成了。

    总结:您不需要需要aws_alb_target_group_attachment,因为在您设置负载平衡器连接时,这些是由 ECS 服务(在运行时)处理的。

    【讨论】:

    • 令人困惑的是,在此设置中,您仍然需要为听众的配置设置一个目标组。而且你必须为i指定一个端口,但是这个端口没有任何实际意义。
    • 确实不错,为目标组指定端口是强制性的,但总是会被附加到目标组的目标覆盖。我总是把端口设置为1234,但是有点傻。
    猜你喜欢
    • 2017-07-28
    • 2022-01-23
    • 2020-05-08
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多