在Terraform中,如何使用另一个部署&x27;谁的资源?
地形v0.12.x 这是我另一篇文章的后续问题 我有两个模块,旨在重用其他模块。我的目录结构是在Terraform中,如何使用另一个部署&x27;谁的资源?,terraform,terraform-provider-aws,Terraform,Terraform Provider Aws,地形v0.12.x 这是我另一篇文章的后续问题 我有两个模块,旨在重用其他模块。我的目录结构是 /terraform/ /terraform/blue/main.tf /terraform/green/main.tf /terraform/module_snapshot/main.tf /terraform/module_ebs/main.tf 我想在两次部署之间重复使用模块\u ebs/main.tf,蓝色/main.tf和绿色/main.tf。确实如此 resource "aws
/terraform/
/terraform/blue/main.tf
/terraform/green/main.tf
/terraform/module_snapshot/main.tf
/terraform/module_ebs/main.tf
我想在两次部署之间重复使用模块\u ebs/main.tf
,蓝色/main.tf
和绿色/main.tf
。确实如此
resource "aws_ebs_volume" "ebs" {
availability_zone = "us-east-1a"
snapshot_id = "sn-123456abcded"
size = 500
type = "gp2"
tags = {
Name = "test-ebs"
}
}
output "ebs_id" {
value = aws_ebs_volume.ebs.id
description = "Volume id of the EBS volume"
}
其思想是green/main.tf
使用module\u EBS/main.tf
(它有一个名为EBS\u id
的输出)创建一个EBS卷
现在我想blue/main.tf
拍摄格林的EBS卷的快照,所以我这样做了
provider "aws" {
region = "us-east-1"
}
terraform {
required_version = ">= 0.12.17, < 0.13"
backend "s3" {
bucket = "my-terraform-states"
key = "test-modules/terraform.tfstate"
region = "us-east-1"
}
}
module "green" {
source "../module"
}
module "snapshot" {
source "../module_snapshot"
green_ebs_id = module.green.green_ebs_id
}
output "blue_ebs_id" {
value = module.blue_ebs.ebs_id
}
如何使用其他部署的资源而不销毁和重新创建它们?如果您可以使用外部“启动程序”脚本(bash、jq等),那么您肯定可以实现这一点。 第一次运行后,将创建一个
terraform.tfstate
文件。它包含所有已创建资源及其ID的描述。
使用初学者脚本,您可以迭代状态文件,提取必要的id,并使用
terraform import{module_2_resource_name}{module_1_resource_id}
将资源导入新模块。您还可以尝试使用terraform import-state=path
直接重用其他状态文件。但是你应该小心。模块1和模块2中资源的定义应相同,以避免破坏。实现这一点的方法有几种不同的变体,它们在考虑隐式关系和显式接口等方面有一些不同的权衡
一种常见的方法是建立一些约定,通过这些约定,下游配置可以使用数据源间接查找由上游配置创建的对象。在您的情况下,这可能涉及为两种配置都同意的EBS卷设计标记方案,以便第二种配置可以找到由第一种配置创建的对象
在第一个配置中:
resource "aws_ebs_volume" "ebs" {
availability_zone = "us-east-1a"
snapshot_id = "sn-123456abcded"
size = 500
type = "gp2"
tags = {
Name = "production-appname"
}
}
data "aws_ebs_volume" "example" {
filter {
name = "tag:Name"
values = ["production-appname"]
}
}
在第二种配置中:
resource "aws_ebs_volume" "ebs" {
availability_zone = "us-east-1a"
snapshot_id = "sn-123456abcded"
size = 500
type = "gp2"
tags = {
Name = "production-appname"
}
}
data "aws_ebs_volume" "example" {
filter {
name = "tag:Name"
values = ["production-appname"]
}
}
本例中的约定是“Name”标记的值为“production appname”。对于您的目的来说,这可能不是正确的约定,但它展示了总体思路。然后,第二个配置可以通过data.aws\u ebs\u volume.example.id
访问该id
provider "aws" {
region = "us-east-1"
}
terraform {
required_version = ">= 0.12.17, < 0.13"
backend "s3" {
bucket = "my-terraform-states"
key = "test-modules/terraform.tfstate"
region = "us-east-1"
}
}
module "green_ebs" {
source "../module_ebs"
}
output "green_ebs_id" {
value = module.green_ebs.ebs_id
}
正如我在开场白中提到的,上述方法进行了一些设计权衡:
- 耦合度相对较低,因为第二个模块只需要以前创建的带有特定标记的EBS卷,因此您可以稍后重构系统,以便在不同的Terraform配置中创建EBS卷,或者使用Terraform以外的其他软件,下游无任何变化
- 然而,这两者之间的联系是隐式的,因为它依赖于共享约定而不是显式接口。这可能会使整个系统架构更难理解,除非您小心地将这些隐式约定记录在您的团队知道要查看的地方
另一种变体是让上游配置明确地将信息发布到专门用于此目的的配置存储中。例如,在AWS中,您可以使用AWS SSM参数存储,该存储在地形中使用
AWS\u SSM\u参数
托管资源类型和数据源表示:
resource "aws_ssm_parameter" "foo" {
name = "appname_ebs_volume_id"
type = "String"
value = aws_ebs_volume.ebs.id
}
这里两种配置之间也有一个共享约定,但约定是写入专门用于存储配置的位置,因此“集合点”(本例中为SSM参数)在上游和下游配置中都有明确表示,保持相似的耦合水平,但增加明确性
最后一个选择是利用大多数“真实”地形配置的状态快照保存在远程网络位置这一事实。
terraform\u remote\u state
数据源是一个特殊的数据源,它从远程位置读取状态快照并提取存储在那里的根模块输出,因此您可以在其他地方使用该数据。因此,只要应用第二个模块的每个人都有足够的权限从第一个模块读取最新的状态快照,就可以使用您在第一个模块中声明的输出来填充第二个模块中的资源配置
我认为,第三种选择与第一种选择相反:
- 耦合度高,因为下游配置被配置为直接从其他配置的状态读取该值。如果以后要重构EBS卷并将其移动到不同的Terraform配置或使用其他软件进行管理,则需要编辑第二个配置以向其传授有关新源的知识
- 然而,这可能是最明确的选项,因为EBS卷ID显然是故意从第一个配置导出的,作为一个值供其他地方使用,而第二个配置准确地描述了哪个子系统负责生成该值
在所有情况下,这些选项都是“正确的”或“错误的”,但我个人认为第二个选项是其他两个之间的一个很好的折衷方案,因为它调和了两个相互竞争的设计考虑。选择哪一个取决于您试图描述的系统的目标和约束,但我认为如果您的案例中没有明确的“赢家”,那么第二个是一个很好的默认值 在Terraform documentation guide(地形文档指南)中,有一些关于减少耦合和以灵活方式分解系统的技术的一般指导。这并不是专门关于在多个单独的地形配置中拆分基础设施,但是这里描述的技术可以帮助您进行设置,以便您可以使用更多的EA
data "aws_ssm_parameter" "foo" {
name = "appname_ebs_volume_id"
}