在模块内的模块之间传递 Terraform 变量?

Posted

技术标签:

【中文标题】在模块内的模块之间传递 Terraform 变量?【英文标题】:Passing Terraform variables between Modules within Modules? 【发布时间】:2020-05-16 14:50:27 【问题描述】:

我在从 Kubespray 项目构建模块时遇到了问题。

我有以下文件夹结构:

terraform/
modules/
   kubespray/
      modules/
         compute/
         ips/
         network/
      main.tf
      variables.tf
roles/
    kubespray/
        terraform_setup/
             main.tf

kubespray/main.tf 模块内有变量被传递:

module "ips" 
  source = "./modules/ips"

  number_of_k8s_masters         = "$var.number_of_k8s_masters"
  number_of_k8s_masters_no_etcd = "$var.number_of_k8s_masters_no_etcd"
  number_of_k8s_nodes           = "$var.number_of_k8s_nodes"
  floatingip_pool               = "$var.floatingip_pool"
  number_of_bastions            = "$var.number_of_bastions"
  external_net                  = "$var.external_net"
  network_name                  = "$var.network_name"
  router_id                     = "$module.network.router_id"


module "compute" 
  source = "./modules/compute"
  ...
  k8s_master_fips                              = "$module.ips.k8s_master_fips"
  k8s_master_no_etcd_fips                      = "$module.ips.k8s_master_no_etcd_fips"
  k8s_node_fips                                = "$module.ips.k8s_node_fips"
  bastion_fips                                 = "$module.ips.bastion_fips"
  ...

output "private_subnet_id" 
  value = "$module.network.subnet_id"


output "floating_network_id" 
  value = "$var.external_net"


output "router_id" 
  value = "$module.network.router_id"


output "k8s_master_fips" 
  value = "$concat(module.ips.k8s_master_fips, module.ips.k8s_master_no_etcd_fips)"


output "k8s_node_fips" 
  value = "$module.ips.k8s_node_fips"


output "bastion_fips" 
  value = "$module.ips.bastion_fips"

如果我从 modules/kubespray/ 的子模块内部运行我的 terraform init/apply,它可以正常工作

如果我从我的role/kubespray 那里逃跑

module "kubespray" 
  source    = "../../../modules/kubespray"
  providers = 
    openstack.src = openstack
  

失败了

错误:索引无效

在 ../../../modules/kubespray/modules/compute/main.tf 第 670 行,在 资源“openstack_compute_floatingip_associate_v2”“k8s_node”:670: floating_ip = "$var.k8s_node_fips[count.index]" |---------------- | count.index 为 0 | var.k8s_node_fips 是动态的空列表

非常感谢您的帮助

【问题讨论】:

【参考方案1】:

当您运行terraform 时,该目录将成为一个隐含的“根模块”。正如Input Variables 文档中所解释的那样,根模块可以从 CLI 或环境访问 TF 输入,但所有其他被调用的模块都需要传入这些。

我假设发生的情况可能是您的~kubespray/variables.tf 输入变量分配了默认值,这些值正在生效。如果是这种情况,那么这些应该被复制到~terraform_setup/variables.tf 并传递给调用模块:

module "kubespray" 
  source    = "../../../modules/kubespray"
  providers = 
    openstack.src = openstack
  

【讨论】:

我认为这可能是我的根本原因,我恢复了很多我的更改并从***(根)模块传递了更多内容,事情似乎很开心。谢谢。 QQ 我可以从这个根模块传递提供者变量吗?输出“输出 openstack_user_domain”? @bison 我可能没有正确理解。如果您不希望它继承一个提供者,您可以将输入传递给子模块以初始化提供者。不过,我认为除了资源上的 provider = name|alias 之外,没有其他方法可以引用提供者,因此我认为您需要找到其中一个合适的资源,为已解决的提供者配置提供输出。【参考方案2】:

在不询问更多信息的情况下,我的猜测是您传入了一个空数组 ($var.k8s_node_fips[count.index]),对于 var.node_root_volume_size_in_gbvar.number_of_k8s_nodes_no_floating_ip,其值大于 0,导致尝试索引资源声明所需的字符串的空数组。

Error: Invalid index

on ../../../modules/kubespray/modules/compute/main.tf line 670, in resource "openstack_compute_floatingip_associate_v2" "k8s_node": 670: floating_ip = "$var.k8s_node_fips[count.index]" |---------------- | count.index is 0 | var.k8s_node_fips is empty list of dynamic

根据错误,这似乎是$var.k8s_node_fips[count.index] 的插值错误。 看起来正在发生的事情是变量为空,但 count 设置为非零数字,从而导致 TF 出错。

查看原始项目代码,似乎count 变量取决于var.node_root_volume_size_in_gb 为0 才能设置为0;否则会将计数设置为 var.number_of_k8s_nodes_no_floating_ip 的值。

错误似乎发生在的片段:

resource "openstack_compute_instance_v2" "k8s_node_no_floating_ip_custom_volume_size" 
  name              = "$var.cluster_name-k8s-node-nf-$count.index+1"
  count             = "$var.node_root_volume_size_in_gb > 0 ? var.number_of_k8s_nodes_no_floating_ip : 0"
  availability_zone = "$element(var.az_list, count.index)"
  image_name        = "$var.image"
  flavor_id         = "$var.flavor_k8s_node"
  key_pair          = "$openstack_compute_keypair_v2.k8s.name"

  block_device 
    uuid                  = "$data.openstack_images_image_v2.vm_image.id"
    source_type           = "image"
    volume_size           = "$var.node_root_volume_size_in_gb"
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  

希望对你有帮助

【讨论】:

非常感谢您查看它,我理解错误告诉我的真正困惑是为什么当我从模块本身运行 terraform 时它工作正常。但是当我从调用模块的东西中运行时,它会失败。如果我不直接从模块运行,似乎 var.k8s_node_fips 无法解决

以上是关于在模块内的模块之间传递 Terraform 变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据源从一个模块引用到另一个模块并将其作为变量传递给根模块?

Terraform 模块依赖关系破坏了 template_file

传递给子模块的 terraform 提供程序不起作用

远程 terraform 模块的输出变量

Terraform 模块 - 输出变量作为另一个模块的输入

Terraform - 模块之间的依赖关系