由于某种奇怪的原因,Terraform 文档没有解释“Error: Cycle”的含义。我到处都找过了,但官方文档中没有提到它。(原来它是一个众所周知的术语,即循环依赖,显然有人重新命名了它,认为这样听起来很酷……)
答案1
作为 Terraform 工作的一部分,它会分析您的resource
块、data
块和其他配置构造之间的依赖关系,以确定合适的顺序来处理它们,以便提供必要的输入数据。
例如,考虑以下设计的简单配置:
resource "null_resource" "foo" {
}
resource "null_resource" "bar" {
triggers = {
foo = null_resource.foo.id
}
}
Terraform 将分析上述内容,并注意到的配置null_resource.bar
包含对的引用null_resource.foo
,因此与 相关的操作null_resource.foo
必须在 之前发生null_resource.bar
。我们可以将其可视化为一个图表,其中箭头表示“必须在 之后发生”或“取决于”:
- 操作
null_resource.bar
必須在之後發生的操作null_resource.foo
。
现在考虑一下如果我们像这样修改配置会发生什么:
resource "null_resource" "foo" {
triggers = {
bar = null_resource.bar.id
}
}
resource "null_resource" "bar" {
triggers = {
foo = null_resource.foo.id
}
}
现在null_resource.foo
还指null_resource.bar
。此配置现在隐含两个“必须发生于”的关系:
- 操作
null_resource.bar
必須在之後發生的操作null_resource.foo
。 - 操作
null_resource.foo
必須在之後發生的操作null_resource.bar
。
上述两个陈述相互矛盾:null_resource.bar
不能同时处理和之后null_resource.foo
。Terraform 将通过报告依赖循环来响应这种情况,使用您看到的错误消息:
Cycle: null_resource.foo, null_resource.bar
当 Terraform 返回此错误时,解决方案是从配置中删除至少一个“必须在之后发生”的箭头(依赖项),这样它就不再相互矛盾了。在没有看到您的配置的情况下,我无法建议哪种具体更改可以实现这一点,但您的配置中可能有两个像这样相互依赖的资源,或者可能有一个资源引用自身。
如果您有视力,则根据您的配置的复杂程度,要求 Terraform 生成类似于我在此答案中包括的图表可能会有所帮助,但会突出显示循环。为此,您可以使用命令terraform graph
, 像这样:
terraform graph -draw-cycles
此命令的输出是图表的描述,格式如下:Graphviz。如果你的本地计算机上没有安装 Graphviz,你可以将输出复制粘贴到Graphviz 在线生成图形图像。该-draw-cycles
命令使 Terraform 使用红色标记与所报告周期相关的箭头。如果您无法在视觉上区分红色和黑色,您可能希望首先编辑生成的 Graphviz 代码以将其替换为red
您可以区分的其他颜色。
由于图形和边太多,配置的图形可视化往往无法用于非平凡配置,因此如果您的配置有许多对象,最好通过配置本身来跟踪依赖关系。
答案2
除了 Martin Atkins 上述出色的解释之外,我想补充一点,在我的案例中,循环不是由资源中的循环引起的,而是由需要销毁的资源引起的。
Terraform 无法弄清楚如何销毁该资源而只查看新资源。
所以,我别无选择,只能销毁并重新开始。这样就删除了“循环”消息。