如何以云不可知的方式使用Terraform

Sam*_*amy 13 azure amazon-web-services terraform

我已经看到很多关于如何使用Terraform启动AWS资源的示例.我也看到很多声称Terraform是云不可知的.

我没有看到的是我如何使用单个tf文件在AWS或Azure中使用某些子网,某些实例,某些ELB以及一些数据库启动VPC的示例.

有没有人有这样的例子?

yda*_*coR 17

虽然Terraform作为一种工具是云不可知的(因为它将支持暴露其API的任何东西,并且有足够的开发人员支持来为它创建"提供者"),Terraform本身根本就不会抽象这一点,我会认真考虑是否除非你有一个非常好的用例,否则这是一个好主意.

如果您确实需要这样做,您需要在模块用户抽象云层的事物之上构建一堆模块,并允许他们将云提供者指定为变量(可能从某些外部脚本控制).

作为抽象DNS的基本示例,您可能会遇到类似这样的事情(未经测试):

模块/谷歌/ DNS /记录/ main.tf

variable "count" = {}

variable "domain_name_record" = {}
variable "domain_name_zone" = {}
variable "domain_name_target" = {}

resource "google_dns_record_set" "frontend" {
  count = "${variable.count}"
  name  = "${var.domain_name_record}.${var.domain_name_zone}"
  type  = "CNAME"
  ttl   = 300

  managed_zone = "${var.domain_name_zone}"

  rrdatas = ["${var.domain_name_target}"]
}
Run Code Online (Sandbox Code Playgroud)

模块/ AWS/DNS /记录/ main.tf

variable "count" = {}

variable "domain_name_record" = {}
variable "domain_name_zone" = {}
variable "domain_name_target" = {}

data "aws_route53_zone" "selected" {
  count = "${variable.count}"
  name  = "${var.domain_name_zone}"
}

resource "aws_route53_record" "www" {
  count   = "${variable.count}"
  zone_id = "${data.aws_route53_zone.selected.zone_id}"
  name    = "${var.domain_name_record}.${data.aws_route53_zone.selected.name}"
  type    = "CNAME"
  ttl     = "60"
  records = [${var.domain_name_target}]
}
Run Code Online (Sandbox Code Playgroud)

模块/通用/ DNS /记录/ main.tf

variable "cloud_provider" = { default = "aws" }

variable "domain_name_record" = {}
variable "domain_name_zone" = {}
variable "domain_name_target" = {}

module "aws_dns_record" {
  source             = "../../aws/dns/record"
  count              = "${var.cloud_provider == "aws" ? 1 : 0}"
  domain_name_record = "${var.domain_name_record}"
  domain_name_zone   = "${var.domain_name_zone}"
  domain_name_target = "${var.domain_name_target}"
}

module "google_dns_record" {
  source             = "../../google/dns/record"
  count              = "${var.cloud_provider == "google" ? 1 : 0}"
  domain_name_record = "${var.domain_name_record}"
  domain_name_zone   = "${var.domain_name_zone}"
  domain_name_target = "${var.domain_name_target}"
}
Run Code Online (Sandbox Code Playgroud)

显然,这将变得非常复杂,但它确实意味着您可以将"通用"模块暴露给其他人并允许他们使用您正在构建的事物上的抽象.如何处理不同云之间没有特征奇偶校验的问题是一个完全独立的问题,可能不是最适合StackOverflow的问题.


小智 5

@ydaetskcoR我喜欢您对提供者特定模块的想法(遵循接口)。但是我建议的更改是,可以直接在main.tf文件中使用其中的变量来调用它们以确定模块源。

所以我会保留:
modules / google / dns / record / main.tf
modules / aws / dns / record / main.tf

我不会使用modules / generic / dns / record / main.tf

并添加:
main.tf

variable "cloud_provider" = { default = "aws" }  
module "dns" {  
  source = "modules/${var.cloud_provider}/dns/record/main.tf"  
  domain_name_record = "${var.domain_name_record}"  
  domain_name_zone   = "${var.domain_name_zone}"  
  domain_name_target = "${var.domain_name_target}"  
}
Run Code Online (Sandbox Code Playgroud)

不幸的是Terraform不支持​​可变模块源。
参见:https : //github.com/hashicorp/terraform/issues/1439

我正在考虑添加插件或什至更高级别的模板抽象的方法。