module - 地形 | 对模块使用“depends_on”时“应用”阶段的循环依赖
问题描述
在模块上使用时,我正在努力解决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
我图表中的循环看起来像这样,
虽然,我仍然无法在图中找出这个循环的原因。
此外,似乎问题特别在于添加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
只有当我定义任务并且在我的扩展策略中有一些位于模块之外的更新时,才会观察到这个循环。
注意:在我的管道中,我确实污染了以前的任务定义,以确保立即使用新的任务定义启动服务,否则不会立即使用新的任务定义推出任务。
解决方案
我设法摆脱了循环依赖。这是使用的方法,
我没有依赖整个模块,而是在模块中添加了输出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}"
}
}
}
虽然,我仍然无法弄清楚为什么这个循环首先存在。
推荐阅读
- html - 当空间可用时,背景图像会拉伸
- python - 有没有办法在熊猫数据框的多列中修剪/去除空白?
- react-native - 如何跨所有屏幕链接组件?
- python - 当我在 Keras 中加载保存的模型时,输入会丢失,其中包含需要多个输入的自定义损失
- mysql - SQL Sum, Subtraction 将 4 个表与 where 连接起来
- c# - 数据表和剑道网格
- matlab - 0.2104 + 0.0000i 在 MATLAB 中是什么意思
- gesture - PDFKit 手势问题在升级到 IOS 13 后停止工作
- ios - 如何在 Swiftui 中更改数组项
- django - 带有 JWT 的 Django。如何使用两者?使用来自 restframework-jwt 的 JWT 令牌认证机制来访问 django-admin