如何强制用户指定`-target=module。<;环境>;`运行“terraform应用”时?

如何强制用户指定`-target=module。<;环境>;`运行“terraform应用”时?,terraform,Terraform,我有一个在AWS上提供web服务的terraform脚本 现在我想在不同的环境(生产、阶段、开发等)中重用这个脚本 以下是我的文件夹结构: . ├── main.tf └── core_module     ├── outputs.tf    ├── my_service.tf    └── variables.tf main.tf包含如下内容: module "prod-service" { source = "./core_module" env_specific_variab

我有一个在AWS上提供web服务的terraform脚本

现在我想在不同的环境(生产、阶段、开发等)中重用这个脚本

以下是我的文件夹结构:

.
├── main.tf
└── core_module
    ├── outputs.tf
    ├── my_service.tf
    └── variables.tf
main.tf
包含如下内容:

module "prod-service" {
  source = "./core_module"
  env_specific_variable = "this is a production environment"
  ...
}

module "stage-service" {
  source = "./core_module"
  env_specific_variable = "this is a stage environment"
  ...
}

module "dev-service" {
  source = "./core_module"
  env_specific_variable = "this is a dev environment"
  ...
}
当我想在生产环境中创建服务时,我运行

terraform apply -target=module.prod-service \
  -var 'access_key=<prod_access_key>' \
  -var 'secret_key=<prod_secret_key>' \
  -var 'region=<prod_region>
terraform应用-target=module.prod-service\
-var“access\u key=”\
-var'secret\u key='0\
-var'区=
当我想在后台环境中创建服务时,我运行

terraform apply -target=module.stage-service \
  -var 'access_key=<stage_access_key>' \
  -var 'secret_key=<stage_secret_key>' \
  -var 'region=<stage_region>
terraform应用-target=module.stage-service\
-var“access\u key=”\
-var'secret\u key='0\
-var'区=
如何强制此脚本的用户添加
-target
选项,使其不会在一个命令中创建所有环境


由于不同的环境需要不同的
aws\u access\u key\u id
aws\u secret\u access\u key
,因此运行
terraform apply来创建所有环境将产生错误。

可以强制设置或验证变量。我不知道如何在
target
命令行属性中强制执行某些内容。你必须使用。改为使用变量,然后更改main.tf,使其仅部署特定于环境的模块版本,并检查该变量是否存在

然而,看起来您并没有按照预期的方式使用Terraform。有一个称为工作区的概念,您应该使用它来管理不同环境的状态,而不是在一个脚本中为所有不同的环境创建重复的资源

要创建新的工作区,请使用

terraform workspace新开发项目
terraform workspace新登台

创建该环境的变量文件

development.tfvars

variable env_specific_variable {
  default = "this is a dev environment"
}
t.tfvara

variable env_specific_variable {
  default = "this is a staging environment"
}
然后在main.tf中只部署模块的一个实例,并使用特定于工作区的环境而不是文本字符串

main.tf

module "my-service" {
  source = "./core_module"
  env_specific_variable = var.env_specific_variable
  ...
}
要部署开发,请使用

terraform workspace select development
terraform apply
要部署暂存,请使用

terraform workspace select staging
terraform apply
请注意,我正在手机上键入此内容,但尚未运行此操作。根据您的TF版本,可能会出现打字错误或语法问题

资源:
(关于常规的好文章,但请特别查看关于隔离工作区的部分)

这不是
-target
参数适用的内容。明确指出
-target
参数仅适用于异常情况,并给出了一些建议:

这种瞄准能力是为特殊情况提供的,例如从错误中恢复或绕过地形限制。不建议在日常操作中使用
-target
,因为这可能会导致未检测到的配置漂移,并混淆资源的真实状态与配置之间的关系

与其使用
-target
作为在非常大的配置的孤立部分上操作的手段,不如将大型配置分解为几个较小的配置,每个配置都可以独立应用。数据源可用于访问有关在其他配置中创建的资源的信息,从而允许将复杂的系统体系结构分解为可独立更新的更易于管理的部分

在您的情况下,我建议将每个环境设置为一个单独的地形配置,并具有自己单独的地形状态。由于您已将环境分解为一个共享模块,因此每个模块将仅包含调用它的
模块
块:

module "service" {
  source = "../../modules/core"
  env_specific_variable = "this is a production environment"
  ...
}
此方法的常见目录结构是:

environments/
  prod/
    main.tf
  stage/
    main.tf
  dev/
    main.tf
modules/
  core/
    variables.tf
    service.tf
    outputs.tf
要将更改应用于特定环境,请执行以下操作:

cd environments/prod
terraform init
terraform apply

通过像这样配置Terraform,您可以避免强制用户以标准方式使用Terraform向其Terraform执行中添加额外选项的需要。独立的环境配置还有其他好处,例如,如果您想在更改生产配置之前先在登台环境中尝试推出新版本,则可以在不同的环境中使用不同的提供程序版本。

@Martim Atkins在我的回答中,使用每个环境的文件夹与使用每个环境的工作区相比,有什么好处?我最近见过你的模式好几次,但对我来说是新的。我在你的答案中看到了使用文件夹的好处,但是你可以在工作空间中做同样的事情。这不是一个批评,我真的在努力学习。这里面有一些更长的信息。简单的回答是:工作空间只分隔状态,而不是输入变量或后端配置。