应用第一个后​​,terraform 可以有 2 个主文件和第二个 运行 吗?

Can terraform have 2 main files with second running after first is applied?

terraform 可以有 2 个主文件,一个 运行ning 一个接一个吗?

我需要 main1 在调用 main2 之前完全 运行,因为我的 main2 有 for_each,这需要先创建资源。 与 main3 相同。

所以 main1 必须 运行 完全 (terraform plan/apply) 然后是 main2.

我的树结构

├── README.md
├── config
│   ├── prod
│   └── sandbox
│       └── us_east_2
│           ├── nonprod.tfvars
│           └── prod.tfvars
├── init
│   ├── prod
│   └── sandbox
│       └── us_east_2
│           ├── nonprod.tfvars
│           └── prod.tfvars
├── main.tf
├── modules
│   ├── create_transit_gateway
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   ├── ec2
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   ├── transit_gateway
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   ├── transit_gateway_asso_prop
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   ├── transit_gateway_locals
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
│   └── vpc
│       ├── main.tf
│       ├── outputs.tf
│       └── variables.tf
├── output.tf
└── variables.tf
provider "aws" {
  region  = var.REGION
}

module "create_transit_gateway" {
    source = "./modules/create_transit_gateway"
    REGION_SHORTHAND = var.REGION_SHORTHAND
    TGW_LOCAL = var.TGW_LOCAL
    ENV_NAME = var.ENV_NAME
    AMAZON_SIDE_ASN = var.AMAZON_SIDE_ASN
}

module "vpc" {
    depends_on = [module.create_transit_gateway]
    source = "./modules/vpc"
    NETWORK_VPC = var.NETWORK_VPC
    SUBNETS = var.SUBNETS
    ROUTE_TABLES = var.ROUTE_TABLES
    ENV_NAME = var.ENV_NAME
    TGW_LOCAL = var.TGW_LOCAL
    REGION_SHORTHAND = var.REGION_SHORTHAND
}

module "ec2" {
    depends_on = [module.create_transit_gateway, module.vpc]
    source = "./modules/ec2"
    FW_ASNS = var.FW_ASNS
    FIREWALLS = var.FIREWALLS
    AMI_IMAGE_KEY = var.AMI_IMAGE_KEY
    REGION_SHORTHAND = var.REGION_SHORTHAND
    ENV_NAME = var.ENV_NAME
    VPC_ID = module.vpc.VPC_ID
    AWS_SUBNETS = module.vpc.AWS_SUBNETS
}

module "transit_gateway" {
    depends_on = [module.create_transit_gateway, module.ec2, module.vpc]
    source = "./modules/transit_gateway"
    REGION = var.REGION
    TGW_LOCAL = var.TGW_LOCAL
    ENV_NAME = var.ENV_NAME
    SITE_CUSTOMER_GATEWAYS = var.SITE_CUSTOMER_GATEWAYS
    EIP_FW1_NICS = module.ec2.EIP_FW1_NICS
    EIP_FW2_NICS = module.ec2.EIP_FW2_NICS
    AWS_SUBNETS = module.vpc.AWS_SUBNETS
    FW_ASNS = var.FW_ASNS
    TGW_PEERS = var.TGW_PEERS
    VPC_ID = module.vpc.VPC_ID
    TGW_ROUTE_TABLES = var.TGW_ROUTE_TABLES
    REGION_SHORTHAND = var.REGION_SHORTHAND
    AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
}

module "transit_gateway_locals" {
    depends_on = [module.create_transit_gateway, module.transit_gateway]
    source = "./modules/transit_gateway_locals"
    REGION = var.REGION
    TGW_PEERS = var.TGW_PEERS
    TGA_VPC_ATTACHMENT = module.vpc.TG_VPC_ATTACHMENT
    ENV_NAME = var.ENV_NAME
    AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
    NETWORK_S2S_VPN = module.transit_gateway.NETWORK_S2S_VPN
    NETWORK_TGW_RT = module.transit_gateway.NETWORK_TGW_RT
    TGW_PEERS_RESOURCE = module.transit_gateway.TGW_PEERS_RESOURCE
    PEER_ACCEPTOR_STATUS = module.transit_gateway.PEER_ACCEPTOR_STATUS
}

module "transit_gateway_asso_prop" {
    depends_on = [module.transit_gateway_locals]
    source = "./modules/transit_gateway_asso_prop"
    REGION = var.REGION
    VPC_ASSO_LIST = module.transit_gateway_locals.VPC_ASSO_LIST
    VPC_PROP_LIST = module.transit_gateway_locals.VPC_PROP_LIST
    VPN_ASSO_LIST = module.transit_gateway_locals.VPN_ASSO_LIST
    VPN_PROP_LIST = module.transit_gateway_locals.VPN_PROP_LIST
    PEER_ASSO_LIST = module.transit_gateway_locals.PEER_ASSO_LIST
    SEC_STATIC_LIST = module.transit_gateway_locals.SEC_STATIC_LIST
    TGW_PEERS = var.TGW_PEERS
    ENV_NAME = var.ENV_NAME
}

在应用上述模块后,我需要模块 transit_gateway_asso_prop 到 运行。 由于 VPN_PROP_LISTVPN_ASSO_LIST 等变量将在应用 transit_gateway_locals 和其他上述模块后创建

Error: Invalid for_each argument

  on modules/transit_gateway_asso_prop/main.tf line 325, in resource "aws_ec2_transit_gateway_route_table_propagation" "NETWORK-TGW-VPNPROPAGATION":
 325:   for_each = var.VPN_PROP_LIST 

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

遗憾的是你不能这样做。构建代码的正确方法是 modules。因此,您必须将 main1main2 转换为子模块,然后创建顶级 main.tf。在 main 中创建 main1main2 模块将确保正确的顺序。

.
├── main.tf
└── modules
    ├── main1
    │   └── main.tf
    └── main2
        └── main.tf

然后在 main.tf 中创建两个模块:

module "main1" {    
    source = "./modules/main1/main"
    VAR2 = var.VAR2
}

module "main2" {    
    source = "./modules/main1/main"
    VAR2 = module.main2.id
}

您可以使用 -target 来做到这一点。 你做的不理想。

terraform plan -target=module.mymodule.aws_instance.myinstance ```

terraform apply

This might help: 

举一个如此人为的例子,很难给出具体的建议,所以改为一些一般性的观察:

  • “要created/modified在一起的一组基础设施”的主要分解单元是一个单独的配置,而不是同一配置中的一个单独模块。如果您将配置分成两部分并使用 Data Sources 以便第二部分可以读取第一部分的结果,那么您可以分两步应用整个系统,从而确保正确的顺序。

  • 话虽如此,对于在规划期间未知的 for_each 值的问题,通常(但并非总是)有不同的方式来构建事物,以便 Terraform 可以至少在计划时间看到地图的钥匙。只要已知,值就可以未知。

    如果您想了解更多相关信息,那么我建议您在 Stack Overflow 上开始一个新问题,您可以在其中分享更真实的配置版本并描述潜在问题,此后回答者可以提出具体建议可能允许工作解决方案的重构或重组。

  • depends_on 的高使用率,特别是在 module 块内,在 Terraform 中通常是 code smell,因为它表明模块没有正确封装和所以他们依赖外部注释才能正确运行。

    这并不总是正确的,而且如果没有真实的例子也很难具体说明,但是有更好的技术可以告诉 Terraform 不同模块中对象之间的关系,这通常可以使模块在默认情况下正确运行,而无需像这样的附加注释。

我的 if 循环中有 if rt_att_id.rt_id != null 个条件。

对于每个都不能引用未知的资源,这就是它出错的原因。

我通过数据获取路由 table id 并使用特定名称而不是遍历整个路由 table.

来修改我的循环

谢谢大家的帮助。