设置

我选择该主题是因为我最近发现了这篇文章: 推荐做法 。 Hashicorp建议使用工作区来控制不同的环境。 与我从2019年2月/ 3月以来所记得的相比,这是对建议的更改。

第一种方式–具有工作空间的单一帐户

早在2019年初,我就开始将Terraform用于一个AWS项目。 我正在做的基础结构的基础与我之前从事的项目(都在Clojure中 )非常相似,但是该项目大量使用bash脚本来处理ELB环境的创建。 您不想对所有内容都使用bash脚本,这很痛苦,混乱……令人沮丧。 因此,我决定学习和使用Terraform。 Terraform很棒(不完美,到处都是小问题)。 因为在该项目中我只有一个AWS账户(现在我知道更好),所以我需要找到一种将多个环境部署到单个账户中的方法。 为此,我使用了工作区 。 使用工作区时,您使用一组文件,然后对可以更改的数据/变量有两个选择,或者使用不同的tfvar文件,每个环境一个,将其作为参数传递给Terraform调用(例如, terraform plan -var-file=env.dev.tfvars )。

例如, env.dev.tfvars可以包含

retention_policy = 7

并且prod.env.tfvars将包括

retention_policy = 365

我使用的另一个选项是创建具有必要值的映射,然后使用查找功能来获取信息,因此tf文件上的代码如下所示:

variable "workspace_to_retention_policy_map" {
  description = "The retention period of cloudwatch logs"
  type = map
  default = {
    dev     = 7
    staging = 7
    prod    = 365
  }
}

locals {
  retention_policy  = lookup(var.workspace_to_retention_policy_map, terraform.workspace, 7)
  # or even better if you don't need the default
  retention_policy2 = var.workspace_to_retention_policy_map[terraform.workspace]
}

我实际上喜欢将每个环境的值一起更改,因此很容易看出环境之间的变化,但确实会在文件中产生更多的干扰。

那时,不建议将工作空间用于多个环境。 您必须非常清楚何时进行terraform workspace select ,或者最好仅通过CI来执行,因此您不会犯任何错误。

第二种方式–多个帐户,单个工作空间

在我当前的项目中,我们正在使用不同的方法。 每个环境都有一个AWS账户。 我们本可以使用相同的工作空间设置,但是由于状态使用S3存储在AWS账户上,因此情况变得复杂(解决方案,下一部分)。

因此,方法是有一个environments文件夹,并在每个环境的文件夹内(开发,测试,生产或使用的任何内容)。 每个文件夹都有相同的文件(变量文件,输出文件,主/设置文件)。 因为您应该使所有环境看起来都相同(或非常相似),所以可以对这些文件进行符号链接,并为需要更改的数据添加一个tfvars文件(与我们在第一种方法中看到的没什么不同)。 可以将仅存在于环境中的任何基础结构添加到其他文件中。 你会有这样的事情

- environments
|- dev
|  |- Main.tf
|  |- variables.tf
|  |- outputs.tf
|  |- dev.env.tfvars
|- test
|  |- main.tf -> ../dev/main.tf
|  |- variables.tf -> ../dev/variables.tf
|  |- outputs.tf -> ../dev/outputs.tf
|  |- test.env.tfvars
|- prod
|  |- main.tf -> ../dev/main.tf
|  |- variables.tf -> ../dev/variables.tf
|  |- outputs.tf -> ../dev/outputs.tf
|  |- prod.env.tfvars
|  |- prod.unique.tf

与工作区不同,在这里犯错是非常困难的。 毕竟,您需要导航到正确的文件夹,然后才能执行Terraform命令。 而且符号链接会继续检查您需要注意的文件数量(否则这将是此方法的一大弊端)。

第三种方式–多个帐户,多个工作区

但是,等等-您说-这是否意味着我不能使用具有多个帐户的工作区? 好吧,当然不会。 上述方法基于以下事实:我们将每个帐户内的每个帐户的Terraform状态保持不变。 但是,如果您切换到单个集中位置,则不会有问题,因此可以在多个帐户上使用工作区。 Terraform为此专门使用了大量后端: Artifactory , Consul , etcd v2和etcd v3 ,一些“随机” http rest , swift , Postgres和他们自己的Terraform Enterprise 。

我可以将单个s3后端使用与系统其余部分不同的配置文件(不同的帐户)吗? 好吧,是的,后端可以使用与其余设置不同的凭据。 实际上,我最近发现,您可以有多个提供程序(同一帐户的混合帐户或多个帐户),为它们提供不同的别名,并为每种资源选择要使用的提供程序。

让我们在这里向您展示一些非常快速的代码,以了解如何使用诸如Azure Blob存储之类的集中状态存储(主要是因为我无权访问“适当的”存储,但我可以访问Codurance Azure游乐场)帐户)。

首先是remote.tf文件,在该文件上我们指示将在哪里存储所有工作区的状态

terraform {
  backend "azurerm" {
    resource_group_name  = "Jorge-Terraform-Test"
    storage_account_name = "jorgeterraformtest"
    container_name       = "terraformstate"
    key                  = "terraform.tfstate"
  }
}

我正在使用az login流程进行测试。 但是在实际的产品基础上,您想使用主体。

然后是variables.tf文件,其中包含我对此快速测试所关心的唯一变量

variable "profile" {
  type=string
}

然后是主文件: resource.tf

provider "aws" {
  version = "~> 2.0"
  region  = "us-east-1"
  profile = var.profile
}

# Create a VPC
resource "aws_vpc" "example" {
  cidr_block = "172.35.0.0/16"

  tags = {
    Name = "jorge's test"
  }
}

最后,对于该测试,我选择使用两个单独的tfvars文件;

dev.env.tfvars

profile="codurance-playground"

prod.env.tfvars

profile="codurance"

Terraform使用该配置文件来检查我的AWS凭证文件。

最后,要使此工作空间设置更容易实现,您将使用在第一部分中将需要的相同命令。 但是现在我可以处理单独的帐户,因为我使用的是单个集中状态位置。

选择什么

哎呀……这取决于。 您想要或需要哪种分隔? 如果您使用的是模块 ,那么工作区将更难处理,因为Terraform似乎没有提供模块的条件设置。 但是,如果您在所有环境中都使用完全相同的设置,则工作区看起来会稍微干净一些。

翻译自: https://www.javacodegeeks.com/2020/04/terraform-with-multiple-environments.html