Terraform 中如何使用数据源?

Posted

技术标签:

【中文标题】Terraform 中如何使用数据源?【英文标题】:How are data sources used in Terraform? 【发布时间】:2018-05-23 03:02:58 【问题描述】:

Terraform Data Sources documentation 告诉我什么是数据源,但我不太明白。有人可以给我一个数据源的用例吗?它和使用变量配置有什么区别?

【问题讨论】:

好问题。直到第3天读了第3遍才看懂…… 【参考方案1】:

可以出于多种原因使用数据源;但他们的目标是做某事,然后给你数据

让我们以他们的documentation为例:

# Find the latest available AMI that is tagged with Component = web
data "aws_ami" "web" 
  filter 
    name   = "state"
    values = ["available"]
  

  filter 
    name   = "tag:Component"
    values = ["web"]
  

  most_recent = true

这使用aws_ami 数据源 - 这与资源不同!相反,它只会为您提供信息,而不是创建任何东西。这个示例将特别调用 describe-images AWS API 调用,传入一些指定的 --filter 选项,并返回一个您可以从中获取信息的对象 - 看看这些 attributes!

姓名 owner_id 说明 image_id

... 名单还在继续。如果我是这样的话,这真的很有用,比方说 - 总是想提取与某些标签匹配的最新 AMI,并保持启动配置是最新的。我可以使用此数据提供程序,而不必总是更新变量或对 ID 进行硬编码。

数据源也可以用于其他原因;我的最爱之一是template provider。

祝你好运!

【讨论】:

嗨,谢谢 TJ。你的回答很清楚。我不明白为什么 terraform 没有以您的方式解释什么是数据源。 :-) 另外一个问题可能与数据源相关,也可能与数据源无关:我在现有的 AWS 云(手动创建)中创建了一些新服务(使用 terraform)。现在,我在我的服务资源中指明了现有云的 id(子网、角色、vpc id 等),例如subnet_id = "$var.subnet_private1_id",我在 terraform.tfvars 中将 subnet_private1_id 设置为实际的子网 id 将来我会将我的 terraform 代码运行到另一个 AWS 云。然后我与当前云相关的所有 id 都将被重新配置。我应该将当前云的所有相关 id 设置为变量,还是应该使用数据源? 你要使用terraform import T J Biddle:我不需要改变现有的东西,我只需要基于现有的云创建新的东西,所以我不需要导入。见***.com/questions/47665428/… Gotchya - 我真的建议您尝试将尽可能多的基础设施放入代码中;这将使事情变得更容易。【参考方案2】:

数据源提供有关当前 Terraform 配置未管理的实体的信息

这可能包括:

来自 Consul 的配置数据 有关手动配置的基础架构组件状态的信息

换句话说,数据源是只读视图,可以查看我们配置外部预先存在的组件的状态。

定义数据源后,您可以在 Terraform 配置中的其他位置使用数据。

例如,假设我们要为新的 AWS EC2 实例创建 Terraform 配置。我们希望使用由 Jenkins 作业使用 AWS CLI 创建和上传的 AMI 图像,而不是由 Terraform 管理。作为 Jenkins 作业配置的一部分,此 AMI 映像的名称将始终具有前缀 app-

在这种情况下,我们可以使用aws_ami data source 来获取有关名称前缀为app- 的最新AMI 映像的信息。

data "aws_ami" "app_ami" 
  most_recent = true
  filter 
    name   = "name"
    values = ["app-*"]
  

数据源导出属性,就像资源一样。我们可以使用语法data.TYPE.NAME.ATTR 插入这些属性。在我们的示例中,我们可以将 AMI ID 的值插入为data.aws_ami.app_ami.id,并将其作为ami 参数传递给aws_instance resource。

resource "aws_instance" "app" 
  ami           = "$data.aws_ami.app_ami.id"
  instance_type = "t2.micro"


在检索有关动态实体的信息时,数据源最强大 - 那些属性值经常更改的实体。例如,下次 Terraform 为我们的 aws_ami 数据源提取数据时,导出的属性的值可能不同(我们可能已经构建并推送了一个新的 AMI)。

变量用于静态值,那些很少改变的值,例如你的访问和密钥,或者你的服务器的标准 sudoer 列表。

【讨论】:

谢谢 d4nyll。换句话说,1)数据源是提供现有基础设施的信息,而不是创建新服务。 2) 它会根据您的过滤逻辑检索动态实体。 1) 是的! 2)每个数据源不同。对于aws_ami数据源,因为它实际上在后面调用了describe-images CLI命令,并且支持过滤。对于其他数据源,可能没有过滤。每个数据源的配置特定于该数据源和提供者。 哦。很高兴知道。再次感谢@d4nyll 嗨@d4nill,感谢您的解释。 archive_file 数据源怎么样?使用它时会创建一个新文件,而不仅仅是“读取”某些内容。那为什么他们认为这是一个数据源呢? @Averell 这是一个我以前没有使用过的数据源,它看起来确实违反了规范。如果您发现任何其他示例,请告诉我,我将更新我的答案。我想描述数据源的一种更准确的方法是它们获取现有资源的状态并将其合并为 Terraform 状态的一部分。 archive_file的现有资源是一个文件或文件目录,看起来整个文件内容都存储在状态中。【参考方案3】:

数据源用于从provider端获取数据,这样就可以在.tf文件中作为配置使用,而不是硬编码。示例:以下代码获取 AWS AMI ID 并使用它来启动 AWS 实例。

data "aws_ami" "std_ami" 
  most_recent = true
  owners      = ["amazon"]

filter 
    name   = "root-device-type"
    values = ["ebs"]
  

filter 
    name   = "virtualization-type"
    values = ["hvm"]
  


resource "aws_instance" "myec2" 
  ami           = data.aws_ami.std_ami.id
  instance_type = "t2.micro"

【讨论】:

【参考方案4】:

上面有很好的例子!

Terraform 数据源、资源和变量的主要区别是:

资源:在我们的平台上提供资源/基础设施。创建、更新和删除!

变量在我们的 IAC 上提供预定义值作为变量。由资源用于配置。

数据源:从我们的基础设施/供应商获取值,并为我们的资源提供数据以供应基础设施/资源。

上面的例子解释得很好:)

【讨论】:

以上是关于Terraform 中如何使用数据源?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 terraform 中使用新引入的 aws_cloudfront_cache_policy 资源

如何使用 terraform 生成 yml 配置文件

如何以与云无关的方式使用 Terraform

terraform如何创建数据盘

Terraform - 如何将列表转换为地图(如何使用 terraform 获取 AMI 标签)

如何使用服务托管标识在 Azure 中使用 Terraform 预配资源