使模块独立于提供者

时间:2021-02-20 12:27:55

标签: terraform

我的根模块中有以下代码:

provider "vsphere" {
  user           = var.vsphere_user
  password       = var.VSPHERE_PASSWORD
  vsphere_server = var.vsphere_server

  # If you have a self-signed cert
  allow_unverified_ssl = true
}

module "kubernetes_cluster_vm_pool" {
  source = "./modules/kubernetes_cluster_vm_pool"
}

module "kubernetes_cluster" {
  source = "./modules/kubernetes_cluster"
}

module "someapp" {
  source = "./modules/someapp"
}

}

第一个模块需要 VMware vSphere 的 terraform 提供程序,因此它将始终尝试连接到 vSphere。但是,我的目标是让那些不一定要使用 VMware 的人使用它,例如他们只想将某些应用程序部署到不受 VMware 虚拟机支持的 ​​kubernetes 集群。

更改代码使其不引用 VMware 提供程序仍会导致 terraform 尝试连接到 VMware,显然它仍在遍历目录结构并选择 kubernetes_cluster_vm_pool 代码。一种选择是运行 terraform init,然后在包含 someapp 模块源代码的实际目录中应用,但是 - 我想知道是否有比这更优雅的解决方案?。

1 个答案:

答案 0 :(得分:0)

一般来说,除了非常有限的模块,它根本不包含任何资源并且仅用于进行一些计算或其他数据处理使用本地值和输出值。

但是,您所描述的情况是一个很好的例子,它是使用 Module Composition 在多个配置中以不同方式使用模块的机会,如 multi-cloud abstractions 部分所述。

这种情况下的想法是编写一些仅依赖于 Kubernetes 提供者的模块和仅依赖于可托管 Kubernetes 集群的特定系统的提供者的其他模块,然后在使用这些模块的每个配置中,您可以组合特定系统的模块,具有通用的 Kubernetes-only 模块,以处理不同底层平台之间的差异。

模块组合指南包含一个使用假设模块的示例,该模块使用 azurerm 提供程序在 Azure 中创建 Kubernetes 集群,另一个假设模块将 Kubernetes 集群主机名作为参数,而无需关心底层基础架构正在托管该 Kubernetes 集群:

module "k8s_cluster" {
  source = "./modules/azurerm-k8s-cluster"

  # (Azure-specific configuration arguments)
}

module "monitoring_tools" {
  source = "./modules/monitoring_tools"

  cluster_hostname = module.k8s_cluster.hostname
}

一个单独的配置可以将相同的“监控工具”模块与一个 vSphere 风格的 Kubernetes 集群模块结合起来,以获得具有不同底层技术的等效结果:

module "k8s_cluster" {
  source = "./modules/vsphere-k8s-cluster"

  # (vSphere-specific configuration arguments)
}

module "monitoring_tools" {
  source = "./modules/monitoring_tools"

  cluster_hostname = module.k8s_cluster.hostname
}

只要这个 monitoring_tools 模块只依赖于 Kubernetes 提供者,而不依赖于 azurevsphere 提供者,那么它就可以如您所希望的那样与底层基础设施无关。


不幸的是,当将一个提供者创建的对象传递给另一个提供者时,上述情况还有一个警告:在创建 Kubernetes 集群之前,Kubernetes 提供者将无法初始化以规划任何资源位于 monitoring_tools 模块中。在这种情况下,我们可以在初始设置期间使用 Terraform 的 -target 选项让 Terraform 在尝试使用它之前先专注于创建 Kubernetes 集群:

terraform apply -target=module.k8s_cluster

此额外选项仅在初始引导时才需要,因为在后续操作中,集群通常已经存在,因此 Kubernetes 提供程序和底层基础设施提供程序可以一起初始化。

如果您最终经常做此类事情,则可以通过将特定于平台的部分和通用部分分解为使用数据源协作的单独 Terraform 配置来消除对 -target 的需要,在这种情况下您可以先terraform apply 平台特定的基础架构,启动并运行它,然后在集群运行后terraform apply 平台无关的部分。这是实现与使用 -target 相同结果的不同方法,由于不需要任何特殊的 Terraform 参数,因此通常更容易自动化。