Terraform更新许多ECS服务/任务之一

时间:2019-08-30 17:18:28

标签: terraform amazon-ecs terraform-provider-aws aws-fargate

星期五快乐!希望有人可以帮助我解决这个问题或指出我的想法中的缺陷。

$ terraform --version
Terraform v0.12.7
+ provider.aws v2.25.0
+ provider.template v2.1.2

前言

这是我第一次使用Terraform。我们已经在“测试”环境中运行了一个现有的AWS ECS / Fargate环境。我们最近(例如,在设置测试环境后)开始将Terraform用于IaC。

当前配置

环境只有一个ECS集群,我们使用的是FARGATE,但我不确定这个问题是否重要。集群具有多个服务,每个服务都具有与其关联的单个任务(泊坞窗映像)-因此可以单独扩展它们。每个docker映像都有自己的存储库。

我要做什么

因此,我希望使用Terraform能够创建,更新和销毁环境。但是,创建/销毁似乎很简单。我遇到了要更新的障碍。

正如我所说的,每个任务都有自己的存储库,当对存储库发出拉取请求时,我们的CI平台(如果重要的话,为CircleCI)将构建新的docker映像,对其进行标记并推送。然后,我们使用API​​调用来触发Terraform Repo的构建,并传递已更新的服务/任务的名称。

问题

我们面临的问题是,当通过服务(如下所述)时,我无法弄清楚如何使Terraform忽略未更新的服务,或者如何提供正确的 aws_ecs_task_definition 中的> container_definitions ,特别是当前图像标签(我们不使用latest tag)。因此,我试图弄清楚如何获取最新的容器信息(标签),或者只是告诉Terraform跳过未修改的任务。

Terraform脚本

这是我尝试过的简化版本,位于一个名为 ecs.tf 的模块中, var.ecs_svc_names 是一个 list < / em>服务名称。我删除了一些元素,因为我认为它们与该问题无关,并且使它们变得非常大。

注意事项 由于我要问的问题,我没有运行如下所示的Terraform'script',所以我的语法可能不正确。抱歉,如果可以的话,希望它能告诉您我要做什么。...

ecs.tf

/* ecs_service_names is passed in, but here is its definition:
variable "ecs_service_names" {
  type = list(string)
  description = "This is a list/array of the images/services that are contained in the cluster"
  default = [
    "main",
    "sub-service1",
    "sub-service2"]
}
*/

locals {
  numberOfServices = length(var.ecs_svc_names)
}

resource "aws_ecs_cluster" "ecs_cluster" {
  name = "${var.env_type}-ecs-cluster"
}

// Create the service objects (1 for each service)
resource "aws_ecs_service" "ecs-service" {
  // How many services are being created
  count = local.numberOfServices
  name = var.ecs_svc_names[count.index]
  cluster = aws_ecs_cluster.ecs_cluster.id
 definition[count.index].family}:${max(aws_ecs_task_definition.ecs-task-definition[count.index].revision, data.aws_ecs_task_definition.ecs-task-def.revision)}"
  desired_count = 1
  launch_type = "FARGATE"
// stuff removed
}

resource "aws_ecs_task_definition" "ecs-task-definition" {
  // How many tasks. There is a 1-1 relationship between tasks and services
  count = local.numberOfServices
  family = var.ecs_svc_names[count.index]
  network_mode = "awsvpc"
  requires_compatibilities = ["FARGATE"]
// cpu/memory stuff removed
  task_role_arn = var.ecs_task_role_arn

  container_definitions = data.template_file.ecs_containers_json[count.index].rendered
}

data.tf

locals {
    numberOfServices = length(var.ecs_svc_names)
}
data "aws_ecs_task_definition" "ecs-task-def" {
    // How many services are being created, 1-1 relationship between tasks and services
    count = local.numberOfServices
    task_definition = aws_ecs_task_definition.ecs-task-definition[count.index].family

    depends_on = [
        "aws_ecs_task_definition.ecs-task-definition",
    ]
}

data "template_file" "ecs_containers_json" {
    // How many tasks. There is a 1-1 relationship between tasks and services
    count = local.numberOfServices
  template = file("${path.module}/container.json.template")
  vars = {
// vars removed

      image = aws_ecs_task_definition.ecs-task-definition[count.index].family

// This is where I hit the road-block, how do I get the current docker tag from Terraform?
      tag = var.ecs_svc_name_2_update == var.ecs_svc_names[count.index]
            ? var.ecs_svc_image_tag
            : data.aws_ecs_task_definition.ecs-task-def[count.index].
}

我没有发布JSON文档,如果您需要我可以提供它...

谢谢

1 个答案:

答案 0 :(得分:0)

必须在任务定义修订版的容器定义中传递更新的图像属性。

您可以data source服务使用的当前任务修订的容器定义,并将其传递给terraform。您可以按照以下代码进行操作。

data "template_file" "example" {
  template = "${file("${path.module}/example.json")}"

  vars {
    image = "${data.aws_ecs_container_definition.example.image}"
  }
}

resource "aws_ecs_task_definition" "example" {
  family                = "${var.project_name}-${var.environment_name}-example"
  container_definitions = "${data.template_file.example.rendered}"
  cpu                   = 192
  memory                = 512
}

data "aws_ecs_container_definition" "example" {
  task_definition = "${var.project_name}-${var.environment_name}-example"
  container_name  = "example"
}