Terraform用例创建多个几乎相同的基础架构副本

时间:2016-10-01 04:57:47

标签: terraform

我有TF模板,其目的是创建相同云基础架构的多个副本。例如,您在一个大型组织内部有多个业务部门,并且您希望构建相同的基本网络。或者,您希望开发人员能够轻松地启动他正在处理的堆栈。 " tf之间的唯一区别是"例如,invokations是变量BUSINESS_UNIT,它作为环境变量传递。

是否有其他人使用这样的系统,如果是这样,您如何管理状态文件?

3 个答案:

答案 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配置。

所以你可能会有一些现在的样子:

网络的实例/ 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}"
    }
}

分贝实例/ 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"
}

然后,您可能有不同的文件夹,每个业务部门调用这些模块:

业务单元-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}"
}

业务单元-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}"
}

您仍然需要一个包装器脚本来管理状态配置,但是通过此路由,您可以在模块中提供粗略模板,然后按业务单位硬编码某些额外配置,例如实例大小或实例数量是为他们而建的。

答案 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文件中,所以当我们不需要它们时,我们可以安全地销毁它们。

相关问题