我有TF模板,其目的是创建相同云基础架构的多个副本。例如,您在一个大型组织内部有多个业务部门,并且您希望构建相同的基本网络。或者,您希望开发人员能够轻松地启动他正在处理的堆栈。 " tf之间的唯一区别是"例如,invokations是变量BUSINESS_UNIT,它作为环境变量传递。
是否有其他人使用这样的系统,如果是这样,您如何管理状态文件?
答案 0 :(得分:5)
您应该使用Terraform Module。创建模块没什么特别之处:只需将任何Terraform模板放在一个文件夹中。模块的特殊之处在于您如何使用它。
假设您将基础架构的Terraform代码放在文件夹/terraform/modules/common-infra
中。然后,在实际定义您的实时基础架构的模板中(例如/terraform/live/business-units/main.tf
),您可以按如下方式使用该模块:
module "business-unit-a" {
source = "/terraform/modules/common-infra"
}
要为多个业务单位创建基础架构,您可以多次使用同一模块:
module "business-unit-a" {
source = "/terraform/modules/common-infra"
}
module "business-unit-b" {
source = "/terraform/modules/common-infra"
}
module "business-unit-c" {
source = "/terraform/modules/common-infra"
}
如果每个业务部门需要自定义一些参数,那么您需要做的就是在模块中定义input variable(例如在/terraform/modules/common-infra/vars.tf
下):
variable "business_unit_name" {
description = "The name of the business unit"
}
现在,每次使用模块时都可以将此变量设置为不同的值:
module "business-unit-a" {
source = "/terraform/modules/common-infra"
business_unit_name = "a"
}
module "business-unit-b" {
source = "/terraform/modules/common-infra"
business_unit_name = "b"
}
module "business-unit-c" {
source = "/terraform/modules/common-infra"
business_unit_name = "c"
}
有关详细信息,请参阅How to create reusable infrastructure with Terraform modules和 Terraform: Up & Running 。
答案 1 :(得分:2)
有两种明显的方法可以让我想到这一点。
首先,您可以沿着使用您应用的相同Terraform配置文件夹的路线,并在运行Terraform时(通过命令行或通过环境变量)简单地传入变量。您还希望拥有调用Terraform的相同包装脚本来配置您的状态设置以使它们不同。
这可能最终会出现这样的事情:
variable "BUSINESS_UNIT" {}
variable "ami" { default = "ami-123456" }
resource "aws_instance" "web" {
ami = "${var.ami}"
instance_type = "t2.micro"
tags {
Name = "web"
Business_Unit = "${var.BUSINESS_UNIT}"
}
}
resource "aws_db_instance" "default" {
allocated_storage = 10
engine = "mysql"
engine_version = "5.6.17"
instance_class = "db.t2.micro"
name = "${var.BUSINESS_UNIT}"
username = "foo"
password = "bar"
db_subnet_group_name = "db_subnet_group"
parameter_group_name = "default.mysql5.6"
}
创建EC2实例和RDS实例。然后你会用这样的东西来调用它:
#!/bin/bash
if [ "$#" -ne 1 ]; then
echo "Illegal number of parameters - specify business unit as positional parameter"
fi
business_unit=$1
terraform remote config -backend="s3" \
-backend-config="bucket=${business_unit}" \
-backend-config="key=state"
terraform remote pull
terraform apply -var 'BUSINESS_UNIT=${business_unit}'
terraform remote push
作为替代路线,您可能需要考虑使用模块来包装Terraform配置。
所以你可能会有一些现在的样子:
variable "BUSINESS_UNIT" {}
variable "ami" { default = "ami-123456" }
resource "aws_instance" "web" {
ami = "${var.ami}"
instance_type = "t2.micro"
tags {
Name = "web"
Business_Unit = "${var.BUSINESS_UNIT}"
}
}
variable "BUSINESS_UNIT" {}
resource "aws_db_instance" "default" {
allocated_storage = 10
engine = "mysql"
engine_version = "5.6.17"
instance_class = "db.t2.micro"
name = "${var.BUSINESS_UNIT}"
username = "foo"
password = "bar"
db_subnet_group_name = "db_subnet_group"
parameter_group_name = "default.mysql5.6"
}
然后,您可能有不同的文件夹,每个业务部门调用这些模块:
variable "BUSINESS_UNIT" { default = "business-unit-1" }
module "web_instance" {
source = "../web-instance"
BUSINESS_UNIT = "${var.BUSINESS_UNIT}"
}
module "db_instance" {
source = "../db-instance"
BUSINESS_UNIT = "${var.BUSINESS_UNIT}"
}
和
variable "BUSINESS_UNIT" { default = "business-unit-2" }
module "web_instance" {
source = "../web-instance"
BUSINESS_UNIT = "${var.BUSINESS_UNIT}"
}
module "db_instance" {
source = "../db-instance"
BUSINESS_UNIT = "${var.BUSINESS_UNIT}"
}
您仍然需要一个包装器脚本来管理状态配置,但是通过此路由,您可以在模块中提供粗略模板,然后按业务单位硬编码某些额外配置,例如实例大小或实例数量是为他们而建的。
答案 2 :(得分:1)
这是一个相当流行的用例。要归档它,您可以让开发人员将变量从命令行或从tfvars文件传递到资源,以使不同的资源唯一:
main.tf:
resource "aws_db_instance" "db" {
identifier = "${var.BUSINESS_UNIT}"
# ... read more in docs
}
$ terraform apply -var 'BUSINESS_UNIT=unit_name'
PS:我们经常这样做为特定的git分支名称配置基础设施,并且因为所有资源都是可识别的并且位于单独的tfstate文件中,所以当我们不需要它们时,我们可以安全地销毁它们。