我一直在试验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无关的东西,但最好是适用于所有云提供商。有没有办法做到这一点?我非常希望能有几个正确方向的指点。
=== EDIT ===
也许我需要进一步解释一下:例如,我并没有对所有内容进行全面概括。 AWS API。但是,由于大多数(如果不是全部)云环境都允许您使用Linux创建VM,并且还具有通过terraform设置一些初始配置的方法,因此应该可以对提供程序的特定部分进行参数设置,以便编写基本的基础架构结构代码,并指定是否将AWS,Azure,Google等用作一组参数。我的问题是我对terraform的研究还不够长,以了解如何做到这一点。
答案 0 :(得分:1)
您 也许可以使用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的相同模块。如果您努力为这些模块保留相似的接口,那么您实际的基础架构代码将减少对云提供商的依赖。
答案 1 :(得分:1)
原则上,您可以使用multi-cloud abstractions在Terraform中创建Module Composition。
话虽如此,您实际上只能对等同的概念进行抽象。 Terraform指南中显示的示例是DNS记录:这是一个标准概念,在不同的供应商之间有许多不同的实现,因此定义一组约定以允许一个模块生成一组请求的DNS记录然后可以将其传递是合理的特定于特定于供应商的DNS记录集模块之一。 the terraformdns
namespace of the public Terraform registry中有一些示例(大多数是实验性的,在撰写本文时)。
对虚拟机服务进行抽象是一个更艰难的主张,因为在所有供应商之间都没有清晰明显的通用功能集。要做到这一点,就需要就如何概括进行一些权衡,然后您做出的决定将限制您使用供应商特定功能的能力。
相反,当在多个供应商之间部署相似的基础结构时,我们通常更喜欢在更高的抽象层次上工作。例如,如果您要在多个云系统之间部署特定的软件,则可以为每个目标云供应商编写一个模块,以封装该软件的部署,并使这些模块的输入变量和输出值相似足以让他们以合理的方式相互替代。
举一个具体的例子,也许您的抽象单元可能是一个Kubernetes集群,所以您可以编写多个模块,所有这些模块都会导致Kubernetes API主机名作为输出导出,但是在内部它们可以使用数字产生该模块。诸如供应商的托管Kubernetes服务,用于开发的minikube部署之类的方法。在这种情况下,所有这些模块最终都会产生可运行的Kubernetes API,您可以为每种配置选择使用哪种模块。
答案 2 :(得分:0)
这不可能概括解决方案。不同的云技术具有不同的产品和不同的API供他们连接。这就是terraform在开始时要求提供程序信息的原因,以便它可以加载特定的提供程序SDK以便与API通信。