Terraform:在同一类型上同时使用数据源和资源有啥意义?
Posted
技术标签:
【中文标题】Terraform:在同一类型上同时使用数据源和资源有啥意义?【英文标题】:Terraform: What's the point using Both Data Source and Resource on the same type?Terraform:在同一类型上同时使用数据源和资源有什么意义? 【发布时间】:2019-07-14 11:30:53 【问题描述】:我是 Terraform 的新手,我正在开发一个在 AWS 上使用 Docker/AWS ECR/ECS 基础设施的项目。我看到in this post,作者在其中指定了类似
data "aws_ecs_task_definition" "test"
task_definition = "$aws_ecs_task_definition.test.family"
depends_on = ["aws_ecs_task_definition.test"]
resource "aws_ecs_task_definition" "test"
family = "test-family"
# ...
为什么他在aws_ecs_task_definition
上同时使用数据源和资源?在深入研究官方文档和谷歌搜索文章数小时后,我找不到解释或类似的例子。
我稍后看到他在设置服务时,使用以下代码来引用它们:(再次,我不确定这里发生了什么)
task_definition = "$aws_ecs_task_definition.test.family:$max("$aws_ecs_task_definition.test.revision", "$data.aws_ecs_task_definition.test.revision")"
我现在对在同一类型上同时使用数据和资源与仅使用资源有什么区别感到困惑。生命周期方面有什么区别吗?
我现在正在尝试为我的 docker 映像创建 AWS ECR,并且我希望 terraform 来管理它(创建/更新/销毁),我是否应该同时使用 aws_ecr_repository
类型的数据源和资源?
【问题讨论】:
资源创建它,数据源检索它。 在上面的示例中,没有理由同时使用data
和resource
。我不得不假设您查看的材料是出于教育原因这样做的。我这样做的一个原因是为了 EBS 快照,所以如果有人在控制台中制作了比 Terraform 制作的更新的快照,则在必要时使用最新的快照。
@victorm 感谢您的解释,这个顺序是有道理的,我猜这就是terraform apply
第一次执行时的作用。但是当我第二次执行terraform apply
时,重新创建资源和数据源检索它的位置是否相同?我之所以这样问,是因为我正在考虑在进行更改后重建 docker 映像,并且想要更新基础架构。
@MattSchuchard 感谢您提供示例,我认为这可以说明问题。您能详细解释一下 EBS 快照吗?是这样的吗:使用 Terraform 创建基础设施后,我使用 AWS CodePipeline 链接到我的 github 源代码存储库。一旦我将新代码推送到 github 存储库,就会触发 AWS CodePipeline 并更新任务定义。这会创建 EBS 快照吗?这是否是同时需要数据源和资源的原因?
Terraform 是幂等的,当您再次运行它时,除非您对其进行更改,否则不会更新任何内容。读取仍然会发生。请记住,如果您对某些资源进行更改,则会创建一个新资源。我不记得 task_definition 是否是其中之一。如果创建了一个新的,您必须更新您的任务服务以使用新的。
【参考方案1】:
这是有道理的。这家伙正在使用数据源来获取最新的任务定义修订。这是因为他可能正在使用其他一些工具(jenkins/circleci)来推动对任务定义或修订的更改。
因此,如果他再次运行该代码,那么 terraform 应该选择最新版本并相应地更新 ecs 服务。
检查以下代码:
resource "aws_ecs_service" "test-ecs-service"
name = "test-vz-service"
cluster = "$aws_ecs_cluster.test-ecs-cluster.id"
task_definition = "$aws_ecs_task_definition.test.family:$max("$aws_ecs_task_definition.test.revision", "$data.aws_ecs_task_definition.test.revision")"
desired_count = 1
iam_role = "$aws_iam_role.ecs-service-role.name"
load_balancer
target_group_arn = "$aws_alb_target_group.test.id"
container_name = "nginx"
container_port = "80"
他正在使用最新版本更新服务。他正在使用返回最大值的 MAX 函数。您可以检查 terraform 插值语法,here。
如果任务定义不存在,这个 terraform 脚本会创建它吗?
是的,它将根据状态文件中的任务定义创建它。如果您手动创建了任务定义,那么它将增加修订号。
如果任务定义存在并且数据源块检索到它,资源块会重新创建另一个修改后的任务定义,还是什么都不做?
如果资源的任何配置发生变化,那么它将创建新的任务定义,并且该任务定义将分配给 ecs 服务资源,但如果资源没有变化,则它什么也不做。
我也不清楚这个 terraform 脚本是打算只运行一次(初始基础设施创建)还是在更改时运行?
这应该在创建基础设施时运行,或者如果您想对任务定义资源进行任何其他更新。
【讨论】:
感谢您的指出,这解决了我的很多困惑。我想我仍然不清楚的是,如果任务定义不存在,这个 terraform 脚本会创建它吗?如果任务定义存在并且数据源块检索到它,资源块会重新创建另一个修改后的任务定义,还是什么都不做?我也不清楚这个 terraform 脚本是打算只运行一次(初始基础设施创建)还是在更改时运行? 我已经更新了答案,解决了所有问题。以上是关于Terraform:在同一类型上同时使用数据源和资源有啥意义?的主要内容,如果未能解决你的问题,请参考以下文章
在同一个 TF 脚本中使用多个 Terraform 提供程序(GCP 和 Kubernetes)创建资源