【问题标题】:How to generalize resources etc in terraform?如何在 terraform 中概括资源等?
【发布时间】:2020-01-15 12:29:28
【问题描述】:

我一直在尝试使用 terraform 和 AWS,例如:

...
provider "aws" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region = "${var.region}"
}

resource "aws_instance" "bastion" {
  ami = "${var.image}"
  instance_type = "${var.inst_type}"
  key_name = "My Keys"
  subnet_id = "${aws_subnet.my_public_subnet.id}"
  vpc_security_group_ids = [
    "${aws_security_group.my_vpc_security_group.id}"
  ]
  tags={
    Name="${var.inst_name}"
  }
}
...

但现在我想远离 AWS,写一些与 AWS 无关但适用于所有云提供商的东西,理想情况下。有没有办法做到这一点?我真的很感激一些正确方向的指示。

===编辑===

也许我需要进一步解释一下:我并没有对例如所有内容进行全面概括。 AWS API。但是,由于大多数(如果不是全部)云环境允许您使用 Linux 创建 VM,并且还可以通过 terraform 设置一些初始配置,因此应该可以对提供程序的特定部分进行参数化,以便我可以编写基本的基础设施结构代码并指定我是否使用 AWS、Azure、Google 等作为一组参数。我的问题是我使用 terraform 的时间还不够长,无法了解如何做到这一点。

【问题讨论】:

  • 跳到解释的最后,答案是“否”的原因是这些云提供商中的每一个都有独特的 API。您将需要一个可以抽象出差异的提供者来实现这一目标。我想这将类似于以多种语言执行相同代码的多语言脚本之一。

标签: terraform


【解决方案1】:

原则上,您可以使用Module Composition 在 Terraform 中创建multi-cloud abstractions

话虽如此,您实际上只能抽象出等价的概念。 Terraform 指南中显示的一个示例是 DNS 记录:这是一个标准概念,在不同供应商中有许多不同的实现,因此定义一组约定以允许一个模块生成一组请求的 DNS 记录然后可以传递是合理的到任何一个供应商特定的 DNS 记录集模块的选择。在the terraformdns namespace of the public Terraform registry 中有一些例子(在撰写本文时主要是实验性的)。

对虚拟机服务进行抽象是一个更难的提议,因为所有供应商都没有一个清晰而明显的通用功能集。这样做需要在如何泛化方面做出一些权衡,然后您做出的决定会限制您使用供应商特定功能的能力。

相反,在跨多个供应商部署类似的基础架构时,我们通常更喜欢在更高的抽象级别上工作。例如,如果您正在跨多个云系统部署特定软件,那么您可能会为每个目标云供应商编写一个模块,封装该软件的部署,并使这些模块的输入变量和输出值相似足以让它们以合理的方式相互替代。

举一个具体的例子,也许你的抽象单元可能是一个 Kubernetes 集群,因此你可以编写多个模块,这些模块都会导致 Kubernetes API 主机名被导出为输出,但在内部它们可以使用数字生成诸如供应商托管的 Kubernetes 服务、用于开发的 minikube 部署等方法。在这种情况下,所有这些模块最终都会产生一个正常运行的 Kubernetes API,您可以为每个配置选择使用其中的哪一个。

【讨论】:

    【解决方案2】:

    可能可以使用modules 构建一些东西。您可以尝试构建一个与云无关的VM 模块,并根据一些开关决定云提供商。

    然而,这并不是 Terraform 的真正设计目的,所以它可能会变得一团糟。

    resource "azurerm_virtual_machine" "main" {
      name                  = "${var.prefix}-vm"
      count                  = "${var.deployToAzure ? 1 : 0}"
      ...
    }
    
    resource "aws_instance" "web" {
      ami           = "${data.aws_ami.ubuntu.id}"
      instance_type = "t2.micro"
      count         = "${var.deployToAws ? 1 : 0}"
    }
    
    

    作为更现实的第一步,您可以围绕这些 VM 资源构建自己的模块。因此,您将拥有一个 Azure VM 模块,AWS 也是如此。如果您努力为这些模块保留类似的接口,您的实际基础架构代码将更少依赖云提供商。

    【讨论】:

      【解决方案3】:

      这不可能概括解决方案。不同的云技术有不同的产品和不同的 API 供他们连接。这就是 terraform 在启动时要求提供者信息的原因,以便它可以加载特定的提供者 SDK 以与 API 通信。

      【讨论】:

      • 我认为这听起来不太合理。我所追求的不是对所有事物的全面概括,而只是对一些共同特征的概括;毕竟,大多数(如果不是全部)云提供商都允许您使用 Linux 创建虚拟机,并且拥有用于进行一些初始设置的机制,因此可以使用 cloud-init 或 puppet 之类的工具。
      猜你喜欢
      • 2022-10-23
      • 2022-11-08
      • 2020-12-14
      • 2021-09-30
      • 2022-01-15
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多