Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Terraform 官方文档详细阐述了 配置的方方面面。请仔细阅读以便理解本节的其余部分。
本节内容将介绍本书中所使用的核心概念。
类似aws_vpc
, aws_db_instance
这样的都统称为资源。单个的资源一定属于某个提供商(Provider),它接受参数,输出属性,并且有一个生命周期。资源可以被创建、检索、更新和删除。
资源模块是一组连接的资源,它们共同执行通用操作(例如,AWS VPC Terraform module 创建VPC、子网、NAT网关等)。它依赖于提供商配置,该配置可以在其中定义,或在更高级别的结构(如在基础设施模块)中定义。
基础设施模块是一组资源模块的集合,这些资源模块在逻辑上可能没有连接,但在当前的情况/项目/设置中具有相同的目的。它定义了提供商的配置,这些配置传递给下游资源模块和资源。通常,它的范围限定在每个逻辑分隔符(例如,AWS区域、Google项目)的一个实体中。
例如,terraform-aws-atlantis 模块使用像 terraform-aws-vpc 和 terraform-aws-security-group 这样的资源模块来管理在 AWS Fargate 上运行 Atlantis 所需的基础设施。
另一个例子是 terraform-aws-cloudquery 模块,其中使用 terraform-aws-modules 的多个模块一起管理基础设施,并使用Docker资源来构建、推送和部署Docker镜像。所有这些都在一个集合中。
组合是由跨越多个逻辑分隔区域(例如,AWS区域、多个AWS账户)的基础设施模块组成的集合。组合用于描述整个组织或项目所需的完整基础设施。
组合由基础设施模块组成,这些基础设施模块又由资源模块组成,这些资源模块实现各个资源。
数据源执行只读操作并依赖于提供商的配置,它用于资源模块和基础设施模块。
数据源terraform_remote_state
作为高级模块和组合的粘合剂。
外部数据源允许外部程序充当数据源,并公开任意数据以供 Terraform 配置中的其他地方使用。这里有一个来自terraform-aws-lambda 模块的示例,其中文件名通过调用外部Python脚本计算。
http 数据源向给定的URL发出HTTP GET请求,并导出有关响应的信息,这对于从不存在本机 Terraform 提供商的端点获取信息通常很有用。
基础设施模块和组合应该将它们的 Terraform state 保存在远程位置,以便可以以可控的方式被他人检索(例如指定ACL、版本控制和日志记录)。
提供商、配置器等术语在官方文档中已经有很好的描述,因此在这里重复没有意义。我认为,它们与编写良好的Terraform模块关系不大。
虽然单个资源就像基础设施中的原子一样,但资源模块是分子。模块是最小的可版本化和可共享的单位。它具有精确的参数列表,为这样一个单元实现基本逻辑来完成所需的功能。例如,terraform-aws-security-group 模块可以根据输入创建aws_security_group
和aws_security_group_rule
资源。这个资源模块本身可以与其他模块一起使用来创建基础设施模块。
使用模块的输出和数据源执行跨分子(资源模块和基础设施模块)的数据访问。
组合之间的访问通常使用远程状态数据源来执行。 有多种方法可以在配置之间共享数据。
当把上面描述的概念放在伪关系中时,它可能看起来像这样:
本文档旨在系统性描述使用 Terraform 的最佳实践,并为 Terraform 用户遇到的最常见问题提供建议。
本书中描述的一些信息可能并不像是最佳实践。为了帮助读者区分哪些是已经确立的最佳实践,哪些是个人偏好的最佳实践,我有时使用提示来提供一些上下文,并使用图标来指定与最佳实践相关的各个小节的成熟度水平。
若您有意参与本书翻译,请与我联系。
本书使用Apache 2 License许可协议,具体请查看协议本身。
本书作者和贡献者无法保证本书内容的有效性。 请确保您了解本书提供的信息是免费提供的,并且您与此内容或项目相关的任何人之间没有任何协议或合同。 作者和贡献者不承担任何一方因本内容中包含的、关联的或链接的信息的错误或遗漏而造成的任何损失、损害或中断的任何责任,无论此类错误或遗漏是由于疏忽、事故或任何其他原因造成的。
版权所有 © 2018-2023 Anton Babenko。
有关Terraform代码结构的问题是社区中迄今为止最常见的问题。 每个人都在某个时候考虑过项目的最佳代码结构。
这是一个有很多解决方案的问题之一,很难给出通用的建议,所以让我们从理解我们正在处理什么开始。
你的项目有多复杂?
相关resources(资源)数量
Terraform 提供商的数量(参见下面关于“逻辑提供者”的注释)
你的基础架构多久更改一次?
从每月/每周/每天一次
到连续(每次有新提交时)
代码更改发起者? 当一个新的artifact(构件)生成时,是否让 CI 服务器更新存储库?
只有开发人员可以推送到基础架构存储库
每个人都可以通过打开 PR(包括在 CI 服务器上运行的自动化任务)来提出对任何事物的更改
你使用哪种部署平台或部署服务?
AWS CodeDeploy、Kubernetes 或 OpenShift 需要稍微不同的方法
环境如何分组?
按环境、地区、项目
当开始或编写示例代码时,将所有代码放在 main.tf
中是一个好主意。 在所有其他情况下,最好将多个文件按逻辑拆分,如下所示:
main.tf
- 调用modules(模块)、locals(本地)和data sources(数据源)来创建所有资源
variables.tf
- 包含在main.tf
中使用的变量声明
outputs.tf
- 包含在 main.tf
中创建的资源的输出
versions.tf
- 包含 Terraform 和提供商的版本要求
使用更少的资源可以更轻松、更快速地进行工作
terraform plan
和 terraform apply
都调用 cloud API 来验证资源状态
如果你的整个基础设施都在一个组合中,这可能需要一些时间
资源越少,爆炸半径(A blast radius)就越小
通过将不相关的资源放置在单独的组合中以进行隔离,可以降低如果出现问题时的风险
使用远程状态启动您的项目,因为:
你的笔记本电脑不是基础设施代码真实来源的合适位置
在 git 中管理tfstate
文件是一场噩梦
当基础设施层开始朝多个方向(依赖项或资源数量)增长时,将更容易控制事物
与procedural code(过程式代码)一样,Terraform 代码应该首先编写供人们阅读。当六个月后发生变化时,一致性将有所帮助
可以在 Terraform 状态文件中移动资源,但如果结构和命名不一致,则可能更难做到
保持资源模块尽可能简单
不要将可以作为变量传递或使用数据源(data sources)发现的值硬编码
专门使用data sources(数据源)和terraform_remote_state
作为composition(组合)中基础设施模块之间的粘合剂
在本书中,示例项目按复杂性分组 —— 从小型到超大型基础设施。这种分离并不严格,因此还要检查其他结构。
拥有小型基础设施意味着存在少量依赖项和资源。 随着项目的增长,链接 Terraform 配置的执行、连接不同的基础设施模块以及在组合中传递值的需求变得显而易见。
开发人员使用的编排解决方案至少有5个不同的群体:
仅限Terraform。 非常简单,开发人员只需了解 Terraform 即可完成工作。
Terragrunt。 纯编排工具,可用于编排整个基础架构以及处理依赖项。 Terragrunt 原生地操作基础设施模块和组合,因此它减少了代码重复。
In-house scripts(内部脚本)。 通常,这发生在编排的起点和发现 Terragrunt 之前。
Ansible 或类似的通用自动化工具。通常在 Ansible 之后采用 Terraform 时使用,或者在积极使用 Ansible UI 时使用。
考虑到这一点,本书回顾了这些项目结构中的前两个,即仅使用Terraform和Terragrunt。
示例和 Terraform 模块应包含说明功能及其使用方法的文档。
README.md 文件中的所有链接都应该是绝对链接,以使 Terraform Registry 网站正确显示它们。