Terraform 用例创建多个几乎相同的基础设施副本
Terraform use case to create multiple almost identical copies of infrastructure
我有 TF 模板,其目的是创建同一云基础架构的多个副本。例如,您在一个大组织中有多个业务部门,并且您想要构建相同的基本网络。或者您想要一种简单的方法让开发人员启动他正在处理的堆栈。 "tf apply" 调用之间的唯一区别是变量 BUSINESS_UNIT,例如,它作为环境变量传入。
还有其他人在使用这样的系统吗?如果是,您如何管理状态文件?
这是一个相当流行的用例。要存档此内容,您可以让开发人员将变量从命令行或 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 文件中,所以我们可以在不使用时安全地销毁它们不需要它们。
我想到了两种方法。
首先,您可以继续使用您应用的同一 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=
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 配置。
因此,您可能拥有现在看起来像这样的东西:
web-instance/main.tf
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}"
}
}
db-instance/main.tf
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"
}
然后您可能有不同的文件夹调用每个业务单元的这些模块:
business-unit-1/main.tf
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}"
}
和
business-unit-2/main.tf
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}"
}
您仍然需要一个包装器脚本来像以前一样管理状态配置,但是走这条路可以让您在模块中提供一个粗略的模板,然后按业务单元硬编码某些额外的配置,例如实例大小或实例数量为他们构建的实例。
你应该使用 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 and Terraform: Up & Running。
我有 TF 模板,其目的是创建同一云基础架构的多个副本。例如,您在一个大组织中有多个业务部门,并且您想要构建相同的基本网络。或者您想要一种简单的方法让开发人员启动他正在处理的堆栈。 "tf apply" 调用之间的唯一区别是变量 BUSINESS_UNIT,例如,它作为环境变量传入。
还有其他人在使用这样的系统吗?如果是,您如何管理状态文件?
这是一个相当流行的用例。要存档此内容,您可以让开发人员将变量从命令行或 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 文件中,所以我们可以在不使用时安全地销毁它们不需要它们。
我想到了两种方法。
首先,您可以继续使用您应用的同一 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=
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 配置。
因此,您可能拥有现在看起来像这样的东西:
web-instance/main.tf
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}"
}
}
db-instance/main.tf
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"
}
然后您可能有不同的文件夹调用每个业务单元的这些模块:
business-unit-1/main.tf
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}"
}
和
business-unit-2/main.tf
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}"
}
您仍然需要一个包装器脚本来像以前一样管理状态配置,但是走这条路可以让您在模块中提供一个粗略的模板,然后按业务单元硬编码某些额外的配置,例如实例大小或实例数量为他们构建的实例。
你应该使用 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 and Terraform: Up & Running。