Terraform-为什么这不会导致循环依赖?

Terraform-为什么这不会导致循环依赖?,terraform,Terraform,Terraform registry AWS VPC示例具有下面的代码,在我看来,这是一个循环依赖项 data "aws_security_group" "default" { name = "default" vpc_id = module.vpc.vpc_id } module "vpc" { source = "../../" name = "complete-example" ... # VPC endpoint for SSM enable_ssm_en

Terraform registry AWS VPC示例具有下面的代码,在我看来,这是一个循环依赖项

data "aws_security_group" "default" {
  name   = "default"
  vpc_id = module.vpc.vpc_id
}

module "vpc" {
  source = "../../"

  name = "complete-example"

...
 # VPC endpoint for SSM
  enable_ssm_endpoint              = true
  ssm_endpoint_private_dns_enabled = true
  ssm_endpoint_security_group_ids  = [data.aws_security_group.default.id] # <----- 

...
数据“aws\u安全组”“默认”{
name=“默认值”
vpc_id=module.vpc.vpc_id
}
模块“专有网络”{
source=“../”
name=“完整示例”
...
#SSM的VPC端点
启用\u ssm\u端点=真
ssm\u端点\u私有\u dns\u已启用=真

ssm_endpoint_security_group_ids=[data.aws_security_group.default.id]#在Terraform语言中,模块创建单独的名称空间,但它不是依赖关系图中的节点。相反,模块的每个输入变量和输出值都是依赖关系图中的单独节点

因此,此配置包含以下依赖项:

  • data.aws\u security\u group.default
    资源取决于
    module.vpc.vpc\u id
    ,它是该模块中的
    输出“vpc\u id”
    块,而不是整个模块
  • vpc
    模块的
    变量“ssm\u端点\u安全性\u组\u ID”
    变量取决于
    数据.aws\u安全性\u组。默认值
    资源
在您的问题中,我们看不到
vpc
模块的内部,但只要模块内部
输出“vpc\u id”
变量“ssm\u endpoint\u security\u group\u id”
之间没有依赖关系,上述内容就可以了

我假设这种连接不存在,所以这里对象的求值顺序如下:

  • aws\u-vpc.example
    module.vpc
    中创建(我刚刚为它编了一个名字,因为它没有包含在您的问题中)
  • 参考
    module.vpc.aws\u vpc.example
    ,评估
    模块.vpc
    中的
    输出“vpc\u id”
    ,并生成
    模块.vpc.vpc\u id
  • 使用
    module.vpc.vpc\u id的值读取根模块中的
    data.aws\u security\u group.default
  • 参考
    数据.aws\u security\u group.default
    评估
    模块的
    变量“ssm\u endpoint\u security\u group\u ids”
  • aws\u vpc\u端点。创建
    模块中的示例
    。创建vpc
    ,包括对
    var.ssm\u端点\u安全\u组\u ID的引用
请注意,在以上所有内容中,我谈论的是模块中的对象,而不是模块本身。模块仅用于为对象创建单独的名称空间,然后单独的对象本身(包括单个
变量
输出
块)参与依赖关系图


通常这种设计细节是不可见的:Terraform通常只是使用它来潜在地优化并发性,在整个模块准备好处理之前就开始处理模块的一部分。不过,在一些有趣的情况下,您也可以有意地利用这种设计,以便显式地执行调用模块的操作夹在子模块的两个操作之间

我们可能使用此功能的另一个原因是,当两个模块自然相互依赖时,例如在中,隐藏了设置VPC对等连接的一些棘手细节:

locals {
  vpc_nets = {
    us-west-2 = module.vpc_usw2
    us-east-1 = module.vpc_use1
  }
}

module "peering_usw2" {
  source = "../../modules/peering-mesh"

  region_vpc_networks = local.vpc_nets
  other_region_connections = {
    us-east-1 = module.peering_use1.outgoing_connection_ids
  }

  providers = {
    aws = aws.usw2
  }
}

module "peering_use1" {
  source = "../../modules/peering-mesh"

  region_vpc_networks = local.vpc_nets
  other_region_connections = {
    us-west-2 = module.peering_usw2.outgoing_connection_ids
  }

  providers = {
    aws = aws.use1
  }
}
(以上仅是中的相关片段。)


在上述情况下,
对等网格
模块经过精心设计,允许这种相互引用,在内部为每对区域专有网络决定哪一个将成为对等发起方,哪一个将成为对等接收方。
传出连接\u id
输出仅指
aws\u专有网络\u对等\u连接
resource和
aws\u-vpc\u-peering\u-connection\u-accepter
仅指
var.other\u-region\u-connections
,因此结果是一系列并发操作来创建
aws\u-vpc\u-peering\u-connection\u-accepter
,然后是一系列并发操作来创建
aws\u-vpc\u-peering\u-accepter
>资源。

因为依赖关系图在单个元素上工作,而不是在模块上。无论您将安全组ID作为
ssm\u endpoint\u security\u group\u ID的一部分传递到哪里,它对安全组都没有循环依赖关系。但是完全没有必要,因为您可以直接传递资源的安全组在模块内部。为了确保您也必须发布模块的源代码。Hi@ydaetskcoR,谢谢,但仍然不确定原因。据我所知,数据源首先运行以检索数据,并且需要现有资源,在这种情况下,默认的安全组module.vpc尚未创建。我想知道为什么它没有失败。由于插值,在创建专有网络之前,它不会运行。但我仍然希望它在第一次创建时失败,因为安全组创建将与专有网络创建同时进行(假设它也插值专有网络ID,并且模块输出直接来自专有网络资源)因此,此时还没有创建安全组。但更重要的是,如果您不发布模块的源代码,就不可能真正具体地说明事情是如何工作的。但考虑到您的模块看起来非常复杂,我会尝试生成一个类似的示例。@ydaetskcoR代码都在Terraform注册表AWS VPC的Github中,示例如下所示在github中。感谢TF 0.12背后的人的回复。谢谢你的工作。我想我明白了。这是不是[依赖于模块]()不会发生的原因?尽管我们用户可能认为TF模块是一种原子单元(DAG中的节点?),将根模块和TF模块中的所有资源放在一个地方,并从中创建DAG。希望这种理解是正确的。