arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 15

简体中文 (Simplified Chinese)

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Terragrunt

使用 Terraform 的大型基础设施

来源: https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/large-terraformarrow-up-right

此示例包含的代码作为为大型基础设施构建 Terraform 配置的示例,该基础设施使用:

  • 2个AWS账户

  • 2个地区

  • 2 个独立的环境(prod 和 stage 什么都不共享)。 每个环境都位于一个单独的 AWS 账户中,并跨越 2 个区域之间的资源

  • 每个环境都使用来自 的不同版本的现成基础设施模块 (alb)

  • 每个环境都使用相同版本的内部模块modules/network,因为它来自本地目录

circle-info

在此处描述的大型项目中,使用 Terragrunt 的好处变得非常明显。请参阅。

circle-check
  • 非常适合基础设施在逻辑上分离的项目(单独的 AWS 账户)

  • 适合不需要修改 AWS 账户之间共享的资源(一个环境 = 一个 AWS 账户 = 一个状态文件)

circle-exclamation

随着项目的增长,让这些环境彼此保持最新状态将变得更加困难。 考虑使用基础设施模块(现成的或内部的)来完成可重复的任务。

hashtag

核心概念

Terraform 官方文档详细阐述了 。请仔细阅读以便理解本节的其余部分。

本节内容将介绍本书中所使用的核心概念。

hashtag
资源 (Resource)

类似aws_vpc, aws_db_instance

代码结构示例

hashtag
Terraform 代码结构

circle-info

这些示例显示的是 AWS 提供商,但示例中显示的大部分原则可以应用于其他公共云提供商以及其他类型的提供商(DNS、DB、监控等)。

使用 Terraform 的中型基础设施

来源:

此示例包含的代码作为为中型基础设施构建 Terraform 配置的示例,该基础设施使用:

  • 2个AWS账户

  • 2 个独立的环境 (prod 和 stage

适合不需要编排环境之间的变化
  • 适合基础设施资源因环境而异且无法一概而论时(例如,在一个环境或某些地区缺少某些资源)

  • Terraform Registryarrow-up-right
    Code Structures examples with Terragrunt
    什么都不共享),每个环境都位于一个单独的 AWS 账户中
  • 每个环境都使用来自 Terraform Registryarrow-up-right 的不同版本的现成基础设施模块 (alb)

  • 每个环境都使用相同版本的内部模块modules/network,因为它来自本地目录

  • circle-check
    • 非常适合基础设施在逻辑上分离的项目(单独的 AWS 账户)

    • 适合不需要修改 AWS 账户之间共享的资源(一个环境 = 一个 AWS 账户 = 一个状态文件)

    • 适合不需要编排环境之间的变化

    • 适合基础设施资源因环境而异且无法一概而论时(例如,在一个环境或某些地区缺少某些资源)

    circle-exclamation

    随着项目的增长,让这些环境彼此保持最新状态将变得更加困难。考虑使用基础设施模块(现成的或内部的)来完成可重复的任务。

    hashtag

    https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/medium-terraformarrow-up-right
    这样的都统称为资源。单个的资源一定属于某个提供商(Provider),它接受参数,输出属性,并且有一个生命周期。资源可以被创建、检索、更新和删除。

    hashtag
    资源模块 (Resource module)

    资源模块是一组连接的资源,它们共同执行通用操作(例如,AWS VPC Terraform modulearrow-up-right 创建VPC、子网、NAT网关等)。它依赖于提供商配置,该配置可以在其中定义,或在更高级别的结构(如在基础设施模块)中定义。

    hashtag
    基础设施模块 (Infrastructure module)

    基础设施模块是一组资源模块的集合,这些资源模块在逻辑上可能没有连接,但在当前的情况/项目/设置中具有相同的目的。它定义了提供商的配置,这些配置传递给下游资源模块和资源。通常,它的范围限定在每个逻辑分隔符(例如,AWS区域、Google项目)的一个实体中。

    例如,terraform-aws-atlantisarrow-up-right 模块使用像 terraform-aws-vpcarrow-up-right 和 terraform-aws-security-grouparrow-up-right 这样的资源模块来管理在 AWS Fargatearrow-up-right 上运行 Atlantisarrow-up-right 所需的基础设施。

    另一个例子是 terraform-aws-cloudqueryarrow-up-right 模块,其中使用 terraform-aws-modulesarrow-up-right 的多个模块一起管理基础设施,并使用Docker资源来构建、推送和部署Docker镜像。所有这些都在一个集合中。

    hashtag
    组合 (Composition)

    组合是由跨越多个逻辑分隔区域(例如,AWS区域、多个AWS账户)的基础设施模块组成的集合。组合用于描述整个组织或项目所需的完整基础设施。

    组合由基础设施模块组成,这些基础设施模块又由资源模块组成,这些资源模块实现各个资源。

    简单的基础设施组合

    hashtag
    数据源 (Data source)

    数据源执行只读操作并依赖于提供商的配置,它用于资源模块和基础设施模块。

    数据源terraform_remote_state作为高级模块和组合的粘合剂。

    外部数据源arrow-up-right允许外部程序充当数据源,并公开任意数据以供 Terraform 配置中的其他地方使用。这里有一个来自terraform-aws-lambdaarrow-up-right 模块的示例,其中文件名通过调用外部Python脚本计算。

    httparrow-up-right 数据源向给定的URL发出HTTP GET请求,并导出有关响应的信息,这对于从不存在本机 Terraform 提供商的端点获取信息通常很有用。

    hashtag
    远程状态 (Remote state)

    基础设施模块和组合应该将它们的 Terraform statearrow-up-right 保存在远程位置,以便可以以可控的方式被他人检索(例如指定ACL、版本控制和日志记录)。

    hashtag
    提供商 (Provider),配置器 (provisioner)和其他

    提供商、配置器等术语在官方文档中已经有很好的描述,因此在这里重复没有意义。我认为,它们与编写良好的Terraform模块关系不大。

    hashtag
    为何如此复杂?

    虽然单个资源就像基础设施中的原子一样,但资源模块是分子。模块是最小的可版本化和可共享的单位。它具有精确的参数列表,为这样一个单元实现基本逻辑来完成所需的功能。例如,terraform-aws-security-grouparrow-up-right 模块可以根据输入创建aws_security_group和aws_security_group_rule资源。这个资源模块本身可以与其他模块一起使用来创建基础设施模块。

    使用模块的输出和数据源执行跨分子(资源模块和基础设施模块)的数据访问。

    组合之间的访问通常使用远程状态数据源来执行。 有多种方法可以在配置之间共享数据arrow-up-right。

    当把上面描述的概念放在伪关系中时,它可能看起来像这样:

    配置的方方面面arrow-up-right
    Type 类型
    Description 描述
    Readiness 准备

    很少资源,没有外部依赖。 单个 AWS 账户。 单一区域。 单一环境。

    Yes

    多个 AWS 账户和环境,使用 Terraform 的现成基础设施模块。

    Yes

    许多 AWS 账户,许多地区,迫切需要减少复制粘贴、自定义基础设施模块、大量使用组合。 使用Terraform。

    WIP 生产中

    very-large

    多个提供商(AWS、GCP、Azure)。 多云部署。 使用Terraform。

    No

    hashtag
    Terragrunt 代码结构

    Type 类型
    Description 描述
    Readiness 准备

    medium

    多个 AWS 账户和环境,现成的基础设施模块,使用 Terragrunt 的组合模式。

    No

    large

    许多 AWS 账户,许多地区,迫切需要减少复制粘贴、自定义基础设施模块、大量使用组合。 使用 Terragrunt。

    No

    very-large

    多个提供商(AWS、GCP、Azure)。 多云部署。 使用 Terragrunt。

    No

    欢迎阅读

    本文档旨在系统性描述使用 Terraform 的最佳实践,并为 Terraform 用户遇到的最常见问题提供建议。

    Terraformarrow-up-right 是一款非常强大(如果不是现在最强大的)的工具,也是最常用的基础设施即代码管理工具之一。它使开发人员可以做很多事情,并且帮助开发人员轻松应对各种复杂实现或集成。

    本书中描述的一些信息可能并不像是最佳实践。为了帮助读者区分哪些是已经确立的最佳实践,哪些是个人偏好的最佳实践,我有时使用提示来提供一些上下文,并使用图标来指定与最佳实践相关的各个小节的成熟度水平。

    本书于2018年在阳光明媚的马德里开始编写,可在此处免费获取 - https://www.terraform-best-practices.com/arrow-up-right 。 经过若干年不断迭代更新,它包含了更多与Terraform 1.0相关的实际最佳实践。最终,本书应该包含大多数无可争议的最佳实践和对 Terraform 用户的建议。

    hashtag
    赞助商

    Please if you want to become a sponsor.

    hashtag
    其他语言版本

    若您有意参与本书翻译,请与我联系。

    hashtag
    贡献

    随着社区的日益成熟和新思路的不断实践和验证,我一直希望得到反馈并更新本书。 如果你对某些话题感兴趣,请,或者点赞您感兴趣的问题。如果您有补充内容并且想要贡献,请提交pull request(不必担心文字是否华丽)。

    hashtag
    作者

    本书在不同贡献者和翻译人员的协助下由 维护。

    hashtag
    版权

    本书使用Apache 2 License许可协议,具体请查看协议本身。

    本书作者和贡献者无法保证本书内容的有效性。 请确保您了解本书提供的信息是免费提供的,并且您与此内容或项目相关的任何人之间没有任何协议或合同。 作者和贡献者不承担任何一方因本内容中包含的、关联的或链接的信息的错误或遗漏而造成的任何损失、损害或中断的任何责任,无论此类错误或遗漏是由于疏忽、事故或任何其他原因造成的。

    版权所有 © 2018-2023 Anton Babenko。

    composition-1 {
      infrastructure-module-1 {
        data-source-1 => d1
    
        resource-module-1 {
          data-source-2 => d2
          resource-1 (d1, d2)
          resource-2 (d2)
        }
    
        resource-module-2 {
          data-source-3 => d3
          resource-3 (d1, d3)
          resource-4 (d3)
        }
      }
    
    }
    small
    medium
    large

    Terraform

    — Terraform Compliance Simplified. Make your Terraform modules compliance-ready.

    —

    contact mearrow-up-right
    العربية (Arabic)chevron-right
    Bosanski (Bosnian)chevron-right
    Português (Brazilian Portuguese)chevron-right
    Englishchevron-right
    Français (French)chevron-right
    ქართული (Georgian)chevron-right
    Deutsch (German)chevron-right
    ελληνικά (Greek)chevron-right
    עברית (Hebrew)chevron-right
    हिंदी (Hindi)chevron-right
    Bahasa Indonesia (Indonesian)chevron-right
    Italiano (Italian)chevron-right
    日本語 (Japanese)chevron-right
    ಕನ್ನಡ (Kannada)chevron-right
    한국어 (Korean)chevron-right
    Polski (Polish)chevron-right
    Română (Romanian)chevron-right
    Español (Spanish)chevron-right
    Türkçe (Turkish)chevron-right
    Українська (Ukrainian)chevron-right
    اردو (Urdu)chevron-right
    开启新问题arrow-up-right
    Anton Babenkoarrow-up-right
    arrow-up-right
    Compliance.tfarrow-up-right

    工作坊

    还有一个研讨会,供想要练习本指南中描述的某些内容的人使用。

    内容在这里 - https://github.com/antonbabenko/terraform-best-practices-workshoparrow-up-right

    代码结构

    有关Terraform代码结构的问题是社区中迄今为止最常见的问题。 每个人都在某个时候考虑过项目的最佳代码结构。

    hashtag
    我应该如何构建我的 Terraform 配置?

    这是一个有很多解决方案的问题之一,很难给出通用的建议,所以让我们从理解我们正在处理什么开始。

    • 你的项目有多复杂?

      • 相关resources(资源)数量

      • Terraform 提供商的数量(参见下面关于“逻辑提供者”的注释)

    • 你的基础架构多久更改一次?

      • 从每月/每周/每天一次

      • 到连续(每次有新提交时)

    • 代码更改发起者? 当一个新的artifact(构件)生成时,是否让 CI 服务器更新存储库?

      • 只有开发人员可以推送到基础架构存储库

      • 每个人都可以通过打开 PR(包括在 CI 服务器上运行的自动化任务)来提出对任何事物的更改

    • 你使用哪种部署平台或部署服务?

      • AWS CodeDeploy、Kubernetes 或 OpenShift 需要稍微不同的方法

    • 环境如何分组?

      • 按环境、地区、项目

    circle-info

    Logical providers(逻辑提供商)完全在 Terraform 的逻辑中工作,并且通常不与任何其他服务交互,因此我们可以将它们的复杂性视为 O(1)。 最常见的逻辑提供商包括 , , , , .

    hashtag
    开始了解 Terraform 配置的结构

    当开始或编写示例代码时,将所有代码放在 main.tf中是一个好主意。 在所有其他情况下,最好将多个文件按逻辑拆分,如下所示:

    • main.tf - 调用modules(模块)、locals(本地)和data sources(数据源)来创建所有资源

    • variables.tf - 包含在main.tf 中使用的变量声明

    terraform.tfvars 不应在除(组合)之外的任何地方使用。

    hashtag
    如何考虑 Terraform 配置结构?

    circle-info

    请确保您了解核心概念 - (资源模块),(基础设施模块),和 (组合), 因为它们在以下示例中使用。

    hashtag
    结构化代码的常见建议

    • 使用更少的资源可以更轻松、更快速地进行工作

      • terraform plan 和 terraform apply 都调用 cloud API 来验证资源状态

    在本书中,示例项目按复杂性分组 —— 从小型到超大型基础设施。这种分离并不严格,因此还要检查其他结构。

    hashtag
    基础架构模块和组合的编排

    拥有小型基础设施意味着存在少量依赖项和资源。 随着项目的增长,链接 Terraform 配置的执行、连接不同的基础设施模块以及在组合中传递值的需求变得显而易见。

    开发人员使用的编排解决方案至少有5个不同的群体:

    1. 仅限Terraform。 非常简单,开发人员只需了解 Terraform 即可完成工作。

    2. Terragrunt。 纯编排工具,可用于编排整个基础架构以及处理依赖项。 Terragrunt 原生地操作基础设施模块和组合,因此它减少了代码重复。

    3. In-house scripts(内部脚本)。 通常,这发生在编排的起点和发现 Terragrunt 之前。

    考虑到这一点,本书回顾了这些项目结构中的前两个,即仅使用Terraform和Terragrunt。

    请参阅下一章中 或 的代码结构示例。

    问答 (FAQ)

    FTP (Frequent Terraform Problems)

    hashtag
    我应该注意并考虑使用哪些工具?

    • - 编排工具(Orchestration tool)

    编写Terraform配置

    hashtag
    使用 locals 指定资源之间的显式依赖关系

    这是一种有用的方法,可以向Terraform提供提示,即使在Terraform配置中没有直接依赖关系,某些资源也应该在其它资源之前被删除。

    使用 Terraform 的小型基础设施

    来源:

    此示例包含的代码作为为小型基础设施构建 Terraform 配置的示例,其中不使用外部依赖项。

    circle-check
    • 非常适合入门和按需重构

    参考资源

    circle-info

    有很多人创建了很棒的内容并管理了与 Terraform 社区相关的开源项目,但我想不出最好的结构来在不复制像 这样的列表的情况下列出这些链接。

    - 非常积极地使用 Terraform 并且可以告诉你很多(如果你问他们的话)的人的名单。

    - HashiCorp 的 Terraform 上精选的资源列表。

    - Anton Babenko 的YouTube 频道“Your Weekly Dose of Terraform”,包含评论、采访、问答、实时编码和一些使用 Terraform 的黑客技术的直播。

    outputs.tf - 包含在 main.tf中创建的资源的输出
  • versions.tf - 包含 Terraform 和提供商的版本要求

  • 如果你的整个基础设施都在一个组合中,这可能需要一些时间
  • 资源越少,爆炸半径(A blast radius)就越小

    • 通过将不相关的资源放置在单独的组合中以进行隔离,可以降低如果出现问题时的风险

  • 使用远程状态启动您的项目,因为:

    • 你的笔记本电脑不是基础设施代码真实来源的合适位置

    • 在 git 中管理tfstate文件是一场噩梦

    • 当基础设施层开始朝多个方向(依赖项或资源数量)增长时,将更容易控制事物

  • 实践一致的结构和 naming convention(命名约定):

    • 与procedural code(过程式代码)一样,Terraform 代码应该首先编写供人们阅读。当六个月后发生变化时,一致性将有所帮助

    • 可以在 Terraform 状态文件中移动资源,但如果结构和命名不一致,则可能更难做到

  • 保持资源模块尽可能简单

  • 不要将可以作为变量传递或使用数据源(data sources)发现的值硬编码

  • 专门使用data sources(数据源)和terraform_remote_state 作为composition(组合)中基础设施模块之间的粘合剂

  • Ansible 或类似的通用自动化工具。通常在 Ansible 之后采用 Terraform 时使用,或者在积极使用 Ansible UI 时使用。
  • Crossplanearrow-up-right 和其他受 Kubernetes 启发的解决方案。有时,利用 Kubernetes 生态系统并采用reconciliation loop(协调循环)功能来实现 Terraform 配置的所需状态是有意义的。 观看视频Crossplane vs Terraformarrow-up-right了解更多信息。

  • randomarrow-up-right
    localarrow-up-right
    terraformarrow-up-right
    nullarrow-up-right
    timearrow-up-right
    composition
    resource module
    infrastructure module
    composition
    Terraform
    Terragrunt
    tflintarrow-up-right - 代码检查器(Code linter)
  • tfenvarrow-up-right - 版本管理器(Version manager)

  • Atlantisarrow-up-right - 拉取请求自动化(Pull Request automation)

  • pre-commit-terraformarrow-up-right - 用于预提交框架 pre-commit frameworkarrow-up-right Terraform 的 git 钩子集合

  • Infracostarrow-up-right - 拉取请求中 Terraform 的云成本估算。 也适用于 Terragrunt、Atlantis 和 pre-commit-terraform。

  • hashtag
    模块dependency hellarrow-up-right(依赖地狱)解决方案是什么?

    应指定资源和基础设施模块的版本。 提供商应该在模块之外配置,但只能在组合中配置。 提供商和 Terraform 的版本也可以被锁定。

    没有主要的依赖管理工具,但有一些技巧可以减少依赖地狱的问题。 例如,Dependabotarrow-up-right 可用于自动化依赖更新。 Dependabot 创建拉取请求以确保您的依赖关系安全和最新。 Dependabot 支持 Terraform 配置。

    Terragruntarrow-up-right

    非常适合小型资源模块

  • 适用于小型和线性基础设施模块(例如,terraform-aws-atlantisarrow-up-right)

  • 适用于少量资源(少于 20-30)

  • circle-exclamation

    如果资源数量不断增加,所有资源的单一状态文件会使使用 Terraform 的过程变慢(考虑使用参数 -target 来限制资源数量)

    https://github.com/antonbabenko/terraform-best-practices/tree/master/examples/small-terraformarrow-up-right
    https://weekly.tfarrow-up-right - Terraform 每周时事通讯。 Terraform 世界中的各种新闻(项目、公告、讨论),由 Anton Babenko 撰写。
    awesome-terraformarrow-up-right
    https://twitter.com/antonbabenko/lists/terraform-expertsarrow-up-right
    https://github.com/shuaibiyy/awesome-terraformarrow-up-right
    http://bit.ly/terraform-youtubearrow-up-right
    hashtag
    Terraform 0.12 - 必需参数与可选参数
    1. 如果var.website不是一个空的map,则必须设置必需参数 index_document。

    2. 可选参数error_document可以省略。

    https://raw.githubusercontent.com/antonbabenko/terraform-best-practices/master/snippets/locals.tfarrow-up-right
    main.tf
    variable "website" {
      type    = map(string)
      default = {}
    }
    
    resource "aws_s3_bucket" "this" {
      # omitted...
    
      dynamic "website" {
        for_each = length(keys(var.website)) == 0 ? [] : [var.website]
    
        content {
          index_document = website.value.index_document
          error_document = lookup(website.value, "error_document", null)
        }
      }
    }
    terraform.tfvars
    website = {
      index_document = "index.html"
    }

    代码风格

    circle-info
    • 示例和 Terraform 模块应包含说明功能及其使用方法的文档。

    • README.md 文件中的所有链接都应该是绝对链接,以使 Terraform Registry 网站正确显示它们。

    • 文档可能包括使用创建的图表和使用创建的蓝图。

    • 使用 确保代码有效、格式正确并自动记录,然后再推送到 git 并由人工审查。

    hashtag
    Documentation(文档)

    hashtag
    自动生成的文档

    是一个用于管理和维护多语言预提交挂钩的框架。它是用 Python 编写的,是一个强大的工具,可以在代码提交到 git 存储库之前在开发人员的机器上自动执行某些操作。通常,它用于运行 linters 和格式化代码(参见)。

    通过 Terraform 配置,pre-commit可用于格式化和验证代码,以及更新文档。

    查看 以熟悉它,以及已经使用它的现有存储库(例如, )。

    hashtag
    terraform-docs

    是一种工具,可以从 Terraform 模块以各种输出格式完成文档的生成。你可以手动运行它(没有预提交挂钩),或使用 来自动更新文档。

    @todo:记录模块版本、发布、GH actions

    hashtag
    参考资源

    1. 预提交框架主页:

    2. 用于预提交框架的Terraform 的 git 钩子集合:

    3. 的博客文章:

    mermaidarrow-up-right
    cloudcraft.coarrow-up-right
    Terraform pre-commit hooksarrow-up-right
    pre-commitarrow-up-right
    supported hooksarrow-up-right
    pre-commit-terraform repositoryarrow-up-right
    terraform-aws-vpcarrow-up-right
    terraform-docsarrow-up-right
    pre-commit-terraform hooksarrow-up-right
    pre-commit framework homepagearrow-up-right
    Collection of git hooks for Terraform to be used with pre-commit frameworkarrow-up-right
    Dean Wilsonarrow-up-right
    pre-commit hooks and terraform - a safety net for your repositoriesarrow-up-right

    命名约定

    hashtag
    一般约定

    circle-info

    至少应该没有理由不遵循这些约定 :)

    circle-info

    请注意,实际的云资源通常对允许的名称有限制。 例如,有些资源不能包含破折号,有些资源必须采用驼峰式大小写。 本书中的约定指的是 Terraform 名称本身。

    1. 在任何地方(资源名称、数据源名称、变量名称、输出等)使用 _ (下划线) 而不是 - (破折号)。

    2. 非常适合使用小写字母和数字(即使支持 UTF-8)。

    hashtag
    资源和数据源参数

    1. 不要在资源名称中重复资源类型(既不要部分,更不要完全):

      circle-check

      resource "aws_route_table" "public" {}

      triangle-exclamation

    hashtag
    resource(资源)代码示例

    hashtag
    count / for_each的使用

    circle-check
    triangle-exclamation

    hashtag
    tags(标签)的放置

    circle-check
    triangle-exclamation

    hashtag
    count(计数)条件

    circle-check

    hashtag
    Variables(变量)

    1. 不要在资源模块中重新造轮子:使用你正在使用的资源的“参数参考”部分中定义的变量 name,description和 default。

    2. 对变量验证的支持相当有限(例如,无法访问其他变量或进行查找)。 相应地计划,因为在许多情况下此功能是无用的。

    3. 当type是list(...)

    hashtag
    Outputs(输出)

    使输出在其范围之外保持一致且易于理解(当用户使用模块时,它返回的值的类型和属性应该很明显)。

    1. 输出的名称应该描述它包含的属性,并且不像你通常想要的那样自由。

    2. 输出名称的良好结构类似于{name}_{type}_{attribute},其中:

      1. {name}

    hashtag
    output(输出)代码示例

    最多返回一个安全组ID:

    circle-check

    当有多个相同类型的资源时,this 在输出名称中应省略:

    triangle-exclamation

    hashtag
    如果返回值是列表,则使用复数名称

    circle-check

    resource "aws_route_table" "public_route_table" {}
    triangle-exclamation

    resource "aws_route_table" "public_aws_route_table" {}

  • 如果没有更多的描述性和通用名称可用,或者如果资源模块创建这种类型的单个资源,资源名称应该被命名为this(例如,在 中有一个类型为 aws_nat_gateway的资源和多个类型为aws_route_table的资源,所以 aws_nat_gateway 应该命名为this,并且aws_route_table 应该有更具描述性的名称——比如private, public, database)。

  • 始终使用单数名词作为名称。

  • 在参数值内部和值将显示给人类的地方,使用-(例如,在 RDS 实例的 DNS 名称内部)。

  • 将参数count / for_each 包含在资源或数据源块中作为顶部的第一个参数,并在其后用换行符分隔。

  • 包括参数tags,如果资源支持,作为最后一个真正的参数,如果需要,后面是 depends_on和lifecycle。所有这些都应该用一个空行分隔。

  • 在参数count / for_each中使用条件时,首选布尔值而不是使用 length或其他表达式。

  • 或
    map(...)
    ,在变量名中使用复数形式。
  • 在变量块中排序键,比如:description,type,default,validation。

  • 始终包括对所有变量的description,即使你认为它很明显(将来你会需要它)。

  • 优先使用简单类型(number,string,list(...),map(...), any) 而不是像object()这样的特定类型,除非您需要对每个键都有严格的约束。

  • 如果map的所有元素都具有相同的类型(例如string)或可以转换为它(例如number类型可以转换为string),则使用特定类型,如map(map(string))。

  • 使用类型any来禁用从某个深度开始或者在支持多个类型时的类型验证。

  • 值{}有时是一个map,有时是一个对象。使用tomap(...) 制作map,因为没有办法制作对象。

  • 是没有提供者前缀的资源或数据源名称。
    aws_subnet
    的
    {name}是subnet
    ,
    aws_vpc
    的
    {name}
    是
    vpc
  • {type} 是一种资源来源

  • {attribute}是输出返回的属性

  • 参见示例 .

  • 如果输出返回一个带有插值函数和多个资源的值,{name} 和 {type} 应该尽可能通用(this 作为前缀应该省略), 参见示例 。

  • 如果返回值是一个列表,它应该有一个复数名称。 参见示例 。

  • 始终包括所有输出的description,即使你认为它很明显。

  • 避免设置sensitive参数, 除非您完全控制此输出在所有模块的所有位置的使用。

  • 更喜欢try()(自 Terraform 0.13 起可用)而不是 element(concat(...))(0.13 之前版本的旧方法)。

  • main.tf
    resource "aws_route_table" "public" {
      count = 2
    
      vpc_id = "vpc-12345678"
      # ... remaining arguments omitted
    }
    
    resource "aws_route_table" "private" {
      for_each = toset(["one", "two"])
    
      vpc_id = "vpc-12345678"
      # ... remaining arguments omitted
    }
    main.tf
    resource "aws_route_table" "public" {
      vpc_id = "vpc-12345678"
      count  = 2
    
      # ... remaining arguments omitted
    }
    main.tf
    resource "aws_nat_gateway" "this" {
      count = 2
    
      allocation_id = "..."
      subnet_id     = "..."
    
      tags = {
        Name = "..."
      }
    
      depends_on = [aws_internet_gateway.this]
    
      lifecycle {
        create_before_destroy = true
      }
    }   
    main.tf
    resource "aws_nat_gateway" "this" {
      count = 2
    
      tags = "..."
    
      depends_on = [aws_internet_gateway.this]
    
      lifecycle {
        create_before_destroy = true
      }
    
      allocation_id = "..."
      subnet_id     = "..."
    }
    outputs.tf
    resource "aws_nat_gateway" "that" {    # Best
      count = var.create_public_subnets ? 1 : 0
    }
    
    resource "aws_nat_gateway" "this" {    # Good
      count = length(var.public_subnets) > 0 ? 1 : 0
    }
    outputs.tf
    output "security_group_id" {
      description = "The ID of the security group"
      value       = try(aws_security_group.this[0].id, aws_security_group.name_prefix[0].id, "")
    }
    outputs.tf
    output "this_security_group_id" {
      description = "The ID of the security group"
      value       = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [""]), 0)
    }
    outputs.tf
    output "rds_cluster_instance_endpoints" {
      description = "A list of all cluster instance endpoints"
      value       = aws_rds_cluster_instance.this.*.endpoint
    }
    AWS VPC modulearrow-up-right
    See examples
    See example
    See example