在 Terraform 工作空间之间共享资源
Posted
技术标签:
【中文标题】在 Terraform 工作空间之间共享资源【英文标题】:Sharing resources between Terraform workspaces 【发布时间】:2019-03-07 10:37:44 【问题描述】:我正在使用 AWS 中的 Terraform 部署一个基础设施。此基础架构可以部署到不同的环境中,我正在使用工作区。
部署中的大多数组件应该为每个工作区单独创建,但我希望在它们之间共享几个关键组件,主要是:
IAM 角色和权限 他们应该使用相同的 API 网关,但每个工作区应该部署到不同的路径和方法例如:
resource "aws_iam_role" "lambda_iam_role"
name = "LambdaGeneralRole"
policy = <...>
resource "aws_lambda_function" "my_lambda"
function_name = "lambda-$terraform.workspace"
role = "$aws_iam_role.lambda_iam_role.arn"
第一个资源是一个 IAM 角色,应该在该 Lambda 的所有实例之间共享,并且不应多次重新创建。
第二个资源是一个 Lambda 函数,其名称取决于当前工作区,因此每个工作区将部署并跟踪不同 Lambda 的状态。
如何在不同的 Terraform 工作空间之间共享资源及其状态?
【问题讨论】:
【参考方案1】:对于共享资源,我在单独的模板中创建它们,然后在需要有关它们的信息的模板中使用terraform_remote_state
引用它们。
以下是我如何实现它,可能还有其他方法可以实现它。 YMMV
在共享服务模板(您将放置 IAM 角色的位置)中,我使用 Terraform 后端将共享服务模板的输出数据存储在 Consul 中。您还需要output
任何您想在其他模板中使用的信息。
shared_services 模板
terraform
backend "consul"
address = "consul.aa.example.com:8500"
path = "terraform/shared_services"
resource "aws_iam_role" "lambda_iam_role"
name = "LambdaGeneralRole"
policy = <...>
output "lambda_iam_role_arn"
value = "$aws_iam_role.lambda_iam_role.arn"
Terraform 中的“后端”决定了如何加载状态以及如何执行应用等操作。这种抽象支持非本地文件状态存储、远程执行等。
在单个模板中,您使用terraform_remote_state
将后端作为数据源调用,并且可以使用该模板中的数据。
terraform_remote_state
:
从远程后端检索状态元数据
单独的模板
data "terraform_remote_state" "shared_services"
backend = "consul"
config
address = "consul.aa.example.com:8500"
path = "terraform/shared_services"
# This is where you use the terraform_remote_state data source
resource "aws_lambda_function" "my_lambda"
function_name = "lambda-$terraform.workspace"
role = "$data.terraform_remote_state.shared_services.lambda_iam_role_arn"
参考文献:
https://www.terraform.io/docs/state/remote.html
https://www.terraform.io/docs/backends/
https://www.terraform.io/docs/providers/terraform/d/remote_state.html
【讨论】:
我没有测试过它,但我认为没有理由不应该这样做,只要terraform.tfstate
文件可用。
我刚刚尝试过,我可以确认terraform_remote_state
可以与backend = "local"
一起使用,甚至没有指定任何后端,这似乎将local
作为默认值。
就我而言,我需要检索仅存在于我的生产工作区中的资源。我在文档中发现您可以在terraform_remote_state
中指定workspace = "production"
。这很方便。
我不太明白的部分是output
的使用方式。我可以从存在该资源的工作空间中输出该资源,以便从不存在该资源的工作空间中引用它。但是,输出在不存在该资源的工作区中不起作用。我错过了什么?
我认为这实际上并不能回答涉及工作空间时的问题。它只是描述了如何从单独的状态中检索。 lambda_iam_role
仍然在每个工作区中创建,这是问题(和我自己)试图避免的。【参考方案2】:
如果name
值与已配置的资源匹配,则具有name
属性的aws_iam_role
等资源将不会创建新实例。
因此,以下将创建一个名为 LambdaGeneralRole
的 aws_iam_role
。
resource "aws_iam_role" "lambda_iam_role"
name = "LambdaGeneralRole"
policy = <...>
...
resource "aws_iam_role" "lambda_iam_role_reuse_existing_if_name_is_LambdaGeneralRole"
name = "LambdaGeneralRole"
policy = <...>
类似地,aws
提供程序将有效地创建一个 S3 bucket
名称 my-store
给定以下条件:
resource "aws_s3_bucket" "store-1"
bucket = "my-store"
acl = "public-read"
force_destroy = true
...
resource "aws_s3_bucket" "store-2"
bucket = "my-store"
acl = "public-read"
force_destroy = true
即使资源被定义为具有各自独立 Terraform 状态的不同工作区,此行为仍然有效。
要充分利用这种方法,请将共享资源定义为单独的配置。这样,您就不会冒着在运行 terraform destroy
后破坏共享资源的风险。
【讨论】:
这不会有一些副作用,比如调用“terraform destroy”会破坏多个工作空间使用的共享基础架构吗? 如果您的所有资源都在一个配置中定义,那就可以了。以上是关于在 Terraform 工作空间之间共享资源的主要内容,如果未能解决你的问题,请参考以下文章