Терраформ | Циклическая зависимость в стадии «применения» при использовании «зависит_on» для модуля - PullRequest
0 голосов
/ 16 сентября 2018

Я борюсь с проблемой циклической зависимости на этапе terraform apply при использовании depends_on в модуле.

Ошибка, которую я получил при применении:

* Cycle: aws_appautoscaling_policy.queue_depth_based_scale_out_policy, module.my_module.aws_ecs_task_definition.task_definition (destroy), aws_appautoscaling_policy.queue_depth_based_scale_in_policy

Этап plan выглядел совершенно нормально, и на этапе plan ошибок нет.

Я попытался определить цикл на графике с помощью команды ниже,

terraform graph -draw-cycles -module-depth=0 -type=plan  | dot -Tsvg > graph-plan.svg

На графике plan цикл не показан.Затем попытался определить цикл в apply, используя,

terraform graph -draw-cycles -module-depth=0 -type=apply  | dot -Tsvg > graph-apply.svg

К сожалению, эти команды не могут отобразить цикл на графике.

К счастью, я могу видеть цикл в apply этап графика, используя эти команды ниже,

terraform plan -out tfplan
terraform graph -draw-cycles -module-depth=0 tfplan | dot -Tsvg > graph-apply.svg

Цикл в моем графике выглядит следующим образом:

Graph showing cycle in apply stage

Хотя,Я все еще не могу разобрать причину этого цикла на графике.

Более того, кажется, что проблема именно с добавлением depends_on в модуль.Поскольку у меня уже есть несколько aws_appautoscaling_policy в моем модуле, который зависит от aws_appautoscaling_target, который зависит от aws_ecs_service и, следовательно, в конечном итоге зависит от aws_ecs_task_definition, но apply для этого прекрасно работает.

Естьнекоторые aws_appautoscaling_policy, которые конкретно относятся к конкретному приложению, поэтому я добавляю их отдельно (а не как часть модуля), но поскольку политика автоматического масштабирования может быть добавлена ​​только после регистрации службы в качестве масштабируемой цели, следовательно, я добавляю depends_on в модуле, поскольку в модуле определено aws_appautoscaling_target.

Вот мой фрагмент кода для модуля,

resource "aws_ecs_task_definition" "task_definition" {
  family                = "${var.service_name}"
  container_definitions = "${var.container_definitions}"
  task_role_arn         = "${aws_iam_role.task_role.arn}"
  lifecycle {
    create_before_destroy = true
  }
}
resource "aws_ecs_service" "service" {
  name                               = "${var.service_name}"
  cluster                            = "${data.aws_ecs_cluster.ecs_cluster.arn}"
  task_definition                    = "${aws_ecs_task_definition.task_definition.arn}"
  deployment_minimum_healthy_percent = 50
  deployment_maximum_percent         = 100
  lifecycle {
    ignore_changes = ["desired_count"]
  }
}
resource "aws_appautoscaling_target" "ecs_target" {
  max_capacity       = "${var.max_scalabe_capacity}"
  min_capacity       = "${var.min_scalabe_capacity}"
  resource_id        = "service/${var.ecs_cluster_name}/${aws_ecs_service.service.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}
resource "aws_appautoscaling_policy" "cpu_based_scale_in_policy" {
  name               = "${var.service_name}-${var.env}-cpu-based-scale-in-policy"
  policy_type        = "StepScaling"
  resource_id        = "service/${var.ecs_cluster_name}/${var.service_name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = "${var.scale_in_cooldown_period}"
    metric_aggregation_type = "Average"
    step_adjustment {
      metric_interval_upper_bound = "${var.scale_in_step_adjustment_upper_bound}"
      scaling_adjustment          = "${var.scale_in_step_adjustment_scaling_adjustment}"
    }
  }
  depends_on = ["aws_appautoscaling_target.ecs_target"]
}

А вот использование модуля,

module "my_module" {
  source = "GIT_URL_FOR_MODULE"
  VARIABLES_AS_NEEDED_BY_MODULE
}
resource "aws_appautoscaling_policy" "queue_depth_based_scale_in_policy" {
  name               = "${local.service_name}-${local.env}-queue-scale-in-policy-new"
  policy_type        = "StepScaling"
  resource_id        = "service/${local.ecs_cluster_name}/${local.service_name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = "${local.queue_scale_in_cooldown_period}"
    metric_aggregation_type = "Average"
    step_adjustment {
      metric_interval_upper_bound = "${local.queue_scale_in_step_adjustment_upper_bound}"
      scaling_adjustment          = "${local.queue_scale_in_step_adjustment_scaling_adjustment}"
    }
  }
  depends_on = ["module.my_module"]
}

Шаги, выполняемые в конвейере:

terraform get -update=true
terraform init
terraform taint -allow-missing -module=${MODULE_NAME} aws_ecs_task_definition.task_definition
terraform plan -out tfplan -input=false
terraform apply -input=false tfplan

Будем рады узнать причину этого цикла?

Еще один момент, который необходимо подчеркнуть, заключается в том, что terraform apply успешен, когда мы простоdestroy все и воссоздать с нуля.Цикл наблюдается только тогда, когда я taint определю задачу и у меня есть некоторые обновления в моих политиках масштабирования, которые находятся вне модуля.

Примечание. В моем конвейере я портю предыдущее определение задачи, чтобыубедитесь, что службы запускаются с новым определением задачи мгновенно, иначе задачи не будут сразу же развернуты с новым определением задачи.

1 Ответ

0 голосов
/ 19 сентября 2018

Мне удалось избавиться от циклической зависимости.Вот используемый подход:

Вместо того, чтобы зависеть от всего модуля, я добавил вывод для aws_appautoscaling_target в модуле.И затем я просто использую этот вывод в политике масштабирования, чтобы убедиться, что создана неявная зависимость.

Вот пример кода,

Модуль

resource "aws_ecs_task_definition" "task_definition" {
  family                = "${var.service_name}"
  container_definitions = "${var.container_definitions}"
  task_role_arn         = "${aws_iam_role.task_role.arn}"
  lifecycle {
    create_before_destroy = true
  }
}
resource "aws_ecs_service" "service" {
  name                               = "${var.service_name}"
  cluster                            = "${data.aws_ecs_cluster.ecs_cluster.arn}"
  task_definition                    = "${aws_ecs_task_definition.task_definition.arn}"
  deployment_minimum_healthy_percent = 50
  deployment_maximum_percent         = 100
  lifecycle {
    ignore_changes = ["desired_count"]
  }
}
resource "aws_appautoscaling_target" "ecs_target" {
  max_capacity       = "${var.max_scalabe_capacity}"
  min_capacity       = "${var.min_scalabe_capacity}"
  resource_id        = "service/${var.ecs_cluster_name}/${aws_ecs_service.service.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}
resource "aws_appautoscaling_policy" "cpu_based_scale_in_policy" {
  name               = "${var.service_name}-${var.env}-cpu-based-scale-in-policy"
  policy_type        = "StepScaling"
  resource_id        = "service/${var.ecs_cluster_name}/${var.service_name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = "${var.scale_in_cooldown_period}"
    metric_aggregation_type = "Average"
    step_adjustment {
      metric_interval_upper_bound = "${var.scale_in_step_adjustment_upper_bound}"
      scaling_adjustment          = "${var.scale_in_step_adjustment_scaling_adjustment}"
    }
  }
  depends_on = ["aws_appautoscaling_target.ecs_target"]
}
output "scalable_target_id" {
  value = "${aws_appautoscaling_target.ecs_target.id}"
}

Примечаниеблок выходного кода добавлен внутри модуля.А вот использование модуля, где выходные данные модуля используются в имени политики масштабирования.

module "my_module" {
  source = "GIT_URL_FOR_MODULE"
  VARIABLES_AS_NEEDED_BY_MODULE
}
resource "aws_appautoscaling_policy" "queue_depth_based_scale_in_policy" {
  name               = "${local.service_name}-${local.env}-queue-scale-in-policy-new-${module.my_module.scalable_target_id}"
  policy_type        = "StepScaling"
  resource_id        = "service/${local.ecs_cluster_name}/${local.service_name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = "${local.queue_scale_in_cooldown_period}"
    metric_aggregation_type = "Average"
    step_adjustment {
      metric_interval_upper_bound = "${local.queue_scale_in_step_adjustment_upper_bound}"
      scaling_adjustment          = "${local.queue_scale_in_step_adjustment_scaling_adjustment}"
    }
  }      
}

Хотя я все еще не могу понять, почему цикл был в первую очередь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...