Chr*_*s F 2 terraform terraform-provider-aws
Terraform v0.12.x
这是我另一篇文章如何使用 Terraform 模块进行代码重用的后续问题?.
我有 2 个模块,旨在重用其他模块。我的目录结构是...
/terraform/
/terraform/blue/main.tf
/terraform/green/main.tf
/terraform/module_snapshot/main.tf
/terraform/module_ebs/main.tf
Run Code Online (Sandbox Code Playgroud)
我想module_ebs/main.tf
在两次部署之间重复使用,blue/main.tf
并且green/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"
}
Run Code Online (Sandbox Code Playgroud)
这个想法是使用green/main.tf
创建一个 EBS 卷module_ebs/main.tf
(它有一个名为 的输出ebs_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
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我得到了所需的 EBS 音量
$ cd /terraform/green
$ terraform plan -out out.o
$ terraform apply "out.o"
green_ebs_id = "vol-123456abcdef"
Run Code Online (Sandbox Code Playgroud)
现在我想拍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
}
Run Code Online (Sandbox Code Playgroud)
然而,当我运行上面的脚本时,它(当然)green/main.tf
也会运行,这当然会破坏它的 EBS 卷并创建另一个,这不是我想要做的。
$ cd /terraform/blue
$ terraform plan -out out.o
# module.green.aws_ebs_volume.ebs will be destroyed
- resource "aws_ebs_volume" "ebs" {
...
}
Run Code Online (Sandbox Code Playgroud)
如何在不破坏和重新创建其他部署的资源的情况下使用它们?
如何实现这一点有几种不同的变体,它们对耦合和隐式关系与显式接口等考虑因素有一些不同的权衡。
一种常见的方法是建立一些约定,通过这些约定,下游配置可以使用数据源间接找到由上游配置创建的对象。在您的情况下,这可能涉及为您的 EBS 卷设计一个两个配置都同意的标记方案,以便第二个配置可以找到第一个配置创建的对象。
在第一个配置中:
resource "aws_ebs_volume" "ebs" {
availability_zone = "us-east-1a"
snapshot_id = "sn-123456abcded"
size = 500
type = "gp2"
tags = {
Name = "production-appname"
}
}
Run Code Online (Sandbox Code Playgroud)
在第二种配置中:
data "aws_ebs_volume" "example" {
filter {
name = "tag:Name"
values = ["production-appname"]
}
}
Run Code Online (Sandbox Code Playgroud)
本示例中的约定是“Name”标签的值为“production-appname”。对于您的目的,这可能不是完全正确的约定,但它展示了总体思路。然后第二个配置可以通过data.aws_ebs_volume.example.id
.
正如我在开篇中提到的,上述方法进行了一些设计权衡:
另一个变体是让您的上游配置明确地将信息发布到专门用于该目的的配置存储中。例如,在 AWS 中,您可能会使用 AWS SSM Parameter Store,它在 Terraform 中使用aws_ssm_parameter
托管资源类型和数据源表示:
resource "aws_ssm_parameter" "foo" {
name = "appname_ebs_volume_id"
type = "String"
value = aws_ebs_volume.ebs.id
}
Run Code Online (Sandbox Code Playgroud)
data "aws_ssm_parameter" "foo" {
name = "appname_ebs_volume_id"
}
Run Code Online (Sandbox Code Playgroud)
同样在这里,两个配置之间有一个共享约定,但约定是写入一个专门用于存储配置的位置,因此“集合点”(在这种情况下为 SSM 参数)在两个上游都清楚地表示和下游配置,保持类似的耦合水平,但增加了明确性。
最后一个选择是利用大多数“真实”Terraform 配置将其状态快照保存在远程网络位置这一事实。所述terraform_remote_state
数据源是从远程位置读取状态快照,并提取存储在那里的根模块输出,所以可以在其他地方使用该数据的专用数据源。因此,您可以利用您已经在第一个模块中声明的输出来填充第二个模块中的资源配置,只要应用第二个模块的每个人都有足够的权限从第一个模块读取最新的状态快照。
我认为,这第三个选项与第一个选项具有相反的权衡:
在所有情况下,这些选项都不是“正确”或“错误”的,但我个人认为第二个选项是其他两个选项之间的一个很好的折衷方案,因为它缓和了两个相互竞争的设计考虑因素。选择哪一个取决于您要描述的系统的目标和约束,但我认为如果您的情况没有明确的“赢家”,则第二个是一个很好的默认设置。
Terraform 文档指南Module Composition 中提供了一些关于以灵活方式减少耦合和分解系统的技术的一般指导。这并不是专门关于在多个单独的 Terraform 配置之间拆分基础设施,但是那里描述的技术可以帮助您进行设置,以便您可以更轻松地更改以后如何分解系统的决定,以便您可以推迟添加多个单独的配置的复杂性配置,直到您发现真正需要这样做。
归档时间: |
|
查看次数: |
268 次 |
最近记录: |